NumPy is the fundamental package for scientific computing in Python. It is a Python library that provides a multidimensional array object, various derived objects (such as masked arrays and matrices), and an assortment of routines for fast operations on arrays, including mathematical, logical, shape manipulation, sorting, selecting, I/O, discrete Fourier transforms, basic linear algebra, basic statistical operations, random simulation and much more.
Topic 1 Ndarray
NumPy 最重要的一个特点是其 N 维数组对象 ndarray, 它是一系列同类型数据的集合, 以 0 下标为开始进行集合中元素的索引. ndarray 有两个个重点:
- ndarray 对象是用于存放同类型元素的多维数组.
- ndarray 中的每个元素在内存中都有相同存储大小的区域.
创建一个 ndarray 只需要调用 Numpy 的 array 函数即可:
1 numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)参数说明:
- object: 数组或嵌套的数列
- dtype: 数组元素的数据类型, 可选
- copy: 对象是否需要复制, 可选
- order: 创建数组的样式, C 为行方向, F 为列方向, A 为任意方向 (默认)
- subok: 默认返回一个与基类类型一致的数组
- ndmin: 指定生成数组的最小维度
我们看几个实例:
[例 1.1] 创建一维数组
1 | import numpy as np |
输出结果为:
1 | [1,2,3] |
[例 1.2] 创建二维数组
1 | import numpy as np |
输出结果为:
1 | [[1,2] |
[例 1.3] 指定最小维度
1 | import numpy as np |
输出结果为:
1 | [[1,2,3,4,5]] |
[例 1.4] 指定数据类型
1 | import numpy as np |
输出结果为:
1 | [1.+0.j 2.+0.j 3.+0.j] |
Topic 2 Data Type
在这里我假设你已经有了一定的 python 的基础. Numpy 支持比 Python 更多种类的数组数据类型. 本节主要是介绍一下 Numpy 里面常用的数据类型.
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型 (True 或者 False) |
int_ | 默认的整数类型 |
intc | 与 C 的 int 类型一样, 一般是 int32 或 int 64 |
intp | 用于索引的整数类型 (类似于 C 的 ssize_t, 一般情况下仍然是 int32 或 int64) |
int8 | 字节 ($-2^7\ to\ 2^7-1$) |
int16 | 整数 ($-2^{15}\ to\ 2^{15}-1$) |
int32 | 整数 ($-2^{31}\ to\ 2^{31}-1$) |
int64 | 整数 ($-2^{63}\ to\ 2^{63}-1$) |
uint8 | 无符号整数 ($2^8-1$) |
uint16 | 无符号整数 ($2^{16}-1$) |
uint32 | 无符号整数 ($2^{32}-1$) |
uint64 | 无符号整数 ($2^{64}-1$) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数, 包括: 1 个符号位, 5 个指数位, 10 个尾数位 — 见注[1]和[2] |
float32 | 单精度浮点数, 包括: 1 个符号位, 8 个指数位, 23 个尾数位 |
float64 | 双精度浮点数, 包括: 1 个符号位, 11 个指数位, 52 个尾数位 |
complex_ | complex128 类型的简写, 即 128 位复数 |
complex64 | 复数, 表示双 32 位浮点数 (实数部分和虚数部分) |
complex128 | 复数, 表示双 64 位浮点数 (实数部分和虚数部分) |
注:
[1] 所有数字以二进制存储, 每个数字对应的二进制分为三段: 符号位、指数位、尾数位. 其中符号位是二进制表示中的第一位, 0 表示正数, 1 表示负数. 指数位决定了数字的范围. 尾数位决定了数字的精度.
[2] 半精度是英伟达在2002年搞出来的, 双精度和单精度是为了计算, 而半精度更多是为了降低数据传输和存储成本.
数据类型对象 (dtype) 是用来描述与数组对应的内存区域如何使用, 这依赖如下几个方面:
- 数据的类型 (整数, 浮点数或者 Python 对象)
- 数据的大小 (例如, 整数使用多少个字节存储)
- 数据的字节顺序 (小端法或大端法)
- 在结构化类型的情况下, 字段的名称、每个字段的数据类型和每个字段所取的内存块的部分
字节顺序是通过对数据类型预先设定”<”或”>”来决定的. “<”意味着小端法(最小值存储在最小的地址, 即低位组放在最前面). “>”意味着大端法 (最重要的字节存储在最小的地址, 即高位组放在最前面).
dtype 对象是使用以下语法构造的:
1 | numpy.dtype(object, align, copy) |
- object: 要转换为的数据类型对象
- align: 如果为 true, 填充字段使其类似 C 的结构体
- copy: 复制 dtype 对象, 如果为 false, 则是对内置数据类型对象的引用
我们接下来看几个实例:
[例 2.1] 使用标量类型
1 | import numpy as np |
输出结果为:
1 | int32 |
[例 2.2] 使用缩写
1 | import numpy as np |
输出结果为:
1 | int32 |
[例 2.3] 指定字节顺序
1 | import numpy as np |
输出结果为:
1 | int32 |
[例 2.4] 创建结构化数据类型
1 | import numpy as np |
输出结果为:
1 | [('age', 'i1')] |
[例 2.5] 将数据类型应用于 ndarray 对象
1 | import numpy as np |
输出结果为:
1 | [(10,) (20,) (30,)] |
[例 2.6] 类型字段名可以用于存取实际的 age 列
1 | import numpy as np |
输出结果为:
1 | [10 20 30] |
[例 2.7] 定义一个结构化数据类型 student, 包含字符串字段 name, 整数字段 age, 及浮点字段 marks, 并将这个 dtype 应用到 ndarray 对象.
1 | import numpy as np |
输出结果为:
1 | [(b'abc', 21, 50.) (b'xyz', 18, 75.)] |
注: S
后面的数字是表示字符串的长度, 超出会被截断.
每个内建类型都有一个唯一定义它的字符代码, 如下:
字符 | 对应类型 |
---|---|
b | 布尔型 |
i | (有符号) 整型 |
u | 无符号整型 integer |
f | 浮点型 |
c | 复数浮点型 |
m | timedelta(时间间隔) |
M | datetime(日期时间) |
O | (Python) 对象 |
S, a | (byte-)字符串 |
U | Unicode |
V | 原始数据 (void) |
Topic 3 Properties of Ndarray
Numpy 数组的维数称为秩 (rank), 秩就是轴的数量, 一维数组的秩是 1, 二维数组的秩为 2, 以此类推. 在 Numpy中,每一个线性的数组称为是一个轴 (axis), 也就是维度 (dimensions). 比如说,二维数组相当于是两个一维数组, 其中第一个一维数组中每个元素又是一个一维数组. 所以一维数组就是 Numpy 中的轴 (axis), 第一个轴相当于是底层数组, 第二个轴是底层数组里的数组. 而轴的数量——秩, 就是数组的维数.
很多时候可以声明 axis. axis=0, 表示沿着第 0 轴进行操作, 即对每一列进行操作. axis=1, 表示沿着第1轴进行操作, 即对每一行进行操作. Numpy 的数组中比较重要 ndarray 对象属性有:
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
ndarray.real | ndarray元素的实部 |
ndarray.imag | ndarray 元素的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
我们来看几个例子:
[例 3.1] 使用 ndarray.ndim 返回数组的维数
1 | import numpy as np |
输出结果为:
1 | [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] |
[例 3.2] 使用 ndarray.shape 来获取数组的维度, 返回一个元组, 这个元组的长度就是维度的数目, 即 ndim 属性 (秩). 比如, 一个二维数组, 其维度表示”行数”和”列数”.
1 | import numpy as np |
输出结果为:
1 | (2,3) |
调整数组大小
1 | import numpy as np |
输出结果为:
1 | [[1 2] |
[例 3.3] 使用 ndarray.size 来获取数组中的元素个数
1 | import numpy as np |
输出结果为:
1 | 6 |
Topic 4 Array Creation
ndarray 数组除了可以使用底层 ndarray 构造器来创建外, 也可以通过以下几种方式来创建.
4.1 numpy.empty
numpy.empty 方法用来创建一个指定形状 (shape), 数据类型 (dtype) 且未初始化(随机值)的数组:
1 | numpy.empty(shape, dtype=float64, order='C') |
[例 4.1]
1 | import numpy as np |
输出结果为:
1 | [[ 0 0 0] |
4.2 numpy.zeros
创建指定大小的数组, 数组元素以 0 来填充:
1 | numpy.zeros(shape, dtype=float64, order='C') |
[例 4.2]
1 | import numpy as np |
输出结果为:
1 | [[0. 0. 0.] |
4.3 numpy.ones
创建指定形状的数组, 数组元素以 1 来填充:
1 | numpy.ones(shape, dtype=float64, order='C') |
[例 4.3]
1 | import numpy as np |
输出结果为:
1 | [[1 1 1] |
4.4 numpy.eye
创建单位矩阵
[例 4.4]
1 | import numpy as np |
输出结果为:
1 | [[1 0 0 0 0] |
4.5 numpy.random.randn
创建标准正态分布随机数组:
1 | numpy.random.randn(d0, d1, d2, ...) |
[例 4.5]
1 | import numpy as np |
输出结果为:
1 | [[-1.49392311 0.88590821 -0.44375056] |
4.6 numpy.random.rand
创建元素位于 [0, 1) 的随机数组
[例 4.6]
1 | import numpy as np |
输出结果为:
1 | [[0.06404836 0.47933279 0.7514547 ] |
4.7 numpy.random.randint
利用 randint(low, high, size)
创建一个整数型指定范围在 [low, high] 之间的数组.
[例 4.7]
1 | import numpy as np |
输出结果为:
1 | [[121 102 170] |
4.8 numpy.asarray
numpy.asarray 类似 numpy.array, 但 numpy.asarray 参数只有三个, 比 numpy.array 少两个.
1 | numpy.asarray(object, dtype=None, order=None) |
[例 4.8]
1 | import numpy as np |
输出结果为:
1 | [1. 2. 3.] |
4.9 numpy.frombuffer
numpy.frombuffer 接受 buffer 输入参数, 以流的形式读入转化成 ndarray 对象.
1 | numpy.frombuffer(buffer, dtype=float64, count=-1, offset=0) |
[例 4.9]
1 | import numpy as np |
输出结果为:
1 | [b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd'] |
4.10 numpy.fromiter
numpy.fromiter 方法从可迭代对象中建立 ndarray 对象, 返回一维数组.
1 | numpy.fromiter(iterable, dtype, count=-1) |
[例 4.10]
1 | import numpy as np |
输出结果为:
1 | [0 1 2 3 4] |
4.11 numpy.arange
使用 arange 函数创建数值范围并返回 ndarray 对象, 函数格式如下:
1 | numpy.arange(start, stop, step, dtype) |
[例 4.11]
1 | import numpy as np |
输出结果为:
1 | [0. 1. 2. 3. 4.] |
4.12 numpy.linspace
numpy.linspace 函数用于创建一个一维数组, 数组是一个等差数列构成的, 格式如下:
1 | numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None) |
[例 4.12]
1 | import numpy as np |
输出结果为:
1 | (array([ 0., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., |
我们也可以使用 reshape 来改变数组维度
1 | import numpy as np |
输出结果为:
1 | [[ 0. 5. 10. 15. 20. 25. 30.] |
4.13 numpy.logspace
numpy.logspace 函数用于创建一个数组中元素取对数后均匀分布的数组, 格式如下:
1 | numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None) |
注意, numpy.logspace
代码等效于代码:
1 | a = np.linspace(start,stop, num=num, base=base, endpoint=True) |
[例 4.13]
1 | import numpy as np |
输出结果是:
1 | [2. 2.16011948 2.33305808 2.5198421 2.72158 2.93946898 |
Topic 5 Slice and Index
5.1 Slice
ndarray对象的内容可以通过索引或切片来访问和修改, 与 Python 中 list 的切片操作一样. ndarray 数组可以基于 0 - n 的下标进行索引, 切片对象可以通过内置的 slice 函数, 并设置 start, stop 及 step 参数进行, 从原数组中切割出一个新数组.
[例 5.1]
1 | import numpy as np |
输出结果为:
1 | [2 4 6] |
[例 5.2]
我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作:
1 | import numpy as np |
输出结果为:
1 | [2 4 6] |
[例 5.3]
同样我们可以提取单个元素
1 | import numpy as np |
输出结果为
1 | 2 |
[例 5.4]
多维数组也同样适用
1 | import numpy as np |
输出结果为:
1 | [[1 2 3] |
[例 5.5]
在多维数组的切片中, 使用 ,
区分维数.
1 | import numpy as np |
输出结果为:
1 | [[ 0 1 2 3] |
5.2 Index
NumPy 比一般的 Python 序列提供更多的索引方式, 除了之前看到的用整数和切片的索引外, 数组可以由整数数组索引、布尔索引及花式索引.
5.2.1 Array Indexing
[例 5.6]
在多维数组中, 非连续索引切片:
1 | import numpy as np |
输出结果为:
1 | a: |
[例 5.7]
获取数组中(0,0), (1,1) 和 (2,0)位置处的元素.
1 | import numpy as np |
输出结果为:
1 | [1 4 5] |
[例 5.8]
获取了 4X3 数组中的四个角的元素. 行索引是 [0,0] 和 [3,3], 而列索引是 [0,2] 和 [0,2].
1 | import numpy as np |
输出结果是:
1 | 我们的数组是: |
5.2.2 Bool Indexing
我们可以通过一个布尔数组来索引目标数组. 布尔索引通过布尔运算 (如: 比较运算符) 来获取符合指定条件的元素的数组.
[例 5.9]
获取大于 5 的元素
1 | import numpy as np |
输出结果是:
1 | 我们的数组是: |
[例 5.10]
使用 ~
(取补运算符) 来过滤 NaN
1 | import numpy as np |
输出结果是:
1 | [1. 2. 3. 4. 5.] |
[例 5.11]
从数组中过滤掉非复数元素
1 | import numpy as np |
输出结果是:
1 | [2. +6.j 3.5+5.j] |
5.2.3 Fancy Indexing
花式索引指的是利用整数数组进行索引. 花式索引根据索引数组的值作为目标数组的某个轴的下标来取值. 对于使用一维整型数组作为索引, 如果目标是一维数组, 那么索引的结果就是对应位置的元素; 如果目标是二维数组, 那么就是对应下标的行.
花式索引跟切片不一样, 它总是将数据复制到新数组中.
[例 5.12]
传入顺序索引数组
1 | import numpy as np |
输出结果是:
1 | [[16 17 18 19] |
[例 5.13]
传入倒序索引数组
1 | import numpy as np |
输出结果是:
1 | [[16 17 18 19] |
[例 5.14]
传入多个索引数组, 使用 np.ix_
1 | import numpy as np |
输出结果是:
1 | [[ 4 7 5 6] |
注:
x[np.ix_([1,5,7,2],[0,3,1,2])]这句话会输出一个4*4的矩阵, 其中的元素分别是:
1
2
3
4 x[1,0] x[1,3] x[1,1] x[1,2]
x[5,0] x[5,3] x[5,1] x[5,2]
x[7,0] x[7,3] x[7,1] x[7,2]
x[2,0] x[2,3] x[2,1] x[2,2]就是说, 如果 np.ix_ 中输入两个列表, 则第一个列表存的是待提取元素的行标, 第二个列表存的是待提取元素的列标, 第一个列表中的每个元素都会遍历第二个列表中的每个值, 构成新矩阵的一行元素.
Topic 6 Broadcast
广播 (Broadcast) 是 numpy 对不同形状 (shape )的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行.
如果两个数组 a 和 b 形状相同, 即满足 a.shape == b.shape, 那么 a*b 的结果就是 a 与 b 数组对应位相乘. 这要求维数相同, 且各维度的长度相同.
[例 6.1]
1 | import numpy as np |
输出结果是:
1 | [ 10 40 90 160] |
[例 6.2]
当运算中的 2 个数组的形状不同时, numpy 将自动触发广播机制. 如:
1 | import numpy as np |
输出结果是:
1 | [[ 1 2 3] |
注:
4x3 的二维数组与长为 3 的一维数组相加, 等效于把数组 b 在二维上重复 4 次再运算:
1
2
3
4
5
6
7 a = np.array([[0,0,0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([1,2,3])
c = np.tile(b,(4,1)) # np.ones((2,3)) 等效于 np.tile(1., (2,3))
print(a+c)输出结果是:
1
2
3
4 [[ 1 2 3]
[11 12 13]
[21 22 23]
[31 32 33]]可以广播的几种情况:
- 两个数组各维度大小从后往前比对均一致
看个例子:
1 | import numpy as np |
举个反例:
1 | import numpy as np |
- 两个数组存在一些维度大小不相等时, 有一个数组的该不相等维度大小为1
这是对上面那条规则的补充,虽然存在多个维大小不一致,但是只要不相等的那些维有一个数组的该大小是1 就可以.
看个例子:
1 | import numpy as np |
同样看个反例:
1 | import numpy as np |
Topic 7 Array Iteration
7.1 numpy.nditer
NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式.
[例 7.1]
使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代.
1 | import numpy as np |
输出结果是:
1 | 原始数组: |
注: 你如果有一定的编程基础, 我们也可以使用 nested for loop 来进行遍历.
以上实例不是使用标准 C 或者 Fortran 顺序, 选择的顺序是和数组内存布局一致的, 这样做是为了提升访问的效率, 默认是行序优先 (row-major order,或者说是 C-order). 这反映了默认情况下只需访问每个元素, 而无需考虑其特定顺序. 我们可以通过迭代上述数组的转置来看到这一点, 并与以 C 顺序访问数组转置的 copy 方式做对比, 如下:
[例 7.2]
1 | import numpy as np |
输出结果是:
1 | 0, 1, 2, 3, 4, 5, |
7.2 Iteration Direction
我们也可以控制遍历顺序:
for x in np.nditer(a, order='F')
Fortran order,即是列序优先.for x in np.nditer(a.T, order='C')
C order,即是行序优先.
[例 7.3]
1 | import numpy as np |
输出结果是:
1 | 原始数组是: |
7.3 Modify Array
我们也可以在遍历过程中修改数组中元素的值.
nditer 对象有另一个可选参数 op_flags. 默认情况下, nditer 将视待迭代遍历的数组为只读对象 (read-only), 为了在遍历数组的同时, 实现对数组元素值得修改, 必须指定 read-write 或者 write-only 的模式.
[例 7.4]
1 | import numpy as np |
输出结果是:
1 | 原始数组是: |
7.4 Return New Array Through Iteration
我们还可以通过修改 nditer
的 flags 参数来使其返回遍历值产生的新数组:
[例 7.5]
1 | import numpy as np |
输出结果是:
1 | [ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55], |
7.5 Broadcast Iteration
还有一种是广播迭代
如果两个数组是可广播的, nditer 组合对象能够同时迭代它们. 假设数组 a 的维度为 3X4, 数组 b 的维度为 1X4, 则使用以下迭代器 (数组 b 被广播到 a 的大小).
[例 7.6]
1 | import numpy as np |
输出结果是:
1 | 第一个数组为: |
Topic 8 Array Operation
8.1 Change Array Shape
函数 | 描述 |
---|---|
numpy.reshape numpy.ndarray.reshape |
不改变数据的条件下修改形状 |
numpy.ndarray.flat |
数组元素迭代器 |
flatten |
返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 |
ravel |
返回展开数组 |
8.1.1 numpy.reshape
numpy.reshape 函数可以在不改变数据的条件下修改形状,格式如下:
numpy.reshape(arr, newshape, order='C')
[例 8.1]
1 | import numpy as np |
输出结果是:
1 | 原始数组: |
8.1.2 numpy.ndarray.flat
numpy.ndarray.flat
是一个数组元素迭代器, 例子如下:
[例 8.2]
1 | import numpy as np |
输出结果为:
1 | 原始数组: |
8.1.3 numpy.ndarray.flatten
numpy.ndarray.flatten 返回一份数组拷贝, 对拷贝所做的修改不会影响原始数组,格式如下:
1 | ndarray.flatten(order='C') |
[例 8.3]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.1.4 numpy.ravel
numpy.ravel() 展平的数组元素, 顺序通常是”C风格”, 返回的是数组视图, 修改会影响原始数组. 该函数接收两个参数:
1 | numpy.ravel(a, order='C') |
[例 8.4]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.2 Concatenate Array
函数 | 描述 |
---|---|
concatenate |
连接沿现有轴的数组序列 |
stack |
沿着新的轴加入一系列数组。 |
hstack |
水平堆叠序列中的数组(列方向) |
vstack |
竖直堆叠序列中的数组(行方向) |
8.2.1 numpy.concatenate
numpy.concatenate
函数用于沿指定轴连接相同形状的两个或多个数组, 格式如下:
1 | numpy.concatenate((a1,a2,...),axis=0) |
我们看一个例子:
[例 8.5]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
8.2.2 numpy.stack
用法和 numpy.concatenate
类似, 但这不是连接, 而是堆叠, 格式如下:
1 | numpy.stack(arrays, axis) |
看一个例子:
[例 8.6]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
8.2.3 numpy.hstack
numpy.hstack
是 numpy.stack
函数的变体, 它通过水平堆叠来生成数组.
[例 8.7]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
8.2.4 numpy.vstack
numpy.vstack
是 numpy.stack
函数的变体, 它通过垂直堆叠来生成数组.
[例 8.8]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
8.3 Split Array
函数 | 数组及操作 |
---|---|
split |
将一个数组分割为多个子数组 |
hsplit |
将一个数组水平分割为多个子数组(按列) |
vsplit |
将一个数组垂直分割为多个子数组(按行) |
8.3.1 numpy.split
numpy.split 函数沿特定的轴将数组分割为子数组, 格式如下:
1 | numpy.split(arr, indicies_or_sections, axis) |
[例 8.9]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
8.3.2 numpy.hsplit
numpy.hsplit 函数用于水平分割数组, 通过指定要返回的相同形状的数组数量来拆分原数组.
[例 8.10]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.3.3 numpy.vsplit
numpy.vsplit
沿着垂直轴分割, 其分割方式与hsplit用法相同。
[例 8.11]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.4 Add and Delete Elements of Array
函数 | 元素及描述 |
---|---|
append |
将值添加到数组末尾 |
insert |
沿指定轴将值插入到指定下标之前 |
delete |
删掉某个轴的子数组,并返回删除后的新数组 |
unique |
用于移去数组中的重复值 |
8.4.1 numpy.append
numpy.append 函数在数组的末尾添加值. 追加操作会分配整个数组, 并把原来的数组复制到新数组中. 此外, 输入数组的维度必须匹配否则将生成ValueError.
1 | numpy.append(arr, values, axis=None) |
[例 8.12]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.4.2 numpy.insert
numpy.insert
函数在给定索引之前, 沿给定轴在输入数组中插入值.
插入函数会返回一个新数组. 此外, 如果未提供轴, 则输入数组会被展开, 格式如下:
1 | numpy.insert(arr, obj, values, axis) |
[例 8.13]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.4.3 numpy.delete
numpy.delete
函数返回从输入数组中删除指定子数组的新数组. 与 insert() 函数的情况一样, 如果未提供轴参数, 则输入数组将展开, 格式如下:
1 | numpy.delete(arr, obj, axis) |
[例 8.14]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
8.4.4 numpy.unique
numpy.unique 函数用于去除数组中的重复元素, 用法如下:
1 | numpy.unique(arr, return_index, return_inverse, return_counts) |
[例 8.15]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
Topic 9 Math Functions
9.1 Trigonometric Functions
NumPy 提供了标准的三角函数:sin()、cos()、tan().
[例 9.1]
1 | import numpy as np |
输出结果是:
1 | 不同角度的正弦值: |
NumPy 提供了标准的三角函数的反函数: arcsin, arccos, arctan. 就不再举例了.
9.2 numpy.floor
numpy.floor()
返回小于或者等于指定表达式的最大整数, 即向下取整.
[例 9.2]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
9.3 numpy.ceil
numpy.ceil()
返回大于或者等于指定表达式的最小整数, 即向上取整.
[例 9.3]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
9.4 Arithmatic Functions
NumPy 算术函数包含简单的加减乘除: add(), subtract(), multiply() 和 divide(). 需要注意的是数组必须具有相同的形状或符合数组广播规则. 在这里, 我就不举例子了.
9.5 numpy.reciprocal
numpy.reciprocal()
函数返回参数逐元素的倒数. 如 1/4 倒数为 4/1.
[例 9.4]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
9.6 numpy.power
numpy.power()
函数将第一个输入数组中的元素作为底数, 计算它与第二个输入数组中相应元素的幂.
[例 9.5]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
9.7 numpy.mod
numpy.mod()
计算输入数组中相应元素的相除后的余数. 函数 numpy.remainder()
也产生相同的结果.
[例 9.6]
1 | import numpy as np |
输出结果是:
1 | 第一个数组: |
Topic 10 Stat Functions
10.1 numpy.amin & numpy.amax
numpy.amin(arr, axis=None)
用于计算数组中的元素沿指定轴的最小值.numpy.amax(arr, axis=None)
用于计算数组中的元素沿指定轴的最大值.
[例 10.1]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
10.2 numpy.ptp
numpy.ptp(arr, axis=None)
函数计算数组中元素最大值与最小值的差 (最大值 - 最小值).
[例 10.2]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
10.3 numpy.percentile
百分位数是统计中使用的度量, 用法如下:
1 | numpy.percentile(arr, Q, axis=None) |
[例 10.3]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
10.4 numpy.mean
numpy.mean(arr, axis=None)
函数返回数组中元素的算术平均值 (权重相等). 如果提供了轴, 则沿其计算.
10.5 numpy.average
numpy.average()
函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值. 用法如下:
1 | numpy.average(arr, weights=None, returned=False, axis=None) |
[例 10.4]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
10.6 numpy.std & numpy.var
numpy.std(arr, axis=None) & numpy.var(arr, axis=None)
求标准差和方差
[例 10.5]
1 | import numpy as np |
输出结果是:
1 | 原数组: |
Topic 11 Search & Condition Statements
11.1 numpy.sort
Numpy 提供了多种排序的方法. 这些排序函数实现不同的排序算法, 每个排序算法的特征在于执行速度, 最坏情况性能, 所需的工作空间和算法的稳定性. 下表显示了三种排序算法的比较.
种类 | 速度 | 最坏情况 | 工作空间 | 稳定性 |
---|---|---|---|---|
quicksort (快速排序) |
1 | O(n^2) |
0 | 否 |
mergesort (归并排序) |
2 | O(n*log(n)) |
~n/2 | 是 |
heapsort (堆排序) |
3 | O(n*log(n)) |
0 | 否 |
numpy.sort() 函数返回输入数组的排序副本. 函数用法如下:
1 | numpy.sort(arr, axis=1, kind='quicksort', order=None) |
[例 11.1]
1 | import numpy as np |
输出结果为:
1 | 原数组: |
11.2 numpy.argsort
numpy.argsort()
函数返回的是数组值从小到大的索引值.
[例 11.2]
1 | import numpy as np |
输出结果是:
1 | 我们的数组是: |
11.3 numpy.lexsort()
numpy.lexsort() 用于对多个序列进行排序. 把它想象成对电子表格进行排序, 每一列代表一个序列, 排序时优先照顾靠后的列.
[例 11.3]
录入了四位同学的成绩,按照总分排序,总分相同时语文高的优先.
1 | import numpy as np |
输出结果是:
1 | 40 30 10 |
11.4 numpy.argmax() & numpy.argmin()
numpy.argmax()
和 numpy.argmin()
函数分别沿给定轴返回最大和最小元素的索引.
11.5 numpy.nonzero
numpy.nonzero()
函数返回输入数组中非零元素的索引.
[例 11.4]
1 | import numpy as np |
输出结果是:
1 | 我们的数组: |
11.6 numpy.where
numpy.where()
函数返回输入数组中满足给定条件的元素的索引.
[例 11.5]
1 | import numpy as np |
输出结果是:
1 | 我们的数组是: |
Topic 12 Copy and View
副本是一个数据的完整的拷贝, 如果我们对副本进行修改, 它不会影响到原始数据, 物理内存不在同一位置.
- Python 序列的切片操作, 调用deepCopy()函数.
- 调用 ndarray 的 copy() 函数产生一个副本.
视图是数据的一个别称或引用, 通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝. 如果我们对视图进行修改, 它会影响到原始数据, 物理内存在同一位置.
- numpy 的切片操作返回原数据的视图.
- 调用 ndarray 的 view() 函数产生一个视图.
[例 11.1]
简单的赋值不会创建数组对象的副本. 相反, 它使用原始数组的相同id()来访问它. id()返回 Python 对象的通用标识符, 类似于 C 中的指针此外, 一个数组的任何变化都反映在另一个数组上. 例如, 一个数组的形状改变也会改变另一个数组的形状.
1 | import numpy as np |
输出结果为:
1 | 我们的数组是: |
12.1 View (ShallowCopy)
ndarray.view()
方会创建一个新的数组对象, 该方法创建的新数组的维数更改不会更改原始数据的维数. 但修改数据还是会跟随改变.
[例 12.2]
1 | import numpy as np |
输出结果是:
1 | 我们的数组是: |
使用切片创建视图修改数据会影响到原始数组, 见[例 11.1]
12.2 Copy (DeepCopy)
ndarray.copy()
函数创建一个副本. 对副本数据进行修改, 不会影响到原始数据, 它们物理内存不在同一位置.
Topic 13 Matrix
Numpy 中包含了一个矩阵库 numpy.matlib
, 该模块中的函数返回的是一个矩阵, 而不是 ndarray
对象.
13.1 Transpose
Numpy 中除了可以使用 numpy.transpose
函数来对换数组的维度, 还可以使用 T 属性.
13.2 numpy.matlib.empty
matlib.empty()
函数返回一个新的矩阵, 语法格式为:
1 | numpy.matlib.empty(shape, dtype, order) |
13.3 numpy.matlib.zeros
matlib.zeros()
函数创建一个以 0 填充的矩阵.
13.4 numpy.matlib.ones
matlib.ones()
函数创建一个以 1 填充的矩阵.
13.5 numpy.matlib.eye
matlib.eye()
函数返回一个对角线元素为 1 的矩阵, 语法格式如下:
1 | numpy.matlib.eye(n, M, k, dtype) |
[例 13.1]
1 | import numpy as np |
输出结果是:
1 | [[1 0 0] |
注:
numpy.matlib
is an optional sub-package ofnumpy
that must be imported separately. When you import justnumpy
without the sub-packagematlib
, then Python will be looking for.matlib
as an attribute of thenumpy
package. This attribute has not been assigned tonumpy
without importing numpy.matlib
13.6 numpy.matlib.identity
返回一个给定大小的单位矩阵, 语法如下:
1 | numpy.matlib.identity(n, dtype) |
13.7 numpy.matlib.rand
numpy.matlib.rand()
函数创建一个给定大小的矩阵, 数据是随机填充的, 介于 0~1.
[例 13.2]
1 | import numpy as np |
输出结果是:
1 | [[0.23519118 0.02624582 0.04782004] |
13.8 numpy.matrix & numpy.asarray & numpy.asmatrix
矩阵总是二维的, 而 ndarray 是一个 n 维数组. 两个对象都是可互换的.
1 | import numpy.matlib |
输出结果是:
1 | 使用 np.matrix 创建矩阵: |
Topic 14 Linear Algebra
Numpy 提供了线性代数函数库 linalg, 该库包含了线性代数所需的所有功能,可以看看下面的说明:
函数 | 描述 |
---|---|
numpy.dot |
对于一维数组是点积, 对于二维数组是矩阵的乘积 |
numpy.vdot |
无论是一维还是二维数组都是点积 |
numpy.inner |
两个数组的内积, 对于二维矩阵等同于 numpy.dot(a,b.T) |
numpy.matmul |
两个数组的矩阵积 |
numpy.linalg.det |
矩阵的行列式 |
numpy.linalg.solve |
求解线性矩阵方程 |
numpy.linalg.inv |
计算矩阵的乘法逆矩阵 |
14.1 numpy.dot
对于一维矩阵
1 | import numpy as np |
输出结果是:
1 | 对于一维矩阵, numpy.dot() 就是对应元素相乘: |
对于二维矩阵:
1 | import numpy as np |
输出结果是:
1 | 对于高维矩阵, numpy.dot() 就是矩阵乘法: |
14.2 numpy.vdot
无论是一维还是二维数组都是点积
1 | import numpy as np |
输出结果是:
1 | numpy.vdot() 就是对应元素相乘: |
14.3 numpy.inner
numpy.inner()
函数返回一维数组的向量内积. 对于更高的维度,它返回最后一个轴上的和的乘积. 等同于 numpy.dot(a, b.T)
1 | import numpy as np |
输出结果是:
1 | numpy.inner() 向量的内积: |
14.4 numpy.matmul
numpy.matmul
函数返回两个数组的矩阵乘积. 虽然它返回二维数组的正常乘积, 但如果任一参数的维数大于2, 则将其视为存在于最后两个索引的矩阵的栈,并进行相应广播.
1 | import numpy as np |
输出结果是:
1 | [[37 40] |
14.5 numpy.linalg.det
求行列式, 这里暂时就不举例了
14.6 numpy.linalg.solve
解线性方程组:
$x+2y=3$
$4x+5y=6$
1 | import numpy as np |
输出结果是:
1 | 方程组的解为: |
14.7 numpy.linalg.inv
求逆矩阵, 我暂时不举例子, 对概念不了解可取看我的 MIT Linear Algebra 的笔记.