numpy

numpy

数组基础

属性

  1. ndarray.ndim

    数组的轴(维度)的个数。在 Python 世界中,维度的数量被称为 rank(秩)

  2. ndarray.shape

    数组的维度。这是一个整数的元组,表示每个维度中数组的大小。对于有 n 行和 m 列的矩阵,shape 将是 (n,m)。因此,shape 元组的长度就是 rank 或维度的个数 ndim。

  3. ndarray.size

    数组元素的总数。这等于 shape 的元素的乘积。

  4. ndarray.dtype

    一个描述数组中元素类型的对象。可以使用标准的 Python 类型创建或指定 dtype。另外 NumPy 提供它自己的类型。例 numpy.int32、numpy.int16 和 numpy.float64。

  5. ndarray.itemsize

    数组中每个元素的字节大小。例如,元素为 float64 类型的数组的 itemsize 为 8(=64/8),而 complex32 类型的数组的 itemsize 为 4(=32/8)。它等于 ndarray.dtype.itemsize 。

  6. ndarray.data

    该缓冲区包含数组的实际元素。通常,我们不需要使用此属性,因为我们将使用索引访问数组中的元素。

创建

概览

1
2
3
4
a = np.array([0, 1, 2, 3, 4])
b = np.array((0, 1, 2, 3, 4))
c = np.arange(5)
d = np.linspace(0, 2*np.pi, 5)

用列表和元组创建数组

使用 array 函数

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

>>>
	array([2, 3, 4])

	array([[1.5, 2. , 3. ],
       		[4. , 5. , 6. ]])

数组类型可以在创建时显示指定

1
2
3
4
5
c = np.array([[1, 2], [3, 4]], dtype=complex)

>>>
	array([[1.+0.j, 2.+0.j],
       		[3.+0.j, 4.+0.j]])

用占位符创建数组

1
2
3
a = np.zeros((3, 4))
b = np.ones((2, 3, 4), dtype=np.int16)	# dtype can also be specified
c = np.empty((2, 3)) 					# uninitialized, output may vary

输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])

array([[[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]],

       [[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]]], dtype=int16)
array([[1.5, 2. , 3. ],
       [4. , 5. , 6. ]])

在一定范围内创建数组

使用 arange 函数

输入起始,终止,步长来创建数组

1
2
3
4
5
6
a = np.arange(10, 30, 5)
b = np.arange(0, 2, 0.3)  # it accepts float arguments

>>>
	array([10, 15, 20, 25])
	array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
使用 linspace 函数

当 arange 与浮点参数一起使用时,由于有限的浮点精度,通常不可能预测所获得的元素的数量。出于这个原因,通常最好使用 linspace 函数来接收我们想要的元素数量的函数,而不是步长(step)

1
2
3
4
a = np.linspace(0, 2, 9)     # numbers from 0 to 2

>>>
	array([0.  , 0.25, 0.5 , 0.75, 1.  , 1.25, 1.5 , 1.75, 2.  ])

创建二维数组

.reshape() 方法

创建一个共 20 个整数、4 行 5 列的二维数组

1
2
3
4
5
6
7
a = np.arange(20).reshape(4, 5)

>>>
	array([[ 0,  1,  2,  3,  4],
       		[ 5,  6,  7,  8,  9],
       		[10, 11, 12, 13, 14],
       		[15, 16, 17, 18, 19]])

随机创建

使用 numpy.random.rand()

numpy.random.rand(d0, d1, …, dn)

  1. rand 函数根据给定维度生成[0,1)之间的数据,包含 0,不包含 1

  2. dn 表示每个维度

  3. 返回值为指定维度的 array

1
2
3
4
5
6
7
np.random.rand(4, 2)

>>>
	array([[0.98674795, 0.13286586],
       		[0.29918216, 0.31617708],
       		[0.11613039, 0.06952587],
       		[0.854591  , 0.46243232]])
使用 numpy.random.randn()

numpy.random.randn(d0, d1, …, dn)

  1. randn 函数返回一个或一组样本,具有标准正态分布

  2. dn 表格每个维度

  3. 返回值为指定维度的 array

  4. 没有参数时,返回单个数据

1
2
3
4
5
np.random.randn(2, 4)

>>>
	array([[-1.00153189,  2.24079402,  1.60828566, -0.65998837],
       		[ 1.98674251, -0.33065155,  0.48365328,  0.4008861 ]])

运算

基本运算符

  1. 乘积运算符*在 NumPy 数组中按元素进行运算。矩阵乘积可以使用@运算符或dot函数或方法执行
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])

A*B
>>>
	array([[2, 0],
       		[0, 4]])

A@B
>>>
	array([[5, 4],
	       [3, 4]])

A.dot(B)
>>>
	array([[5, 4],
	       [3, 4]])
  1. 某些操作(例如+=*=)会更直接更改被操作的矩阵数组而不会创建新矩阵数组
  2. 当使用不同类型的数组进行操作时,结果数组的类型对应于更一般或更精确的数组(称为向上转换的行为)

特殊运算符

1
2
3
4
5
6
# dot, sum, min, max, cumsum
a = np.arange(10)
print(a.sum())  # >>>45
print(a.min())  # >>>0
print(a.max())  # >>>9
print(a.cumsum())  # >>>[ 0  1  3  6 10 15 21 28 36 45]

通过指定 axis(列)参数,可以沿数组的指定轴应用操作

1
2
3
4
5
b = np.arange(12).reshape(3, 4)
b.sum(axis=0)              # sum of each column

>>>
	array([12, 15, 18, 21])

通函数(ufunc)

数学函数合集

NumPy 提供熟悉的数学函数,例如 sin,cos 和 exp。在 NumPy 中,这些被称为“通函数”。在 NumPy 中,这些函数在数组上按元素进行运算,产生一个数组作为输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
A = np.arange(3)

np.exp(A)  # 以e为底的指数函数
>>>
	array([1.        , 2.71828183, 7.3890561 ])

np.sqrt(A)  # 开平方根
>>>
	array([0.        , 1.        , 1.41421356])

B = np.array([2., -1., 4.])
np.add(A, B)  # 相加
>>>
	array([2., 0., 6.])

x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6], [7, 8]])
# Matrix / matrix product; both produce the rank 2 array
print(x.dot(y))
print(np.dot(x, y))

>>>
	[[19 22]
	 [43 50]]

切片

一维数组

 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
a = np.arange(10)**3

a
>>> 
	array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729], dtype=int32)

a[2]
>>> 
	8

a[2:5]
>>> 
	array([ 8, 27, 64], dtype=int32)

a[:6:2] = -1000  # from start to position 6, exclusive, set every 2nd element to -1000

a
>>> 
	array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,
         	729], dtype=int32)

a[::-1]          # reversed a
>>>
	array([  729,   512,   343,   216,   125, -1000,    27, -1000,     1,
       		-1000], dtype=int32)

多维数组

image-20210106161435811

多维的数组每个轴可以有一个索引。这些索引以逗号分隔的元组给出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a = np.array([[11, 12, 13, 14, 15],
              [16, 17, 18, 19, 20],
              [21, 22, 23, 24, 25],
              [26, 27, 28, 29, 30], 
              [31, 32, 33, 34, 35]])

print(a[0, 1:4])  
>>>
	[12 13 14]
    
print(a[1:4, 0])  
>>>
	[16 21 26]
    
print(a[::2, ::2])   
>>>
	[[11 13 15]
     [21 23 25]
     [31 33 35]]
    
print(a[:, 1])  
>>>
	[12 17 22 27 32]

三个点( … )表示产生完整索引元组所需的冒号。例如,如果 x 是 rank 为 5 的数组(即,它具有 5 个轴),则

x[1 , 2 , …] 相当于 x[1,2, : , : , :],

x[… , 3] 等效于 x[: , : , : , : ,3]

x[4, … ,5, :] 等效于 x[4, : , : , 5, : ]

调整数据

四舍五入

返回四舍五入后的值,可指定精度

np.around(a, decimals=0, out=None)

  • a:输入数组

  • decimals:要舍入的小数位数。 默认值为 0。 如果为负,整数将四舍五入到小数点左侧的位置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
n = np.array([-0.746, 4.6, 9.4, 7.447, 10.455, 11.555])
 
np.around(n)
>>>
	[ -1.   5.   9.   7.  10.  12.]
 
np.around(n, decimals=1)
>>>
	[ -0.7   4.6   9.4   7.4  10.5  11.6]
 
np.around(n, decimals=-1)
>>>
	[ -0.   0.  10.  10.  10.  10.]

向下取整

返回不大于输入参数的最大整数

np.floor()

1
2
3
4
5
n = np.array([-1.7, -2.5, -0.2, 0.6, 1.2, 2.7, 11])
 
np.floor(n)
>>>
	[ -2.  -3.  -1.   0.   1.   2.  11.]

向上取整

返回输入值的上限

np.ceil()

1
2
3
4
5
n = np.array([-1.7, -2.5, -0.2, 0.6, 1.2, 2.7, 11])
 
np.ceil(n)
>>>
	[ -1.  -2.  -0.   1.   2.   3.  11.]

索引进阶

花式索引

用想要检索的特定索引序列对数组进行索引。这反过来返回索引的元素的列表。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Fancy indexing
a = np.arange(0, 100, 10)
indices = [1, 5, -1]
b = a[indices]
print(a)   
>>>	
	[ 0 10 20 30 40 50 60 70 80 90]
    
print(b)  
>>>
	[10 50 90]

布尔屏蔽

Where 函数

只需要把条件传递给它,它就会返回一个使得条件为真的元素的列表。

返回索引(下标)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Where
a = np.arange(0, 100, 10)
b = np.where(a < 50)
c = np.where(a >= 50)[0]

print(b)  
>>>
	(array([0, 1, 2, 3, 4]),)
    
print(c)  
>>>
	[5 6 7 8 9]

形状操控

改变数组的形状

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

可以使用各种命令更改数组的形状。请注意,以下三个命令(除 resize)都返回一个修改后的数组,但不会更改原始数组

 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
28
29
30
31
a.ravel()  			# 展平数组
>>>
	array([2, 8, 0, 6, 4, 5, 1, 1, 8, 9, 3, 6])
    
 a.reshape(6,2)  	# 重塑数组行列
>>>
	array([[2, 8],
       [0, 6],
       [4, 5],
       [1, 1],
       [8, 9],
       [3, 6]])

a.reshape(3,-1)		# 如果在 reshape 操作中将 size 指定为-1,则会自动计算其他的 size 大小
>>>
	array([[2, 8, 0, 6],
       [4, 5, 1, 1],
       [8, 9, 3, 6]])

 a.T  				# 转置数组
>>>
	array([[2, 4, 8],
       [8, 5, 9],
       [0, 1, 3],
       [6, 1, 6]])

a.resize((2,6))		#.resize()方法会修改数组本身
print(a)
>>>
	array([[2, 8, 0, 6, 4, 5],
       [1, 1, 8, 9, 3, 6]])

堆叠数组

几个数组可以沿不同的轴堆叠在一起

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
a = np.array([[8,  8],
              [0,  0]])
b = np.array([[1,  8],
              [0,  4]])

np.vstack((a, b))  # 垂直(按列顺序)把数组给堆叠起来
>>>
	array([[8, 8],
       [0, 0],
       [1, 8],
       [0, 4]])
    
np.hstack((a, b))  # 水平(按列顺序)把数组给堆叠起来
>>>
	array([[8, 8, 1, 8],
       [0, 0, 0, 4]])

拆分数组

使用hsplit,可以沿数组的水平轴拆分数组,方法是指定要返回的形状相等的数组的数量,或者指定应该在其之后进行分割的列

使用vsplit沿垂直轴分割

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
a = np.array([[9,  5,  6,  3,  6,  8,  0,  7,  9,  7,  2,  7],
              [1,  4,  9,  2,  2,  1,  0,  6,  2,  2,  4,  0]])

np.hsplit(a,3)   # 平均分成三份
>>>
	[array([[9, 5, 6, 3],
        [1, 4, 9, 2]]),
 	 array([[6, 8, 0, 7],
        [2, 1, 0, 6]]),
 	 array([[9, 7, 2, 7],
        [2, 2, 4, 0]])]
    
np.hsplit(a,(3,4))   # 以第三列和第四列为界,分割数组
>>>
	[array([[9, 5, 6],
        [1, 4, 9]]),
 	 array([[3],
        [2]]),
 	 array([[6, 8, 0, 7, 9, 7, 2, 7],
        [2, 1, 0, 6, 2, 2, 4, 0]])]

  1. 打印 numpy 的版本和配置说明
1
2
print(np.__version__)
np.show_config()
  1. 如何找到任何一个数组的内存大小?
1
2
Z = np.zeros((10, 10))
print("%d bytes" % (Z.size * Z.itemsize))
  1. 如何从一维数组中提取满足指定条件的元素?
1
2
3
4
5
6
7
# Input
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# Solution
arr[arr % 2 == 1]

>>>
	array([1, 3, 5, 7, 9])
  1. 找到数组[1,2,0,0,4,0]中非 0 元素的位置索引
1
2
nz = np.nonzero([1, 2, 0, 0, 4, 0])
print(nz)