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
2
3
import numpy as np
a = np.array([1,2,3])
print(a)

输出结果为:

1
[1,2,3]

[例 1.2] 创建二维数组

1
2
3
import numpy as np
a = np.array([[1,2],[3,4]])
print(a)

输出结果为:

1
2
[[1,2]
[3,4]]

[例 1.3] 指定最小维度

1
2
3
import numpy as np
a = np.array([1,2,3,4,5],ndmin=2)
print(a)

输出结果为:

1
[[1,2,3,4,5]]

[例 1.4] 指定数据类型

1
2
3
import numpy as np
a = np.array([1,2,3],dtype=complex)
print(a)

输出结果为:

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
2
3
import numpy as np
dt = np.dtype(np.int32)
print(dt)

输出结果为:

1
int32

[例 2.2] 使用缩写

1
2
3
import numpy as np
dt = np.dtype('i4')
print(dt)

输出结果为:

1
int32

[例 2.3] 指定字节顺序

1
2
3
import numpy as np
dt = np.dtype('<i4')
print(dt)

输出结果为:

1
int32

[例 2.4] 创建结构化数据类型

1
2
3
import numpy as np
dt = np.dtype([('age', np.int8)])
print(dt)

输出结果为:

1
[('age', 'i1')]

[例 2.5] 将数据类型应用于 ndarray 对象

1
2
3
4
import numpy as np
dt = np.dtype([('age','i1')])
a = np.array([(10,),(20,),(30,)], dtype=dt)
print(a)

输出结果为:

1
[(10,) (20,) (30,)]

[例 2.6] 类型字段名可以用于存取实际的 age 列

1
2
3
4
import numpy as np
dt = np.dtype([('age','i1')])
a = np.array([(10,),(20,),(30,)], dtype=dt)
print(a['age'])

输出结果为:

1
[10 20 30]

[例 2.7] 定义一个结构化数据类型 student, 包含字符串字段 name, 整数字段 age, 及浮点字段 marks, 并将这个 dtype 应用到 ndarray 对象.

1
2
3
4
import numpy as np
student = np.dtype([('name','S20'),('age','i1'),('marks','f4')])
a = np.array([('abc',21,50),('xyz',18,75)], dtype=student)
print(a)

输出结果为:

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
2
3
4
5
6
7
8
9
import numpy as np

a = np.arange(24)
print(a)
print(a.ndim)

b = a.reshape(2,4,3)
print(b)
print(b.ndim)

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
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

[例 3.2] 使用 ndarray.shape 来获取数组的维度, 返回一个元组, 这个元组的长度就是维度的数目, 即 ndim 属性 (秩). 比如, 一个二维数组, 其维度表示”行数”和”列数”.

1
2
3
4
import numpy as np

a = np.array([[1,2,3],[4,5,6]])
print(a.shape)

输出结果为:

1
(2,3)

调整数组大小

1
2
3
4
5
import numpy as np 

a = np.array([[1,2,3],[4,5,6]])
a.shape = (3,2)
print(a)

输出结果为:

1
2
3
[[1 2]
[3 4]
[5 6]]

[例 3.3] 使用 ndarray.size 来获取数组中的元素个数

1
2
3
4
import numpy as np 

a = np.array([[1,2,3],[4,5,6]])
print(a.size)

输出结果为:

1
6

Topic 4 Array Creation

ndarray 数组除了可以使用底层 ndarray 构造器来创建外, 也可以通过以下几种方式来创建.

4.1 numpy.empty

numpy.empty 方法用来创建一个指定形状 (shape), 数据类型 (dtype) 且未初始化(随机值)的数组:

1
2
3
4
5
6
numpy.empty(shape, dtype=float64, order='C')

# 参数说明
# shape: 数组形状, 可以是 list 也可以是 tuple
# dtype: 数据类型, 默认为 float64
# order: 有"C"和"F"两个选项,分别代表, 行优先和列优先, 在计算机内存中的存储元素的顺序.

[例 4.1]

1
2
3
4
import numpy as np

a = np.empty([3,3],dtype=np.int8)
print(a)

输出结果为:

1
2
3
[[  0   0   0]
[ 0 0 0]
[ 0 -80 0]]

4.2 numpy.zeros

创建指定大小的数组, 数组元素以 0 来填充:

1
numpy.zeros(shape, dtype=float64, order='C')

[例 4.2]

1
2
3
4
import numpy as np

a = np.zeros([3,3], dtype='f8')
print(a)

输出结果为:

1
2
3
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

4.3 numpy.ones

创建指定形状的数组, 数组元素以 1 来填充:

1
numpy.ones(shape, dtype=float64, order='C')

[例 4.3]

1
2
3
4
import numpy as np

a = np.ones([3,3], dtype='i2')
print(a)

输出结果为:

1
2
3
[[1 1 1]
[1 1 1]
[1 1 1]]

4.4 numpy.eye

创建单位矩阵

[例 4.4]

1
2
3
import numpy as np
a = np.eye(5, dtype='i8')
print(a)

输出结果为:

1
2
3
4
5
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]

4.5 numpy.random.randn

创建标准正态分布随机数组:

1
numpy.random.randn(d0, d1, d2, ...)

[例 4.5]

1
2
3
4
import numpy as np

a = np.random.randn(3,3)
print(a)

输出结果为:

1
2
3
[[-1.49392311  0.88590821 -0.44375056]
[-0.19250296 -0.72078554 0.65790911]
[-0.03507985 -0.2863142 -0.73509595]]

4.6 numpy.random.rand

创建元素位于 [0, 1) 的随机数组

[例 4.6]

1
2
3
4
import numpy as np

a = np.random.rand(3,3)
print(a)

输出结果为:

1
2
3
[[0.06404836 0.47933279 0.7514547 ]
[0.51344134 0.36646154 0.68031114]
[0.31175219 0.53322371 0.26923007]]

4.7 numpy.random.randint

利用 randint(low, high, size) 创建一个整数型指定范围在 [low, high] 之间的数组.

[例 4.7]

1
2
3
4
import numpy as np

a = np.random.randint(100,200,[3,3])
print(a)

输出结果为:

1
2
3
[[121 102 170]
[104 166 144]
[120 172 129]]

4.8 numpy.asarray

numpy.asarray 类似 numpy.array, 但 numpy.asarray 参数只有三个, 比 numpy.array 少两个.

1
2
3
4
5
6
numpy.asarray(object, dtype=None, order=None)

# 参数说明
# object: 可以是列表, 列表的元组, 元组, 元组的元组, 元组的列表和多维数组
# dtype: 数据类型
# order: 可选, 有"C"和"F"两个选项,分别代表, 行优先和列优先, 在计算机内存中的存储元素的顺序.

[例 4.8]

1
2
3
4
5
import numpy as np

x = [1,2,3]
a = np.asarray(x, dtype='f8')
print(a)

输出结果为:

1
[1. 2. 3.]

4.9 numpy.frombuffer

numpy.frombuffer 接受 buffer 输入参数, 以流的形式读入转化成 ndarray 对象.

1
2
3
4
5
6
7
numpy.frombuffer(buffer, dtype=float64, count=-1, offset=0)

# 参数说明
# buffer: 可以是任意对象, 以流的形式读入.
# dtype: 返回数组的数据类型
# count: 读取的数据数量, 默认为-1, 读取所有数据.
# offset: 读取初始位置, 默认为 0.

[例 4.9]

1
2
3
4
5
import numpy as np

s = b'Hello World'
a = np.frombuffer(s, dtype='S1')
print(a)

输出结果为:

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
2
3
4
5
6
numpy.fromiter(iterable, dtype, count=-1)

# 参数说明
# iterable: 可迭代对象
# dtype: 返回数组的数据类型
# count: 读取的数据数量, 默认为-1, 读取所有数据

[例 4.10]

1
2
3
4
5
6
7
import numpy as np

lt = range(5)
itr = iter(lt)

a = np.fromiter(itr, dtype='i4', count=-1)
print(a)

输出结果为:

1
[0 1 2 3 4]

4.11 numpy.arange

使用 arange 函数创建数值范围并返回 ndarray 对象, 函数格式如下:

1
2
3
4
5
6
7
numpy.arange(start, stop, step, dtype)

# 参数说明
# start: 起始值, 默认为 0
# stop: 终止值 (不包含)
# step: 步长, 默认为 1
# dtype: 指定数据类型

[例 4.11]

1
2
3
4
import numpy as np

a = np.arange(5, dtype='f8')
print(a)

输出结果为:

1
[0.  1.  2.  3.  4.]

4.12 numpy.linspace

numpy.linspace 函数用于创建一个一维数组, 数组是一个等差数列构成的, 格式如下:

1
2
3
4
5
6
7
8
9
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

# 参数说明
# start: 序列的起始值
# stop: 序列的终止值, 如果endpoint为true, 该值包含于数列中
# num: 要生成的等步长的样本数量, 默认为50
# endpoint: 该值为 true 时, 数列中包含stop值, 反之不包含, 默认是True
# retstep: 如果为 True 时, 生成的数组中会显示间距, 反之不显示.
# dtype: 数据类型

[例 4.12]

1
2
3
4
5
import numpy as np

a = np.linspace(0,100,21,retstep=True,dtype='f8')
print(a)
type(a)

输出结果为:

1
2
3
(array([  0.,   5.,  10.,  15.,  20.,  25.,  30.,  35.,  40.,  45.,  50.,
55., 60., 65., 70., 75., 80., 85., 90., 95., 100.]), 5.0)
<class 'tuple'>

我们也可以使用 reshape 来改变数组维度

1
2
3
4
5
import numpy as np

a = np.linspace(0,100,21,retstep=False,dtype='f8')
b = a.reshape(3,7)
print(b)

输出结果为:

1
2
3
[[  0.   5.  10.  15.  20.  25.  30.]
[ 35. 40. 45. 50. 55. 60. 65.]
[ 70. 75. 80. 85. 90. 95. 100.]]

4.13 numpy.logspace

numpy.logspace 函数用于创建一个数组中元素取对数后均匀分布的数组, 格式如下:

1
2
3
4
5
6
7
8
9
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

# 参数说明
# start: 序列的起始值为 base^start
# stop: 序列的终止值为 base^stop (若 endpoint=True 的情况)
# num: 要生成的等步长的样本数量, 默认为 50
# endpoint: 是否包含 base^stop
# base: 对数 log 的底数
# dtype: 数据类型

注意, numpy.logspace 代码等效于代码:

1
2
a = np.linspace(start,stop, num=num, base=base, endpoint=True)
result = np.power(a, base)

[例 4.13]

1
2
3
4
import numpy as np

a = np.logspace(1,2,10,base=2)
print(a)

输出结果是:

1
2
[2.         2.16011948 2.33305808 2.5198421  2.72158    2.93946898
3.1748021 3.42897593 3.70349885 4. ]

Topic 5 Slice and Index

5.1 Slice

ndarray对象的内容可以通过索引或切片来访问和修改, 与 Python 中 list 的切片操作一样. ndarray 数组可以基于 0 - n 的下标进行索引, 切片对象可以通过内置的 slice 函数, 并设置 start, stop 及 step 参数进行, 从原数组中切割出一个新数组.

[例 5.1]

1
2
3
4
5
import numpy as np

a = np.arange(10)
s = slice(2,7,2)
print(a[s])

输出结果为:

1
[2 4 6]

[例 5.2]

我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作:

1
2
3
4
5
import numpy as np

a = np.arange(10)
b = a[2:7:2]
print(b)

输出结果为:

1
[2 4 6]

[例 5.3]

同样我们可以提取单个元素

1
2
3
4
5
import numpy as np

a = np.arange(10)
b = a[2]
print(b)

输出结果为

1
2

[例 5.4]

多维数组也同样适用

1
2
3
4
5
6
7
import numpy as np

a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print(a)

print('从数组索引 a[1:] 处开始切割') # 还记得之前我们讲的轴的概念吗?
print(a[1:])

输出结果为:

1
2
3
4
5
6
[[1 2 3]
[3 4 5]
[4 5 6]]
从数组索引 a[1:] 处开始切割
[[3 4 5]
[4 5 6]]

[例 5.5]

在多维数组的切片中, 使用 , 区分维数.

1
2
3
4
5
6
import numpy as np

a = np.arange(12)
a.shape = 3,4
print(a)
print(a[0:2,1:3]) # 第1,2 行 和 第 2,3 列

输出结果为:

1
2
3
4
5
[[ 0  1  2  3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[1 2]
[5 6]]

5.2 Index

NumPy 比一般的 Python 序列提供更多的索引方式, 除了之前看到的用整数和切片的索引外, 数组可以由整数数组索引、布尔索引及花式索引.

5.2.1 Array Indexing

[例 5.6]

在多维数组中, 非连续索引切片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.arange(0,6)
b = np.arange(0,25)
b.shape(5,5)

# 切片向量既可以是 ndarrat 也可以是 list
r = np.array([0,1,4]) # r = [0,1,4]
c = [1,2,4] # c = np.array([1,2,4])

print('a:\n',a)
print('a_slice:\n',a[r])

print('b:\n',b)
print('b_slice:\n',b[r,:][:,c])

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a:
[0 1 2 3 4 5]
a_slice:
[0 1 4]
b:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
b_slice:
[[ 1 2 4]
[ 6 7 9]
[21 22 24]]

[例 5.7]

获取数组中(0,0), (1,1) 和 (2,0)位置处的元素.

1
2
3
4
5
import numpy as np

x = np.array([[1,2],[3,4],[5,6]])
y = x[[0,1,2],[0,1,0]]
print(y)

输出结果为:

1
[1 4 5]

[例 5.8]

获取了 4X3 数组中的四个角的元素. 行索引是 [0,0] 和 [3,3], 而列索引是 [0,2] 和 [0,2].

1
2
3
4
5
6
7
8
import numpy as np

x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print('我们的数组是:\n',x)
rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]])
y = x[rows,cols]
print('这个数组的四个角元素是:\n',y)

输出结果是:

1
2
3
4
5
6
7
8
9
我们的数组是:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]

这个数组的四个角元素是:
[[ 0 2]
[ 9 11]]

5.2.2 Bool Indexing

我们可以通过一个布尔数组来索引目标数组. 布尔索引通过布尔运算 (如: 比较运算符) 来获取符合指定条件的元素的数组.

[例 5.9]

获取大于 5 的元素

1
2
3
4
5
6
import numpy as np

x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print('我们的数组是:\n',x)
y = x[x>5]
print('大于 5 的元素是:\n',y)

输出结果是:

1
2
3
4
5
6
7
我们的数组是:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
大于 5 的元素是:
[ 6 7 8 9 10 11]

[例 5.10]

使用 ~ (取补运算符) 来过滤 NaN

1
2
3
4
5
import numpy as np

a = np.array([np.nan,1,2,np.nan,3,4,5])
b = a[~np.isnan(a)]
print(b)

输出结果是:

1
[1. 2. 3. 4. 5.]

[例 5.11]

从数组中过滤掉非复数元素

1
2
3
4
5
import numpy as np

a = np.array([1,2+6j,5,3.5+5j])
b = a[np.iscomplex(a)]
print(b)

输出结果是:

1
[2. +6.j 3.5+5.j]

5.2.3 Fancy Indexing

花式索引指的是利用整数数组进行索引. 花式索引根据索引数组的值作为目标数组的某个轴的下标来取值. 对于使用一维整型数组作为索引, 如果目标是一维数组, 那么索引的结果就是对应位置的元素; 如果目标是二维数组, 那么就是对应下标的行.

花式索引跟切片不一样, 它总是将数据复制到新数组中.

[例 5.12]

传入顺序索引数组

1
2
3
4
5
import numpy as np

x = np.arange(32).reshape(8,4)
y = x[[4,2,1,7]]
print(y)

输出结果是:

1
2
3
4
[[16 17 18 19]
[ 8 9 10 11]
[ 4 5 6 7]
[28 29 30 31]]

[例 5.13]

传入倒序索引数组

1
2
3
4
5
import numpy as np

x = np.arange(32).reshape(8,4)
y = x[[-4,-2,-1,-7]]
print(y)

输出结果是:

1
2
3
4
[[16 17 18 19]
[24 25 26 27]
[28 29 30 31]
[ 4 5 6 7]]

[例 5.14]

传入多个索引数组, 使用 np.ix_

1
2
3
4
5
import numpy as np

x = np.arange(32).reshape(8,4)
y = x[np.ix_([1,5,7,2],[0,3,1,2])]
print(y)

输出结果是:

1
2
3
4
[[ 4  7  5  6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]

注:

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
2
3
4
5
6
import numpy as np

a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
c = a*b
print(c)

输出结果是:

1
[ 10  40  90 160]

[例 6.2]

当运算中的 2 个数组的形状不同时, numpy 将自动触发广播机制. 如:

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([[0,0,0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([1,2,3])
print(a+b)

输出结果是:

1
2
3
4
[[ 1  2  3]
[11 12 13]
[21 22 23]
[31 32 33]]

注:

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. 两个数组各维度大小从后往前比对均一致

看个例子:

1
2
3
4
5
6
7
8
9
import numpy as np

A = np.zeros((2,5,3,4))
B = np.zeros((3,4))
print((A+B).shape) # 输出 (2, 5, 3, 4)

A = np.zeros((4))
B = np.zeros((3,4))
print((A+B).shape) # 输出(3,4)

举个反例:

1
2
3
4
5
6
7
8
import numpy as np

A = np.zeros((2,5,3,4))
B = np.zeros((2,4))
print((A+B).shape)

# 这将会报错:
# ValueError: operands could not be broadcast together with shapes (2,5,3,4) (2,4)
  1. 两个数组存在一些维度大小不相等时, 有一个数组的该不相等维度大小为1

这是对上面那条规则的补充,虽然存在多个维大小不一致,但是只要不相等的那些维有一个数组的该大小是1 就可以.

看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
A = np.zeros((2,5,3,4))
B = np.zeros((3,1))
print((A+B).shape) # 输出:(2, 5, 3, 4)

A = np.zeros((2,5,3,4))
B = np.zeros((2,1,1,4))
print((A+B).shape) # 输出:(2, 5, 3, 4)

A = np.zeros((1))
B = np.zeros((3,4))
print((A+B).shape) # 输出(3,4)

同样看个反例:

1
2
3
4
5
6
7
8
import numpy as np

A = np.zeros((2,5,3,4))
B = np.zeros((2,4,1,4))
print((A+B).shape)

# 这将会报错
# ValueError: operands could not be broadcast together with shapes (2,5,3,4) (2,4,1,4)

Topic 7 Array Iteration

7.1 numpy.nditer

NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式.

[例 7.1]

使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代.

1
2
3
4
5
6
7
8
import numpy as np

a = np.arange(6).reshape(2,3)
print('原始数组:\n',a)
print('\n')
print('迭代数组元素:')
for x in np.nditer(a):
print(x,end=', ')

输出结果是:

1
2
3
4
5
6
原始数组:
[[0 1 2]
[3 4 5]]

迭代数组元素:
0, 1, 2, 3, 4, 5,

注: 你如果有一定的编程基础, 我们也可以使用 nested for loop 来进行遍历.

以上实例不是使用标准 C 或者 Fortran 顺序, 选择的顺序是和数组内存布局一致的, 这样做是为了提升访问的效率, 默认是行序优先 (row-major order,或者说是 C-order). 这反映了默认情况下只需访问每个元素, 而无需考虑其特定顺序. 我们可以通过迭代上述数组的转置来看到这一点, 并与以 C 顺序访问数组转置的 copy 方式做对比, 如下:

[例 7.2]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.arange(6).reshape(2,3)
for x in np.nditer(a.T):
print(x, end=', ')

print('\n')

for x in np.nditer(a.T.copy(order='C')):
print(x, end=', ')

输出结果是:

1
2
3
0, 1, 2, 3, 4, 5, 

0, 3, 1, 4, 2, 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.arange(0,60,5)
a.shape = 3,4
print('原始数组是:\n',a)
print('\n')
print('原始数组的转置是:\n',a.T)
print('\n')
print('以 C 风格遍历:\n',a)
for x in np.nditer(a, order='C'):
print(x,end=', ')
print('\n')
print('以 F 风格遍历:\n',a)
for x in np.nditer(a, order='F'):
print(x,end=', ')

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]


原始数组的转置是:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]


以 C 风格遍历:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,


以 F 风格遍历:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55,

7.3 Modify Array

我们也可以在遍历过程中修改数组中元素的值.

nditer 对象有另一个可选参数 op_flags. 默认情况下, nditer 将视待迭代遍历的数组为只读对象 (read-only), 为了在遍历数组的同时, 实现对数组元素值得修改, 必须指定 read-write 或者 write-only 的模式.

[例 7.4]

1
2
3
4
5
6
7
8
9
import numpy as np

a = np.arange(0,60,5)
a.shape = 3,4
print('原始数组是:\n',a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = x*2
print('修改后的数组是:\n',a)

输出结果是:

1
2
3
4
5
6
7
8
9
10
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]


修改后的数组是:
[[ 0 10 20 30]
[ 40 50 60 70]
[ 80 90 100 110]]

7.4 Return New Array Through Iteration

我们还可以通过修改 nditer 的 flags 参数来使其返回遍历值产生的新数组:

[例 7.5]

1
2
3
4
5
6
7
8
9
import numpy as np

a = np.arange(0,60,5)
a.shape = 3,4
print('原始数组是:\n',a)
print('\n')
print('返回新的数组:')
for x in np.nditer(a, flags=['external_loop'], order='F'):
print(x, end=', ')

输出结果是:

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
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np 

a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('第一个数组为:')
print (a)
print ('\n')
print ('第二个数组为:')
b = np.array([1,2,3,4], dtype=int)
print (b)
print ('\n')
print ('修改后的数组为:')
for x,y in np.nditer([a,b]):
print("%d:%d" % (x,y), end=", ")

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
第一个数组为:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]


第二个数组为:
[1 2 3 4]


修改后的数组为:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,

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
2
3
4
5
6
7
8
import numpy as np

a = np.arange(8)
print('原始数组:\n',a)
print('\n')

b = np.reshape(a, [4,2], order='F')
print('修改后的数组:\n',b)

输出结果是:

1
2
3
4
5
6
7
8
9
原始数组:
[0 1 2 3 4 5 6 7]


修改后的数组:
[[0 4]
[1 5]
[2 6]
[3 7]]

8.1.2 numpy.ndarray.flat

numpy.ndarray.flat 是一个数组元素迭代器, 例子如下:

[例 8.2]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.arange(9).reshape(3,3)
print('原始数组:')
for row in a:
print(row)

print('迭代之后的数组:')
for element in a.flat:
print(element)

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
原始数组:
[0 1 2]
[3 4 5]
[6 7 8]
迭代后的数组:
0
1
2
3
4
5
6
7
8

8.1.3 numpy.ndarray.flatten

numpy.ndarray.flatten 返回一份数组拷贝, 对拷贝所做的修改不会影响原始数组,格式如下:

1
ndarray.flatten(order='C')

[例 8.3]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.arange(8).reshape(2,4)
print('原数组:\n',a)
print('\n')

print('按行展开的数组 (默认):\n',a.flatten())
print('\n')

print('按 F 展开的数组:\n',a.flatten(order='F'))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
原数组:
[[0 1 2 3]
[4 5 6 7]]


按行展开的数组 (默认):
[0 1 2 3 4 5 6 7]


按 F 展开的数组:
[0 4 1 5 2 6 3 7]

8.1.4 numpy.ravel

numpy.ravel() 展平的数组元素, 顺序通常是”C风格”, 返回的是数组视图, 修改会影响原始数组. 该函数接收两个参数:

1
numpy.ravel(a, order='C')

[例 8.4]

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.arange(8).reshape(2,4)

print('原数组:\n',a)
print('\n')

print('按行展开的数组 (默认):\n',np.ravel(a))
print('\n')

print('按 F 展开的数组:\n',np.ravel(a,order='F'))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
原数组:
[[0 1 2 3]
[4 5 6 7]]


按行展开的数组 (默认):
[0 1 2 3 4 5 6 7]


按 F 展开的数组:
[0 4 1 5 2 6 3 7]

8.2 Concatenate Array

函数 描述
concatenate 连接沿现有轴的数组序列
stack 沿着新的轴加入一系列数组。
hstack 水平堆叠序列中的数组(列方向)
vstack 竖直堆叠序列中的数组(行方向)

8.2.1 numpy.concatenate

numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组, 格式如下:

1
2
3
4
5
numpy.concatenate((a1,a2,...),axis=0)

# 参数说明
# a1, a2, ... 相同类型的数组
# axis: 沿着它连接数组的轴, 默认为 0. 注: 回一下 Topic 3 里面对轴的介绍

我们看一个例子:

[例 8.5]

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

print('第一个数组:\n',a)
print('\n')
print('第二个数组:\n',b)
print('\n')
print('沿轴 0 连接两个数组:\n', np.concatenate((a,b),axis=0))
print('\n')
print('沿轴 1 连接两个数组:\n', np.concatenate((a,b),axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
第一个数组:
[[1 2]
[3 4]]


第二个数组:
[[5 6]
[7 8]]


沿轴 0 连接两个数组:
[[1 2]
[3 4]
[5 6]
[7 8]]


沿轴 1 连接两个数组:
[[1 2 5 6]
[3 4 7 8]]

8.2.2 numpy.stack

用法和 numpy.concatenate 类似, 但这不是连接, 而是堆叠, 格式如下:

1
2
3
4
5
numpy.stack(arrays, axis)

# 参数说明
# arrays: 相同形状的数组序列
# axis: 返回数组中的轴,输入数组沿着它来堆叠

看一个例子:

[例 8.6]

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

print('第一个数组:\n',a)
print('\n')
print('第二个数组:\n',b)
print('\n')
print('沿轴 0 堆叠两个数组:\n', np.stack((a,b),axis=0))
print('\n')
print('沿轴 1 堆叠两个数组:\n', np.stack((a,b),axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
第一个数组:
[[1 2]
[3 4]]


第二个数组:
[[5 6]
[7 8]]


沿轴 0 堆叠两个数组:
[[[1 2]
[3 4]]

[[5 6]
[7 8]]]


沿轴 1 堆叠两个数组:
[[[1 2]
[5 6]]

[[3 4]
[7 8]]]

8.2.3 numpy.hstack

numpy.hstacknumpy.stack 函数的变体, 它通过水平堆叠来生成数组.

[例 8.7]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

print('第一个数组:\n',a)
print('\n')
print('第二个数组:\n',b)
print('\n')
print('水平堆叠:\n',np.hstack((a,b))) # 接受 tuple 或 list

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
第一个数组:
[[1 2]
[3 4]]


第二个数组:
[[5 6]
[7 8]]


水平堆叠:
[[1 2 5 6]
[3 4 7 8]]

8.2.4 numpy.vstack

numpy.vstacknumpy.stack 函数的变体, 它通过垂直堆叠来生成数组.

[例 8.8]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

print('第一个数组:\n',a)
print('\n')
print('第二个数组:\n',b)
print('\n')
print('竖直堆叠:\n',np.vstack((a,b))) # 接受 tuple 或 list

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
第一个数组:
[[1 2]
[3 4]]


第二个数组:
[[5 6]
[7 8]]


竖直堆叠:
[[1 2]
[3 4]
[5 6]
[7 8]]

8.3 Split Array

函数 数组及操作
split 将一个数组分割为多个子数组
hsplit 将一个数组水平分割为多个子数组(按列)
vsplit 将一个数组垂直分割为多个子数组(按行)

8.3.1 numpy.split

numpy.split 函数沿特定的轴将数组分割为子数组, 格式如下:

1
2
3
4
5
6
numpy.split(arr, indicies_or_sections, axis)

# 参数说明
# arr: 待分割的数组
# indicies_or_sections: 如果是一个整数, 就用该数平均切分, 如果是一个数组, 为沿轴切分的位置(左开右闭)
# axis: 沿着哪个维度进行切向,默认为0,横向切分. 为1时,纵向切分.

[例 8.9]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.arange(9).reshape(3,3)
print('第一个数组:\n',a)
print('\n')
print('横向切分:\n',np.split(a,3,axis=0))
print('\n')
print('纵向切分:\n',np.split(a,3,axis=1))
print('\n')
print('传入数组不均匀切分:\n',np.split(a,[2,],axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
第一个数组:
[[0 1 2]
[3 4 5]
[6 7 8]]


横向切分:
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]


纵向切分:
[array([[0],
[3],
[6]]), array([[1],
[4],
[7]]), array([[2],
[5],
[8]])]


传入数组不均匀切分:
[array([[0, 1],
[3, 4],
[6, 7]]), array([[2],
[5],
[8]])]

8.3.2 numpy.hsplit

numpy.hsplit 函数用于水平分割数组, 通过指定要返回的相同形状的数组数量来拆分原数组.

[例 8.10]

1
2
3
4
5
6
import numpy as np

a = np.floor(10 * np.random.random((2, 6)))
print('原数组:\n',a)
print('\n')
print('拆分后:\n',np.hsplit(a,3))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
原数组:
[[1. 1. 8. 7. 4. 3.]
[2. 7. 0. 4. 8. 6.]]



拆分后:
[array([[1., 1.],
[2., 7.]]), array([[8., 7.],
[0., 4.]]), array([[4., 3.],
[8., 6.]])]

8.3.3 numpy.vsplit

numpy.vsplit 沿着垂直轴分割, 其分割方式与hsplit用法相同。

[例 8.11]

1
2
3
4
5
6
import numpy as np

a = np.arange(16).reshape(4,4)
print('原数组:\n',a)
print('\n')
print('拆分后:\n',np.vsplit(a,2))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
原数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]


拆分后:
[array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]

8.4 Add and Delete Elements of Array

函数 元素及描述
append 将值添加到数组末尾
insert 沿指定轴将值插入到指定下标之前
delete 删掉某个轴的子数组,并返回删除后的新数组
unique 用于移去数组中的重复值

8.4.1 numpy.append

numpy.append 函数在数组的末尾添加值. 追加操作会分配整个数组, 并把原来的数组复制到新数组中. 此外, 输入数组的维度必须匹配否则将生成ValueError.

1
2
3
4
5
6
numpy.append(arr, values, axis=None)

# 参数说明
# arr: 原数组
# values: 要向arr添加的值, 需要和arr形状相同 (除了要添加的轴)
# axis: 默认为 None. 当axis无定义时,是横向添加, 返回总是为一维数组! 当axis有定义的时候, 分别为0和1的时候. 当axis有定义的时候, 分别为0和1的时候 (列数要相同). 当axis为1时, 数组是加在右边 (行数要相同).

[例 8.12]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[1,2,3],[4,5,6]])
print('原数组:\n',a)
print('\n')
print('向数组添加元素,不定义 axis:\n',np.append(a,[7,8,9]))
print('\n')
print('沿轴 0 添加元素:\n',np.append(a,[[7,8,9]],axis=0))
print('\n')
print('沿轴 1 添加元素:\n',np.append(a,[[5,5,5],[7,8,9]],axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
原数组:
[[1 2 3]
[4 5 6]]


向数组添加元素,不定义 axis:
[1 2 3 4 5 6 7 8 9]


沿轴 0 添加元素:
[[1 2 3]
[4 5 6]
[7 8 9]]


沿轴 1 添加元素:
[[1 2 3 5 5 5]
[4 5 6 7 8 9]]

8.4.2 numpy.insert

numpy.insert 函数在给定索引之前, 沿给定轴在输入数组中插入值.

插入函数会返回一个新数组. 此外, 如果未提供轴, 则输入数组会被展开, 格式如下:

1
2
3
4
5
6
7
numpy.insert(arr, obj, values, axis)

# 参数说明
# arr: 待插入数组
# obj: 插入处的索引值
# values: 要插入的值
# axis: 沿轴插入, 如果未提供, 则待插入数组会被展开

[例 8.13]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[1,2],[3,4],[5,6]])
print('原数组:\n',a)
print('\n')
print('未传递 Axis 参数, 在插入之前输入数组会被展开:\n', np.insert(a,3,[11,12]))
print('\n')
print('传递 Axis 参数, 沿轴 0 广播:\n',np.insert(a,1,[11],axis=0))
print('\n')
print('传递 Axis 参数, 沿轴 1 广播:\n',np.insert(a,1,[11],axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
原数组:
[[1 2]
[3 4]
[5 6]]


未传递 Axis 参数, 在插入之前输入数组会被展开:
[ 1 2 3 11 12 4 5 6]


传递 Axis 参数, 沿轴 0 广播:
[[ 1 2]
[11 11]
[ 3 4]
[ 5 6]]


传递 Axis 参数, 沿轴 1 广播:
[[ 1 11 2]
[ 3 11 4]
[ 5 11 6]]

8.4.3 numpy.delete

numpy.delete 函数返回从输入数组中删除指定子数组的新数组. 与 insert() 函数的情况一样, 如果未提供轴参数, 则输入数组将展开, 格式如下:

1
2
3
4
5
6
numpy.delete(arr, obj, axis)

# 参数说明
# arr: 输入数组
# obj: 整数或者整数数组, 待删除的索引
# axis: 按指定轴删除, 如果未提供, 则输入数组会被展开

[例 8.14]

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.arange(12).reshape(3,4)
print('原数组:\n',a)
print('\n')
print('未传递 Axis 参数, 在插入之前输入数组会被展开:\n', np.delete(a,5))
print('\n')
print('删除第二行:\n', np.delete(a,1,axis=0))
print('\n')
print('删除第二列:\n', np.delete(a,1,axis=1))
print('包含从数组中删除的替代值的切片:\n', np.delete(a, np.s_[::2]))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
原数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]


未传递 Axis 参数, 在插入之前输入数组会被展开:
[ 0 1 2 3 4 6 7 8 9 10 11]


删除第二行:
[[ 0 1 2 3]
[ 8 9 10 11]]


删除第二列:
[[ 0 2 3]
[ 4 6 7]
[ 8 10 11]]


包含从数组中删除的替代值的切片:
[ 1 3 5 7 9 11]

8.4.4 numpy.unique

numpy.unique 函数用于去除数组中的重复元素, 用法如下:

1
2
3
4
5
6
7
numpy.unique(arr, return_index, return_inverse, return_counts)

# 参数说明
# arr: 输入数组,如果不是一维数组则会展开
# return_index: 如果为true, 返回新列表元素在旧列表中的位置 (下标), 并以列表形式存储
# return_inverse: 如果为true, 返回旧列表元素在新列表中的位置 (下标), 并以列表形式储
# return_counts: 如果为true, 返回去重数组中的元素在原数组中的出现次数

[例 8.15]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

a = np.array([5,2,6,2,7,5,6,8,2,9])
print('原数组:\n',a)
print('\n')
print('去重之后的数组:\n',np.unique(a))
print('\n')
print('新列表元素在旧列表中的下标:')
u,indicies = np.unique(a, return_index=True)
print(indicies)
print('\n')
print('旧列表元素在新列表中的下标:')
u,indicies = np.unique(a, return_inverse=True)
print(indicies)
print('使用下标重构原数组:\n',u[indicies])
print('\n')
print('返回去重元素的重复数量:')
u,counts = np.unique(a, return_counts=True)
print(u)
print(counts)

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
原数组:
[5 2 6 2 7 5 6 8 2 9]


去重之后的数组:
[2 5 6 7 8 9]


新列表元素在旧列表中的下标:
[1 0 2 4 7 9]


旧列表元素在新列表中的下标:
[1 0 2 0 3 1 2 4 0 5]


使用下标重构原数组:
[5 2 6 2 7 5 6 8 2 9]


print('返回去重元素的重复数量:')
[2 5 6 7 8 9]
[3 2 2 1 1 1]

Topic 9 Math Functions

9.1 Trigonometric Functions

NumPy 提供了标准的三角函数:sin()、cos()、tan().

[例 9.1]

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([0,30,45,60,90])
print('不同角度的正弦值:\n',np.sin(a*np.pi/180))
print('\n')
print('不同角度的余弦值:\n',np.cos(a*np.pi/180))
print('\n')
print('不同角度的正切值:\n',np.tan(a*np.pi/180))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
不同角度的正弦值:
[0. 0.5 0.70710678 0.8660254 1. ]


不同角度的余弦值:
[1.00000000e+00 8.66025404e-01 7.07106781e-01 5.00000000e-01
6.12323400e-17]


不同角度的正切值:
[0.00000000e+00 5.77350269e-01 1.00000000e+00 1.73205081e+00
1.63312394e+16]

NumPy 提供了标准的三角函数的反函数: arcsin, arccos, arctan. 就不再举例了.

9.2 numpy.floor

numpy.floor() 返回小于或者等于指定表达式的最大整数, 即向下取整.

[例 9.2]

1
2
3
4
5
6
import numpy as np

a = np.array([-1.7,1.5,-0.2,0.6,10])
print('原数组:\n',a)
print('\n')
print('修改后的数组:\n',np.floor(a))

输出结果是:

1
2
3
4
5
6
原数组:
[-1.7 1.5 -0.2 0.6 10. ]


修改后的数组:
[-2. 1. -1. 0. 10.]

9.3 numpy.ceil

numpy.ceil() 返回大于或者等于指定表达式的最小整数, 即向上取整.

[例 9.3]

1
2
3
4
5
6
import numpy as np

a = np.array([-1.7,1.5,-0.2,0.6,10])
print('原数组:\n',a)
print('\n')
print('修改后的数组:\n',np.ceil(a))

输出结果是:

1
2
3
4
5
6
原数组:
[-1.7 1.5 -0.2 0.6 10. ]


修改后的数组:
[-1. 2. -0. 1. 10.]

9.4 Arithmatic Functions

NumPy 算术函数包含简单的加减乘除: add(), subtract(), multiply()divide(). 需要注意的是数组必须具有相同的形状或符合数组广播规则. 在这里, 我就不举例子了.

9.5 numpy.reciprocal

numpy.reciprocal() 函数返回参数逐元素的倒数. 如 1/4 倒数为 4/1.

[例 9.4]

1
2
3
4
5
6
import numpy as np

a = np.array([0.25, 1.33, 1, 100])
print('原数组:\n',a)
print('\n')
print('渠倒数的数组:\n',np.reciprocal(a))

输出结果是:

1
2
3
4
5
6
原数组:
[ 0.25 1.33 1. 100. ]


渠倒数的数组:
[4. 0.7518797 1. 0.01 ]

9.6 numpy.power

numpy.power() 函数将第一个输入数组中的元素作为底数, 计算它与第二个输入数组中相应元素的幂.

[例 9.5]

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([10,100,1000])
print('原数组:\n',a)
print('\n')
print('调用 power 函数(固定的幂):\n',np.power(a,2))
print('\n')
print('调用 power 函数(多个幂):\n',np.power(a,[1,2,3]))

输出结果是:

1
2
3
4
5
6
7
8
9
10
原数组:
[ 10 100 1000]


调用 power 函数(固定的幂):
[ 100 10000 1000000]


调用 power 函数(多个幂):
[ 10 10000 1000000000]

9.7 numpy.mod

numpy.mod() 计算输入数组中相应元素的相除后的余数. 函数 numpy.remainder() 也产生相同的结果.

[例 9.6]

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.array([10,20,30])
b = np.array([3,5,7])
print('第一个数组:\n',a)
print('\n')
print('第二个数组:\n',b)
print('\n')
print('调用 mod 函数:\n',np.mod(a,b))
print('\n')
print('调用 remainder 函数:\n',np.remainder(a,b))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
第一个数组:
[10 20 30]


第二个数组:
[3 5 7]


调用 mod 函数:
[1 0 2]


调用 remainder 函数:
[1 0 2]

Topic 10 Stat Functions

10.1 numpy.amin & numpy.amax

  • numpy.amin(arr, axis=None) 用于计算数组中的元素沿指定轴的最小值.

  • numpy.amax(arr, axis=None) 用于计算数组中的元素沿指定轴的最大值.

[例 10.1]

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

a = np.array([[3,7,5],[8,4,3],[2,4,9]])
print('原数组:\n',a)
print('\n')
print('调用 amin() 函数且轴数为 0:\n',np.amin(a,axis=0))
print('\n')
print('调用 amin() 函数且轴数为 1:\n',np.amin(a,axis=1))
print('\n')
print('调用 amax() 函数且轴数为 0:\n',np.amax(a,axis=0))
print('\n')
print('调用 amax() 函数且轴数为 1:\n',np.amax(a,axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
原数组:
[[3 7 5]
[8 4 3]
[2 4 9]]


调用 amin() 函数且轴数为 0:
[2 4 3]


调用 amin() 函数且轴数为 1:
[3 3 2]


调用 amax() 函数且轴数为 0:
[8 7 9]


调用 amax() 函数且轴数为 1:
[7 8 9]

10.2 numpy.ptp

numpy.ptp(arr, axis=None) 函数计算数组中元素最大值与最小值的差 (最大值 - 最小值).

[例 10.2]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[3,7,5],[8,4,3],[2,4,9]])
print('原数组:\n',a)
print('\n')
print('调用 ptp() 函数且不指定轴数:\n',np.ptp(a))
print('\n')
print('调用 ptp() 函数且轴数为 0:\n',np.ptp(a,axis=0))
print('\n')
print('调用 ptp() 函数且轴数为 1:\n',np.ptp(a,axis=1))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
原数组:
[[3 7 5]
[8 4 3]
[2 4 9]]


调用 ptp() 函数且不指定轴数:
7


调用 ptp() 函数且轴数为 0:
[6 3 6]


调用 ptp() 函数且轴数为 1:
[4 5 7]

10.3 numpy.percentile

百分位数是统计中使用的度量, 用法如下:

1
2
3
4
5
6
numpy.percentile(arr, Q, axis=None)

# 参数说明
# arr: 输入数组
# Q: 百分位, 取值范围在 0 ~ 100 之间
# axis: 指定轴位

[例 10.3]

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.array([[10,7,4],[3,2,1]])
print('原数组:\n',a)
print('\n')
print('调用 percentile() 函数且不指定轴数:\n',np.percentile(a,50))
print('\n')
print('调用 percentile() 函数且轴数为 0:\n',np.percentile(a,50,axis=0))
print('\n')
print('调用 percentile() 函数且轴数为 1:\n',np.percentile(a,50,axis=0))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
原数组:
[[10 7 4]
[ 3 2 1]]


调用 percentile() 函数且不指定轴数:
3.5


调用 percentile() 函数且轴数为 0:
[6.5 4.5 2.5]


调用 percentile() 函数且轴数为 1:
[6.5 4.5 2.5]

10.4 numpy.mean

numpy.mean(arr, axis=None) 函数返回数组中元素的算术平均值 (权重相等). 如果提供了轴, 则沿其计算.

10.5 numpy.average

numpy.average() 函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值. 用法如下:

1
2
3
4
5
6
7
numpy.average(arr, weights=None, returned=False, axis=None)

# 参数说明
# arr: 输入数组
# weights: 平均的权重
# returned: 是否返回权重的和
# axis: 指定轴数

[例 10.4]

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([1,2,3,4])
print('原数组:\n',a)
print('\n')
print('调用 average() 函数, 不指定权重:\n',np.average(a))
print('\n')
print('调用 average() 函数, 指定权重, 并返回权重的和:\n',np.average(a, weights=[4,3,2,1],returned=True))

输出结果是:

1
2
3
4
5
6
7
8
9
10
原数组:
[1 2 3 4]


调用 average() 函数, 不指定权重:
2.5


调用 average() 函数, 指定权重, 并返回权重的和:
(2.0, 10.0)

10.6 numpy.std & numpy.var

numpy.std(arr, axis=None) & numpy.var(arr, axis=None) 求标准差和方差

[例 10.5]

1
2
3
4
5
6
7
8
import numpy as np

a = np.arange(24).reshape(4,6)
print('原数组:\n',a)
print('\n')
print('求取标准差:\n',np.std(a,axis=0))
print('\n')
print('求取方差:\n',np.var(a,axis=0))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
原数组:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]


求取标准差:
[6.70820393 6.70820393 6.70820393 6.70820393 6.70820393 6.70820393]


求取方差:
[45. 45. 45. 45. 45. 45.]

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
2
3
4
5
6
7
numpy.sort(arr, axis=1, kind='quicksort', order=None)

# 参数说明
# arr: 待排序数组
# axis: 沿着排序数组的轴, 如果没有指定数组会被展开. axis=0 按列排序,axis=1 按行排序 (默认)
# kind: 默认为快速排序 'quicksort
# order: 如果数组包含字段,则是要排序的字段

[例 11.1]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

a = np.array([[3,7],[9,1]])
print('原数组:\n',a)
print('\n')
print('调用 sort() 函数, 且不指定轴:\n',np.sort(a,axis=None))
print('\n')
print('调用 sort() 函数, 并按列排序:\n',np.sort(a, axis=0))
print('\n')

print('指定数据列名, 然后排序.')
dt = np.dtype([('name','S10'),('age','i2')])
a = np.array([('raju',21),('anil',25),('ravi',17),('amar',27)],dtype=dt)
print('我们的数组是:\n',a)
print('\n')
print('按 name 排序:\n',np.sort(a,order='name'))

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
原数组:
[[3 7]
[9 1]]


调用 sort() 函数, 且不指定轴:
[1 3 7 9]


调用 sort() 函数, 并按列排序:
[[3 1]
[9 7]]


指定数据列名, 然后排序.
我们的数组是:
[(b'raju', 21) (b'anil', 25) (b'ravi', 17) (b'amar', 27)]


按 name 排序:
[(b'amar', 27) (b'anil', 25) (b'raju', 21) (b'ravi', 17)]

11.2 numpy.argsort

numpy.argsort() 函数返回的是数组值从小到大的索引值.

[例 11.2]

1
2
3
4
5
6
7
8
import numpy as np

x = np.array([3,1,2])
print('我们的数组是:\n',x)
print('\n')
print('对 x 调用 argsort() 函数:\n',np.argsort(x))
print('\n')
print ('以排序后的顺序重构原数组:\n',x[np.argsort(x)])

输出结果是:

1
2
3
4
5
6
7
8
9
10
我们的数组是:
[3 1 2]


对 x 调用 argsort() 函数:
[1 2 0]


以排序后的顺序重构原数组:
[1 2 3]

11.3 numpy.lexsort()

numpy.lexsort() 用于对多个序列进行排序. 把它想象成对电子表格进行排序, 每一列代表一个序列, 排序时优先照顾靠后的列.

[例 11.3]

录入了四位同学的成绩,按照总分排序,总分相同时语文高的优先.

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

math = (10, 20, 50, 10)
chinese = (30, 50, 40, 60)
total = (40, 70, 90, 70)

# 将优先级高的项放在后面
indicies = np.lexsort((math, chinese, total))

for idx in indicies:
print(total[i],chinese[i],math[i])

输出结果是:

1
2
3
4
40 30 10
70 50 20
70 60 10
90 40 50

11.4 numpy.argmax() & numpy.argmin()

numpy.argmax()numpy.argmin() 函数分别沿给定轴返回最大和最小元素的索引.

11.5 numpy.nonzero

numpy.nonzero() 函数返回输入数组中非零元素的索引.

[例 11.4]

1
2
3
4
5
6
import numpy as np

a = np.array([[30,40,0],[0,20,10],[50,0,60]])
print('我们的数组:\n',a)
print('\n')
print('调用 nonzero() 函数:\n',np.nonzero(a))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
我们的数组:
[[30 40 0]
[ 0 20 10]
[50 0 60]]


调用 nonzero() 函数:
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))

#
得到的是一个长度为2的元组。它的第0个元素是数组a中值不为0的元素的第0轴的下标,第1个元素则是第1轴的下标

11.6 numpy.where

numpy.where() 函数返回输入数组中满足给定条件的元素的索引.

[例 11.5]

1
2
3
4
5
6
7
8
import numpy as np

a = np.arange(9).reshape(3,3)
print('我们的数组是:\n',a)
print('\n')
print('大于 3 的元素的索引是:\n',np.where(a>3))
print('\n')
print('用这些索引来索取元素:\n',a[np.where(a>3)])

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
我们的数组是:
[[0 1 2]
[3 4 5]
[6 7 8]]


大于 3 的元素的索引是:
(array([1, 1, 2, 2, 2]), array([1, 2, 0, 1, 2]))


用这些索引来索取元素:
[4 5 6 7 8]

Topic 12 Copy and View

副本是一个数据的完整的拷贝, 如果我们对副本进行修改, 它不会影响到原始数据, 物理内存不在同一位置.

  • Python 序列的切片操作, 调用deepCopy()函数.
  • 调用 ndarray 的 copy() 函数产生一个副本.

视图是数据的一个别称或引用, 通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝. 如果我们对视图进行修改, 它会影响到原始数据, 物理内存在同一位置.

  • numpy 的切片操作返回原数据的视图.
  • 调用 ndarray 的 view() 函数产生一个视图.

[例 11.1]

简单的赋值不会创建数组对象的副本. 相反, 它使用原始数组的相同id()来访问它. id()返回 Python 对象的通用标识符, 类似于 C 中的指针此外, 一个数组的任何变化都反映在另一个数组上. 例如, 一个数组的形状改变也会改变另一个数组的形状.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

a = np.arange(6)
print('我们的数组是:\n',a)
print('\n')
print('调用 id() 函数, 查看 a 的 id:\n',id(a))
print('\n')
print('将 a 赋值给 b:')
b = a
print(b)
print('\n')
print('调用 id() 函数, 查看 b 的 id:\n',id(b))
print('\n')
print('修改 b 的形状:')
b.shape = 3,2
print(b)
print('a 的形状也随之被修改:\n',a)

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
我们的数组是:
[0 1 2 3 4 5]


调用 id() 函数, 查看 a 的 id:
140651199630432


将 a 赋值给 b:
[0 1 2 3 4 5]


调用 id() 函数, 查看 b 的 id:
140651199630432


修改 b 的形状:
[[0 1]
[2 3]
[4 5]]


a 的形状也随之被修改:
[[0 1]
[2 3]
[4 5]]

12.1 View (ShallowCopy)

ndarray.view() 方会创建一个新的数组对象, 该方法创建的新数组的维数更改不会更改原始数据的维数. 但修改数据还是会跟随改变.

[例 12.2]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

a = np.arange(6).reshape(3,2)
print('我们的数组是:\n',a)
print('\n')
print('创建 a 的视图:')
b = a.view()
print(b)
print('\n')
print('两个数组的 id 不同.')
print('a 的 id:\n',id(a))
print('b 的 id:\n',id(b))
print('\n')
print('修改 b 的形状并不会改变 a 的形状.')
b.shape = 2,3
print('b 的形状:\n',b)
print('a 的形状:\n',a)

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
我们的数组是:
[[0 1]
[2 3]
[4 5]]


创建 a 的视图:
[[0 1]
[2 3]
[4 5]]


两个数组的 id 不同.
a 的 id:
140651199630192
b 的 id:
140651199630672


修改 b 的形状并不会改变 a 的形状.
b 的形状:
[[0 1 2]
[3 4 5]]
a 的形状:
[[0 1]
[2 3]
[4 5]]

使用切片创建视图修改数据会影响到原始数组, 见[例 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
2
3
4
5
6
numpy.matlib.empty(shape, dtype, order)

# 参数说明
# shape: 矩阵的形状
# dtype: 数据类型
# order: C (行序优先) 或者 F (列序优先)

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
2
3
4
5
6
7
numpy.matlib.eye(n, M, k, dtype)

# 参数说明
# n: 返回矩阵的行数
# M: 返回矩阵的列数, 默认为 n
# k: 对角线的索引
# dtype: 数据类型

[例 13.1]

1
2
3
4
import numpy as np
import numpy.matlib

print(np.matlib.eye(n=3,M=3,k=0,dtype='i2'))

输出结果是:

1
2
3
[[1 0 0]
[0 1 0]
[0 0 1]]

注:

numpy.matlib is an optional sub-package of numpy that must be imported separately. When you import just numpy without the sub-package matlib, then Python will be looking for .matlib as an attribute of the numpy package. This attribute has not been assigned to numpy without importing numpy.matlib

13.6 numpy.matlib.identity

返回一个给定大小的单位矩阵, 语法如下:

1
2
3
4
5
numpy.matlib.identity(n, dtype)

# 参数说明
# n: 单位矩阵的大小
# dtype: 数据的类型

13.7 numpy.matlib.rand

numpy.matlib.rand() 函数创建一个给定大小的矩阵, 数据是随机填充的, 介于 0~1.

[例 13.2]

1
2
3
4
import numpy as np
import numpy.matlib

print(np.matlib.rand(3,3))

输出结果是:

1
2
3
[[0.23519118 0.02624582 0.04782004]
[0.17469861 0.62994689 0.21809582]
[0.26929478 0.938636 0.38530064]]

13.8 numpy.matrix & numpy.asarray & numpy.asmatrix

矩阵总是二维的, 而 ndarray 是一个 n 维数组. 两个对象都是可互换的.

1
2
3
4
5
6
7
8
9
import numpy.matlib
import numpy as np

i = np.matrix('1,2;3,4') # matlab 式写法
print('使用 np.matrix 创建矩阵:\n',i)
print('\n')
print('将矩阵转化为 ndarray:\n',np.asarray(i))
print('\n')
print('将 ndarray 转换为矩阵:\n',np.asmatrix(np.asarray(i)))

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
使用 np.matrix 创建矩阵:
[[1 2]
[3 4]]


将矩阵转化为 ndarray:
[[1 2]
[3 4]]


将 ndarray 转换为矩阵:
[[1 2]
[3 4]]

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
2
3
4
5
import numpy as np

a = np.array([1,2,3])
b = np.array([10,20,30])
print('对于一维矩阵, numpy.dot() 就是对应元素相乘:\n',np.dot(a,b))

输出结果是:

1
2
对于一维矩阵, numpy.dot() 就是对应元素相乘:
140

对于二维矩阵:

1
2
3
4
5
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
print('对于高维矩阵, numpy.dot() 就是矩阵乘法:\n',np.dot(a,b))

输出结果是:

1
2
3
对于高维矩阵, numpy.dot() 就是矩阵乘法:
[[37 40]
[85 92]]

14.2 numpy.vdot

无论是一维还是二维数组都是点积

1
2
3
4
5
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
print('numpy.vdot() 就是点积:\n',np.vdot(a,b))

输出结果是:

1
2
numpy.vdot() 就是对应元素相乘:
130

14.3 numpy.inner

numpy.inner() 函数返回一维数组的向量内积. 对于更高的维度,它返回最后一个轴上的和的乘积. 等同于 numpy.dot(a, b.T)

1
2
3
4
5
6
7
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
print('numpy.inner() 向量的内积:\n',np.inner(a,b))
print('\n')
print('等同于 numpy.dot(a,b.T):\n',np.dot(a,b.T))

输出结果是:

1
2
3
4
5
6
7
8
numpy.inner() 向量的内积:
[[35 41]
[81 95]]


等同于 numpy.dot(a,b.T):
[[35 41]
[81 95]]

14.4 numpy.matmul

numpy.matmul 函数返回两个数组的矩阵乘积. 虽然它返回二维数组的正常乘积, 但如果任一参数的维数大于2, 则将其视为存在于最后两个索引的矩阵的栈,并进行相应广播.

1
2
3
4
5
6
7
8
9
import numpy as np
import numpy.matlib

a = np.array([[1,2],[3,4]])
a = np.asmatrix(a)
b = np.array([[11,12],[13,14]])
b = np.asmatrix(b)

print(np.matmul(a,b))

输出结果是:

1
2
[[37 40]
[85 92]]

14.5 numpy.linalg.det

求行列式, 这里暂时就不举例了

14.6 numpy.linalg.solve

解线性方程组:

$x+2y=3$

$4x+5y=6$

1
2
3
4
5
6
7
import numpy as np
import numpy.matlib

A = np.matrix('1,2;4,5')
b = np.matrix('3,6').T
result = np.linalg.solve(A,b)
print('方程组的解为:\n',result)

输出结果是:

1
2
3
方程组的解为:
[[-1.]
[ 2.]]

14.7 numpy.linalg.inv

求逆矩阵, 我暂时不举例子, 对概念不了解可取看我的 MIT Linear Algebra 的笔记.