NumPy 2.x 完全指南【六】根据现有数据创建数组
文章目录
- 1. 概述
- 2. 创建数组
- 2.1 array
- 2.2 asarray
- 2.3 asanyarray
- 2.4 ascontiguousarray
- 2.5 asmatrix
- 2.6 astype
- 2.7 copy
- 2.8 loadtxt
- 2.9 fromXX
- 2.9.1 frombuffer
- 2.9.2 from_dlpack
- 2.9.3 fromfile
- 2.9.4 fromfunction
- 2.9.5 fromiter
- 2.9.6 fromstring
1. 概述
NumPy
提供了多种方式来创建数组,在官方文档中有详细介绍,这里先介绍一些常用的,后续再介绍其他不常用的方式。
根据现有数据创建数组是指将已有的数据(如列表、元组、其他数组、文件数据等)转换为 NumPy
数组,无需手动初始化或填充数据。
支持的函数:
array
asarray
asanyarray
ascontiguousarray
asmatrix
astype
copy
frombuffer
from_dlpack
fromfile
fromfunction
fromiter
fromstring
loadtxt
2. 创建数组
2.1 array
numpy.array
:从多种数据源(如列表、元组、其他数组等)创建数组,并允许精细控制数据类型、内存布局和维度。
函数定义:
numpy.array(object, # 输入数据 (列表/元组/数组等)dtype=None, # 指定数据类型*, # 后续参数必须作为关键字参数传递 copy=True, # 是否强制复制数据order='K', # 内存布局 ('C', 'F', 'A', 'K')subok=False, # 是否允许返回子类ndmin=0, # 最小维度数like=None # 兼容其他数组库的创建方式
)
参数说明:
参数名 | 类型/取值范围 | 必填 | 案例与解释 |
---|---|---|---|
object | array_like | 是 | 输入数据源:支持列表、元组、生成器等。 |
dtype | data-type | 否 | 数据类型控制:显式指定元素类型。 |
copy | bool | 否 | 内存复制策略:控制是否创建数据副本。 |
order | {‘K’,‘A’,‘C’,‘F’} | 否 | 内存布局优化:影响数组计算效率。 |
subok | bool | 否 | 子类保留:决定返回基类或子类对象。 |
ndmin | int | 否 | 维度扩展:强制数组达到最小维度。 |
like | array_like | 否 | 兼容性扩展:创建其他库的数组对象(需支持协议)。 |
示例 1 ,从 Python
序列创建各种数组:
import numpy as np# 列表
arr1 = np.array([1, 2, 3])
print(arr1) # 输出: [1 2 3]# 元组
arr2 = np.array((4, 5, 6))
print(arr2) # 输出: [4 5 6]# 生成器
generator = (x*2 for x in range(3))
arr3 = np.array(generator)
print(arr3) # 输出: [0 2 4]
示例 2 ,指定数据类型:
# 自动推断为int64
arr_default = np.array([1, 2, 3])
print(arr_default.dtype) # 输出: int64# 指定为float32
arr_float = np.array([1, 2, 3], dtype=np.float32)
print(arr_float) # 输出: [1. 2. 3.]
print(arr_float.dtype) # 输出: float32# 字符串转换
arr_str = np.array(['1.5', '2.3'], dtype=np.float64)
print(arr_str) # 输出: [1.5 2.3]
copy
参数有以下几种可配置值:
True
:强制复制,无论输入类型,始终创建独立数据副本False
:禁止复制,若输入无法直接引用(如列表/非连续数组),则抛出ValueError
None
:智能复制,仅在输入不符合目标要求(类型/布局)时复制
示例 3 ,控制内存复制:
original = [10, 20, 30]# 默认copy=True(创建新副本)
arr_copy = np.array(original, copy=True)
arr_copy[0] = 100
print(original) # 输出: [10, 20, 30](未改变)# copy=False(共享内存,若可能)
arr_nocopy = np.array(original, copy=False)
arr_nocopy[0] = 200
print(original) # 输出: [200, 20, 30](原数据被修改!)
示例 4 ,指定维度:
# 一维输入转为二维
arr_1d = np.array([1, 2, 3], ndmin=2)
print(arr_1d.shape) # 输出: (1, 3)# 二维输入强制为三维
arr_2d = np.array([[4,5],[6,7]], ndmin=3)
print(arr_2d.shape) # 输出: (1, 2, 2)
2.2 asarray
numpy.asarray
:和 array
一样,但是默认会遵循避免复制的设计原则。
函数定义:
asarray(a, dtype=None, order=None, *, device=None, copy=None, like=None)
参数区别:
asarray
多了一个device
参数,可以指定设备,但是目前仅支持cpu
,未来可能支持GPU/TPU
设备。- 少了
subok
参数,强制返回基类ndarray
对象,避免子类带来的意外行为。 - 少了
ndmin
参数,因为维度变化时,必须创建一个新数组,违背了asarray
的设计原则。 copy
参数的默认值。
最重要的一个区别是 array
中的 copy
默认值是 true
,表示默认复制数据,不管是参数是一般数组,还是 ndarray
类型的数组,最终都会复制原数据创建一个新的 ndarray
对象:
# 默认复制
original = np.array([10, 20])
arr2 = np.array(original)
print(np.shares_memory(original, arr2)) # False# 配置为不复制
original = np.array([10, 20])
arr2 = np.array(original, copy=False)
print(np.shares_memory(original, arr2)) # True
asarray
中 copy
参数的默认值是 None
(智能复制),输入为一般数组肯定还是创建新对象,但是输入为 ndarray
时,不会进行复制而是共享同一个内存,避免了对已有数组的冗余复制:
# 输入为 NumPy 数组时,不进行复制
original = np.array([10, 20])
# asarray
arr2 = np.asarray(original)
print(np.shares_memory(original, arr2)) # True
2.3 asanyarray
numpy.asanyarray
:和 asarray
的关键区别在于,当输入是 ndarray
的子类时,asanyarray
会保留子类,而 asarray
会强制转换为基类 ndarray
。
函数定义:
asanyarray(a, dtype=None, order=None, *, device=None, copy=None, like=None)
示例:
import numpy as np# 创建矩阵子类对象
m = np.matrix([[1, 2], [3, 4]])# 转换测试
arr_any = np.asanyarray(m) # 保留 matrix 类型
arr_as = np.asarray(m) # 转换为 ndarrayprint(type(arr_any)) # <class 'numpy.matrix'>
print(type(arr_as)) # <class 'numpy.ndarray'>
2.4 ascontiguousarray
numpy.ascontiguousarray
: 将输入的数组转换为 C
顺序(行优先)连续内存布局的数组,若输入数组已满足 C
连续条件,则直接返回原数组。
函数定义:
ascontiguousarray(a, dtype=None, *, like=None)
示例:
import numpy as np# 创建非连续数组(转置操作会导致内存不连续)
arr = np.array([[1, 2], [3, 4]], order='F') # Fortran顺序初始化的数组
print("原始数组是否C连续:", arr.flags.c_contiguous) # False# 转换为C连续数组
arr_contiguous = np.ascontiguousarray(arr)
print("转换后是否C连续:", arr_contiguous.flags.c_contiguous) # True
2.5 asmatrix
numpy.asmatrix
:将输入转换为矩阵(matrix
)对象,矩阵是线性代数中的概念,一般可以理解为二维数组,但是矩阵对象支持特定的数学运算符。
函数定义:
@set_module('numpy')
def asmatrix(data, dtype=None):
示例 1,基本转换:
import numpy as np# 将列表转换为矩阵
lst = [[1, 2], [3, 4]]
mat = np.asmatrix(lst)
print(mat)
# 输出:
# [[1 2]
# [3 4]]
print(type(mat)) # <class 'numpy.matrix'>
示例 2,一维输入自动转为二维:
arr_1d = np.array([1, 2, 3])
mat = np.asmatrix(arr_1d)
print(mat) # [[1 2 3]] (行向量)
print(mat.shape) # (1, 3)
示例 3 ,矩阵乘法:
a = np.asmatrix([[1, 2], [3, 4]])
b = np.asmatrix([[5, 6], [7, 8]])# 矩阵乘法
print(a * b)
# [[19 22]
# [43 50]]# 对比数组的逐元素乘法
arr_a = np.array([[1, 2], [3, 4]])
arr_b = np.array([[5, 6], [7, 8]])
print(arr_a * arr_b) # [[ 5 12]# [21 32]]
2.6 astype
numpy.astype
:将 NumPy
数组转换为指定的数据类型。
函数定义:
@array_function_dispatch(_astype_dispatcher)
def astype(x, dtype, /, *, copy=True, device=None):# (实现代码)
示例 1 ,整数 → 浮点数:
import numpy as nparr_int = np.array([1, 2, 3, 4], dtype=np.int32)
arr_float = arr_int.astype(np.float64)
print(arr_float) # 输出: [1.0, 2.0, 3.0, 4.0]
示例 2 ,浮点数 → 整数,会直接截断小数部分:
arr_float = np.array([1.9, 2.5, 3.1, 4.8])
arr_int = arr_float.astype(np.int32)
print(arr_int) # 输出: [1, 2, 3, 4]
说明:常用于图像像素值处理等需要离散化数据的场景。
示例 3 ,布尔值 ↔ 数值
# 非零转 True,零转 False
arr_num = np.array([0, 1, -2, 0])
arr_bool = arr_num.astype(bool)
print(arr_bool) # 输出: [False, True, True, False]# 布尔转整数(True→1,False→0)
arr_bool = np.array([True, False, True])
arr_int = arr_bool.astype(int)
print(arr_int) # 输出: [1, 0, 1]
示例 4 ,字符串 → 数值(需确保字符串内容为数字):
arr_str = np.array(["10", "20", "30"])
arr_int = arr_str.astype(np.int64)
print(arr_int) # 输出: [10, 20, 30]
2.7 copy
numpy.copy
:创建输入数组的副本,副本与原始数组在内存中完全独立,修改副本不会影响原数组。
注意事项:
np.copy(a)
等价于np.array(a, copy=True)
。- 对于对象数据类型(
object dtype
)使用浅拷贝机制 - 对数值型数组执行深拷贝(独立内存)
函数定义:
@array_function_dispatch(_copy_dispatcher)
def copy(a, order='K', subok=False):return array(a, order=order, subok=subok, copy=True)
示例,引用与拷贝的区别:
import numpy as np# 创建原始数组 x,引用 y 和拷贝 z
x = np.array([1, 2, 3])
y = x # y 是 x 的引用(共享内存)
z = np.copy(x) # z 是 x 的拷贝(独立内存)# 修改 x 的第一个元素
x[0] = 10print("x[0] == y[0]:", x[0] == y[0]) # True(引用同步变化)
print("x[0] == z[0]:", x[0] == z[0]) # False(拷贝保持原值)
2.8 loadtxt
numpy.loadtxt
: 从文本文件加载数据。
函数定义:
@finalize_array_function_like
@set_module('numpy')
def loadtxt(fname, dtype=float, comments='#', delimiter=None,converters=None, skiprows=0, usecols=None, unpack=False,ndmin=0, encoding=None, max_rows=None, *, quotechar=None,like=None):
参数说明:
fname
:指定输入源,支持文件路径、生成器、字符串列表等。dtype
:定义输出数组的数据类型,默认为float
。comments
:标识注释行的起始字符(如'#'
),跳过这些行。delimiter
::定义列分隔符,仅支持单字符分隔,默认为任意空白符(空格、制表符)。converters
::自定义列数据预处理函数,支持字典(按列映射)或可调用对象(全局应用)。skiprows
::跳过文件开头的指定行数(包括注释行)。usecols
:选择特定列加载(列索引从 0 开始)。unpack
:转置结果数组,便于分列赋值(如x, y = loadtxt(...)
)。ndmin
:控制输出数组的最小维度。默认为 0(自动压缩单维),可设为 1 或 2 强制保留维度。encoding
:文件解码格式(如'utf-8'
),默认为None
(系统默认)。max_rows
:读取skiprows
后的前N
行有效数据(空行和注释行不计入)。quotechar
:处理带引号的字段(如"a, b"
),引号内的分隔符和注释符会被忽略。like
:生成与指定对象兼容的数组(支持Dask
、CuPy
等库)。
示例,从 CSV
文件加载数据创建数组:
import numpy as np# 示例文件内容(data.csv):
# 1,2,3
# 4,5,6
data = np.loadtxt('data.csv', delimiter=',')
print(data)
2.9 fromXX
最后,简单介绍下不太常用的以 from
开头的多个函数,使用时请参考官方 API
文档。
2.9.1 frombuffer
frombuffer
从二进制缓冲区创建数组:
frombuffer(buffer, dtype=float, count=-1, offset=0, *, like=None)
2.9.2 from_dlpack
from_dlpack
通过 DLPack
协议从其他库(如 PyTorch
、TensorFlow
)共享内存创建数组:
def from_dlpack(x: _SupportsDLPack[None],/,*,device: L["cpu"] | None = None,copy: builtins.bool | None = None,
) -> NDArray[number[Any] | np.bool]: ...
2.9.3 fromfile
fromfile
从二进制或文本文件读取数据创建数组:
fromfile(file, dtype=float, count=-1, sep='', offset=0, *, like=None)
2.9.4 fromfunction
fromfunction
根据坐标生成函数创建数组,每个元素由函数计算得到:
def fromfunction(function, shape, *, dtype=float, like=None, **kwargs):
2.9.5 fromiter
fromiter
从可迭代对象创建数组:
fromiter(iter, dtype, count=-1, *, like=None)
2.9.6 fromstring
fromstring
从字符串解析数据创建数组:
fromstring(string, dtype=float, count=-1, *, sep, like=None)