Numpy 中数据结构的核心是 n 维数组 n-dimensional array,简称 ndarray,需要注意的是数组中的元素都要属于同一个数据类型。
几个常用的 ndarray 的属性:ndarray.dtype,ndarray.shape,ndarray.ndim
几个常用的生成 ndarray 的方法:np.zeros( ),np.ones( ),np.zeros_like( ),np.ones_like( ),np.empty( ),np.arange( ),np.eye( ),np.identity( )
np.zeros(shape, dtype=float):shape 参数可以是一个自然数,也可以是二维元组,当元组中有三个参数时,后两个参数可以理解为 ndarray 的行数和列数,第一个参数为同样形状的 array 的个数。继续增加参数的个数的工作机制同上,都是对于后续的数组进行一个按照给定参数的量进行复制,np.ones( ) 工作机制类似。
np.zeros((2, 5, 3))
array([[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]])
np.zeros_like(),np.ones_like() 的参数为已有的一个 ndarray,会返回一个同形状的元素全 0 或全 1 的 ndarray。
np.empty() 生成一个占位的空数组,由于需要自行设置数组中的每一个值,因此要尽量少用。
np.arange() 的参数为一个整数,工作机制类似于 python 内建函数 range,但返回一个 ndarray。
np.arange(11)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
np.eye(N, M=none, k=0, dtype=) :N 为矩阵的行,M 为矩阵的列,如果 M 不指定则默认为 N x N 方阵,k 为 1 所在的对角线的位置
不指定列数:
np.eye(3) # 相当于 np.identity(3)
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
指定列数和 1 所在对角线位置:
np.eye(3, 4, 2)
array([[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.],
[ 0., 0., 0., 0.]])
当 k ≥ M 时,为 0 矩阵:
np.eye(3, 4, 4)
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
还可以通过 np.identity() 来创建单位矩阵
np.identity(4)
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
ndarray 的索引和切片
一维 ndarray
一维 ndarray 的索引和切片与 list 类似,主要差别是可以通过索引和切片直接修改原 ndarray 中的值。同时, ndarray 的切片只是提供了原 ndarray 的一个局部视图 view 而不是原 ndarray 的一个拷贝,但对于切片的任何修改都会反映到原有的 ndarray 中去。后续大量数组的操作都是采用视图而非拷贝的原因是 Numpy 是为了操作大量数据而构建的,因此从性能的角度出发需要尽量的减少内存占用。
arr = np.arange(10)
arr[3: 8] = 10
arr_slice = arr[5: 8]
arr_slice
array([10, 10, 10])
对切片进行索引赋值操作会直接作用到原来的数组:
arr_slice[1] = 12
arr
array([0, 1, 2, 10, 10, 10, 12, 10, 8, 9])
如果确实需要进行复制,则可以通过显式的使用 arr[ 5: 8].copy() 来完成。
当对一维数组进行 arr.shape 查询时结果是诸如 (3, ) 的形式,这个看起来很怪异的形状在 Numpy 中称为 Rank 1 数组,对应的 arr.ndim 返回 1,在实际使用中应尽量避免这种数据结构,原因请参见这篇 rank 1 数组。
二维和高维 ndarray
二维数组的单个索引值得到的是一个一维数组:
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]
array([7, 8, 9])
两个索引值则会获取相应位置的值:
arr2d[2, 2] # arr2d[2][2]
9
高维数组的索引机制与二维类似,即会根据提供的索引值逐次找到相应位置的数组或元素。
arr3d = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]])
arr3d.shape
(1, 4, 3)
单个索引值: