NumPy 学习
数据类型
数据类型
- 布尔型
bool_
- 有符号整型
int_
:默认的整数类型,一般情况下是int32
或int64
intc
:与C语言中的int
大小相同,一般情况下是int32
或int64
intp
:一般情况下是int32
或int64
int8、int16、int32、int64
- 无符号整型
uint8、uint16、uint32、uint64
- 浮点型
float_
:float64
的简写float16、float32、float64
- 复数型
complex_
:complex128
的简写complex64、complex128
:实数和虚数均为双32/64位浮点型
数据类型对象(dtype)
dtype(object, align, copy)
object
:要转换为的数据类型对象align
:如果为 true,填充字段使其类似 C 的结构体。copy
:复制 dtype 对象,如果为 False,则是对内置数据类型对象的引用
数组(ndarray)
用于存放同类型元素的多维数组,链表实现 创建:array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
object
:数组或嵌套的数列dtype
:数组的数据类型copy
:是否需要复制对象生成order
:创建数组的样式(C
为行向量,F
为列向量,A
为任意方向)subok
:默认返回一个与基类类型一致的数组ndmin
:指定生成数组的最小维度 属性:ndim
:秩,即轴的数量或维度的数量shape
:数组的维度,对于矩阵, 行 列size
:数组元素的总个数,相当于.shape
中 的值dtype
:对象的元素类型itemsize
:对象中每个元素的大小,以字节为单位flags
:对象的内存信息real
:元素的实部imag
:元素的虚部
创建
初始化创建
numpy.empty(shape, dtype = float, order = 'C')
:创建未初始化的数组numpy.zeros(shape, dtype = float, order = 'C')
:创建全 数组numpy.ones(shape, dtype = None, order = 'C')
:创建全 数组
从数组创建
numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)
:创建与数组a
相同大小的全 数组numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)
:创建与数组a
相同大小的全 数组
从其他对象创建
numpy.asarray(a, dtype = None, order = None)
:从元组、列表等任意形式的a
创建数组numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)
:从buffer
流式读入创建数组numpy.fromiter(iterable, dtype, count=-1)
:从iterable
迭代器读入创建数组
从数列创建
numpy.arange(start, stop, step, dtype)
:从范围创建数组(前闭后开)numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
:从等差数列创建一维数组numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
:从等比数列创建一维数组
索引和切片
整数数组索引
- 使用一个数组(列表)访问另一个数组
a = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[[1, 2], [1, 2]])
## 效果是分别获取到了位于 (1, 1) 和 (2, 2) 位置上的 5 和 9,故输出为 [5, 9]
- 用于索引的数组表示的是指定下标,即
[[a1, a2, a3], [b1, b2, b3], [c1, c2, c3]]
获取到的会是array[array[a1, b1, c1], array[a2, b2, c2], array[a3, b3, c3]]
切片索引
- 语法:
a[<开始>:<结束>:<步长>, <开始>:<结束>:<步长>]
- 开始默认为 0,结束默认为长度,步长默认为 1
- 如果
<开始>
或<结束>
中出现负数x
,等价于size+x
,即若a.shape == (4, 4)
,则a[1:-1, 1:-2] == a[1:3, 1:2]
- 使用省略号代替取某一个维度的全部,如:
a.shape == (3, 3)
,a[0:3:1, 0:1:1] == a[..., 0:1] == a[::, :1]
索引和切片的实现
通过重写 __getitem__(self, item)
方法,item
传入的内容会是 slice
对象或 Ellipsis
对象的元组,据此可以对维度进行拆分。效果如下:
class A:
def __getitem__(self, item):
print(item)
a = A()
a[1:2:3, ..., 4:5:6]
## output: (slice(1, 2, 3), Ellipsis, slice(4, 5, 6))
布尔索引
- 使用布尔运算来获取一个数组中所有满足条件的值
a = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[a > 5])
## 输出:
## [6, 7, 8, 9]
广播
当运算中的 2 个数组的形状不同时,自动触发广播机制,以使得运算可以继续进行。
广播的规则
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 即
[1, 2] + [[1, 2], [3, 4]]
会先转化为[[1, 2]] + [[1, 2], [3, 4]]
,反映在shape
上,就是第一个加数的shape
从(2)
变成了(1, 2)
,与第二个加数的(2, 2)
长度相同
- 即
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
- 即
[[1, 2]] + [[1, 2], [3, 4]]
会转化为[[1, 2], [1, 2]] + [[1, 2], [3, 4]]
,将第一行的[1,2]
进行复用 简单理解,对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 即
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。 若条件不满足,抛出
ValueError: frames are not aligned
注意
在 numpy 中,默认两个数组相乘是将对应元素相乘,而非矩阵乘法,因此,直接将两个 ndarray 相乘,可能触发广播机制,例如 np.array([1, 2]) * np.array([[1, 2], [3, 4]])
的结果是 [[1, 2], [1, 2]] * [[1, 2], [3, 4]] = [[1*1, 2*2][1*3, 2*4]] = [[1, 4], [3, 8]]
数组操作
reshape 改变形状
numpy.reshape(arr, newshape, order='C')
arr
:要修改形状的数组newshape
:整数或者整数数组,新的形状应当兼容原有形状order
:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
flat 迭代
numpy.ndarray.flat
是一个数组元素迭代器
flatten 拷贝展开
ndarray.flatten(order='C')
返回按顺序展开,并拷贝一份后的数组,不会修改原数组order
:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
ravel 展开
numpy.ravel(a, order='C')
返回按顺序展开的数组,会修改原数组order
:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
翻转
矩阵(numpy.matlib)
矩阵总是二维的,而 ndarray 是一个 n 维数组。 两个对象都是可互换的。
线性代数
numpy.dot(a, b, out=None)
:- 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为向量点积);
- 对于二维数组,计算的是两个数组的矩阵乘积;
- 对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二维上的所有元素的乘积和:
dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
。 - 参数
out
: ndarray, 可选,用来保存dot()的计算结果
numpy.vdot(a, b, out=None)
:两个向量的点积。如果第一个参数是复数,那么它的共轭复数会用于计算。如果参数是多维数组,它会被展开。numpy.inner(a, b, out=None)
:返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上的和的乘积。