Skip to content

numpy 使用

ndarray 数组的创建

函数说明
array将序列类型转换为 ndarray , 可以推断或指定 dtype
asarray同上,但当参数为 ndarray 时不会创建新的 ndarray 而是返回其本身
arange类似内置函数 range , 但创建行向量
linspace指定首尾,等距生成若干个数字。在函数绘制中很有用
ones, ones_like根据指定形状和 dtype 创建全 1 矩阵;后者以其他数组为参数,创建相同形状的全 1 矩阵
zeros, zeros_like类似
empty, empty_like类似
identity, eye创建单位矩阵。identity(N) 创建 N×N 的单位矩阵, eye(N, M)创建 N×M 的单位对角矩阵

ndarray 数组元素的类型

numpy 的数组与 C 语言的数组密切相关。在数组创建时,可以指定需要的类型。在上一节的函数中,都可以加入 dtype 参数来指定类型。如 np.arange(10, dtype='i8')。当浮点型数字转变为整形时,将发生截断,即向 0 取整。

类型类型代码说明
整形int8, uint8i1, u1
int16, uint16i2, u2
int32, uint32i4, u4
int64, uint64i8, u8
浮点型float16f2
float32f4 / f
float64f8 / d
float128f16 / g
复数complex64c8用两个 float32 表示的复数
complex128c16用两个 float64 表示的复数
complex256c32用两个 float128 表示的复数
其它bool?布尔
objectOpython 对象
string_S固定长度的字符串类型 e.g. S10 表示长度为 10 的字符串
unicode_U固定长度的 unicode 类型

ndarray 切片和维度变换

形状

  • size 数组所含元素的个数
  • shape 数组的维度,如 N × M 矩阵的 shape 是(N, M)
  • reshape 重新排列数组。维度与元素个数应相关。可以用-1让 python 推测剩余的一个维度。
  • transpose 数组转置。转置后的 shape 与原来完全相反。
  • swapaxes 轴对换。示例见下。
python
a = np.arange(24).reshape((2,3,4))
b = a.swapaxes(0,1)
b.shape
# (3,2,4)
np.asarray([
    a[i,j,:] == b[j,i,:] for i in range(2) for j in range(3)
]).all()
# True

拼接

concatenate 函数将一系列数组沿指定维度拼接。默认沿维度 1 拼接。要求第一个参数中所有数组除拼接维度外,其它维度必须相同。

python
a = np.arange(24).reshape((2,3,4))
b = np.array(a)
c = np.concatenate((a, b), axis=2)
c.shape
# (2, 3, 8)

类似的函数:

函数说明
vstack
hstack
dstack
分别沿第 0,1,2 条轴堆叠
column_stack与 hstack 几乎一样,但遇到行向量时会先将其转化为列向量

拆分

split 函数将一个 ndarray 沿指定轴等距或在给定位置处分割。

python
[arr.shape for arr in np.split(c, 2, axis=0)]
# [(1, 6, 4), (1, 6, 4)]
[arr.shape for arr in np.split(c, [2], axis=0)]
# [(2, 6, 4), (0, 6, 4)]

类似的函数:

函数说明
array_split与 split 完全相同,但是当等距分割不成功时,用最接近等距的分割方式且不报错
vsplit
hsplit
dsplit
分别沿第 0,1,2 条轴分割

切片

以使用与列表类似的 : 符号,但不同维度之间可以用 , 隔开。在某个维度仅取单个数字值时引发降维。

python
a = np.arange(24).reshape((2,3,4))
a[:, 1, 2:4].shape
# (2, 2)
a[:, 1:2, 2:4].shape
# (2, 1, 2)

我们知道,python 列表切片创建了浅拷贝,而对于 ndarray 切片,除非降维至 0 维(一个数字),否则返回的数组都是原数组的一个视图 (引用,会同时变化)。想获得与原数组无关的切片,需要手动调用 copy() 方法。

python
a = np.arange(24).reshape((2,3,4))
c = a[-1,-1,-1:]
c
# array([23])
c *= -1
a[-1,-1,-1]
# -23

也可以使用整形数组来索引数组,这被称为花式索引。整形数组会被理解为某个元素的该维度的下标,因而如果使用了整形数组作为索引,则要求整形数组之间相互兼容(遵循广播原理)。如 a[[0,1], [0,1], [0,1]] 返回的结果是 a[0,0,0]a[1,1,1] 的结合。返回的结果是一维的数组视图。

切片语法与花式索引可以结合使用。

另参见 布尔索引

ndarray 运算与广播机制

numpy 中的普通运算(+,-,×,÷)均与线性代数无关,而是对应元素的计算。当运算双方的维度不同时, numpy 进行兼容检查,如果兼容则进行广播,然后计算。

数组是否兼容

从右至左比较数组的 shape, 遇到不相同且两方均不为 1 的情况,则数组不兼容。

比如: a.shape = (5,4,3), b.shape = (4, 1) 。则 1 与 3 兼容, 4 与 4 兼容, a, b 都将扩展至 (5, 4, 3) 。

  • (5, 3, 1) 和 (6, 1, 1, 4) 产生 (6, 5, 3, 4)
  • (4, 3) 和 (1,) 产生 (4, 3)
  • (4, 2) 和 (2, 2) 不兼容

广播

由兼容性判断可以发现,兼容的维度为 1 或相同。若为 1 则将该维度重复若干次;为相同则对应地执行相应操作。

python
import numpy as np
a = np.ones((2,3,4))
b = np.asarray([[[2,3,4,5]]])
b.shape
# (1, 1, 4)
c = a + b
c.shape
# (2, 3, 4)
c
# array([[[3., 4., 5., 6.],
#         [3., 4., 5., 6.],
#         [3., 4., 5., 6.]],
#
#        [[3., 4., 5., 6.],
#         [3., 4., 5., 6.],
#         [3., 4., 5., 6.]]])

广播机制能够把循环放到 numpy 底层的 C 库中进行计算,从而加速了计算过程。

通用函数(universe function)

通用函数对一个数组执行元素级运算。

函数说明
absfabs绝对值,前者可以计算复数的模。实测后者不一定快。
sqrtsquareexp平方根/平方/指数
loglog10log2log1plnx,log10x,log2x,ln(1+x)
ceilfloorfixtrunc向上/向下/向 0 取整,截断
roundrint四舍六入,前者保留 dtype
modmodffmod

布尔数组

有一类特殊的数组,元素类型为 bool,可以完成一些特殊的操作。

布尔索引

布尔数组可以用作索引,索引要求与原数组的 shape 完全相同。通过布尔索引生成的数组都是一维的,是原数组的一个视图,包含对应 True 位置的所有元素,可以用来更改原数组。

python
a = np.ones((3,3))
a[np.identity(3, dtype='bool')] = 4

以上代码生成了一个对角线为 4 ,其它元素为 1 的二维数组。

where 函数

统计方法

函数说明
sum, cumsum和,累积和
mean, std, var均值,标准差,方差
min, max, medium最小值,最大值,中位数
argmin, argmax最小值的索引,最大值的索引

线性代数

numpy.linalg 模块的常用函数。

函数说明
trace矩阵的迹
det矩阵的行列式
eig本征值和本征向量
inv矩阵的逆
solveAx=b的解
lstsqAx=b的最小二乘解