NumPy的数组类被称为ndarray
。别名为 array。
ndarray.ndim
:数组的轴(维度)的个数。又称为rank。ndarray.shape
:数组的维度。是一个整数的元组,对于有n行和m列的矩阵,shape将是(n,m)。因此,shape元组的长度就是rank或维度的个数 ndim。ndarray.size
:数组元素的总数。等于shape的元素的乘积。ndarray.dtype
:数组中元素类型的对象。可以使用标准的Python类型创建或指定dtype。另外NumPy提供它自己的类型。例如numpy.int32、numpy.int16和numpy.float64。ndarray.itemsize
:数组中每个元素的字节大小。例如,元素为 float64 类型的数组的 itemsize 为8(=64/8),而 complex32 类型的数组的 itemsize 为4(=32/8)。它等于 ndarray.dtype.itemsize 。ndarray.data
:该缓冲区包含数组的实际元素。通常,我们不需要使用此属性,因为我们将使用索引访问数组中的元素。
1. 一个典型例子
代码语言:javascript复制>>> import numpy as np
>>> a = np.arange(15).reshape(3,5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int32'
>>> a.itemsize
4
>>> a.size
15
>>> type(a)
<class 'numpy.ndarray'>
>>> b = np.array([6,7,8])
>>> b
array([6, 7, 8])
>>> type(b)
<class 'numpy.ndarray'>
2. 数组的创建
- 直接python列表 [ ] 创建
>>> a = np.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int32')
>>> b = np.array([1.2, 3.5, 5.6])
>>> b.dtype
dtype('float64')
np.array() 传入的是一个列表 [ ]
代码语言:javascript复制>>> a = np.array(1,2,3,4) # WRONG
- 多维数组
>>> b = np.array([(1.5, 2, 3),(4, 5, 6)])
>>> b
array([[1.5, 2. , 3. ],
[4. , 5. , 6. ]])
可以指定数组类型
代码语言:javascript复制>>> c = np.array([[1,2],[3,4]],dtype=complex)
>>> c
array([[1. 0.j, 2. 0.j],
[3. 0.j, 4. 0.j]])
>>> c.dtype
dtype('complex128')
- 可以预先分配大小,避免数组频繁扩容
>>> np.zeros((3,4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.ones((2,3,4),dtype=np.int16)
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)
>>> np.empty((2,3)) #随机内容
array([[1.5, 2. , 3. ],
[4. , 5. , 6. ]])
- NumPy提供的
arange
,返回数组
np.arange
代码语言:javascript复制>>> np.arange(10,30,5) #(start, end, step) 不包括end
array([10, 15, 20, 25])
>>> np.arange(0,2,0.3) # 浮点精度优先,有时元素数量不能准确提前知道
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
np.linspace
代码语言:javascript复制>>> from numpy import pi
>>> np.linspace(0, 2, 9) ## 9 numbers from 0 to 2
array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
>>> x = np.linspace(0, 2*pi, 100)
>>> x
array([0. , 0.06346652, 0.12693304, 0.19039955, 0.25386607,
0.31733259, 0.38079911, 0.44426563, 0.50773215, 0.57119866,
0.63466518, 0.6981317 , 0.76159822, 0.82506474, 0.88853126,
0.95199777, 1.01546429, 1.07893081, 1.14239733, 1.20586385,
1.26933037, 1.33279688, 1.3962634 , 1.45972992, 1.52319644,
1.58666296, 1.65012947, 1.71359599, 1.77706251, 1.84052903,
1.90399555, 1.96746207, 2.03092858, 2.0943951 , 2.15786162,
2.22132814, 2.28479466, 2.34826118, 2.41172769, 2.47519421,
2.53866073, 2.60212725, 2.66559377, 2.72906028, 2.7925268 ,
2.85599332, 2.91945984, 2.98292636, 3.04639288, 3.10985939,
3.17332591, 3.23679243, 3.30025895, 3.36372547, 3.42719199,
3.4906585 , 3.55412502, 3.61759154, 3.68105806, 3.74452458,
3.8079911 , 3.87145761, 3.93492413, 3.99839065, 4.06185717,
4.12532369, 4.1887902 , 4.25225672, 4.31572324, 4.37918976,
4.44265628, 4.5061228 , 4.56958931, 4.63305583, 4.69652235,
4.75998887, 4.82345539, 4.88692191, 4.95038842, 5.01385494,
5.07732146, 5.14078798, 5.2042545 , 5.26772102, 5.33118753,
5.39465405, 5.45812057, 5.52158709, 5.58505361, 5.64852012,
5.71198664, 5.77545316, 5.83891968, 5.9023862 , 5.96585272,
6.02931923, 6.09278575, 6.15625227, 6.21971879, 6.28318531])
>>> f = np.sin(x)
>>> f
array([ 0.00000000e 00, 6.34239197e-02, 1.26592454e-01, 1.89251244e-01,
2.51147987e-01, 3.12033446e-01, 3.71662456e-01, 4.29794912e-01,
4.86196736e-01, 5.40640817e-01, 5.92907929e-01, 6.42787610e-01,
6.90079011e-01, 7.34591709e-01, 7.76146464e-01, 8.14575952e-01,
8.49725430e-01, 8.81453363e-01, 9.09631995e-01, 9.34147860e-01,
9.54902241e-01, 9.71811568e-01, 9.84807753e-01, 9.93838464e-01,
9.98867339e-01, 9.99874128e-01, 9.96854776e-01, 9.89821442e-01,
9.78802446e-01, 9.63842159e-01, 9.45000819e-01, 9.22354294e-01,
8.95993774e-01, 8.66025404e-01, 8.32569855e-01, 7.95761841e-01,
7.55749574e-01, 7.12694171e-01, 6.66769001e-01, 6.18158986e-01,
5.67059864e-01, 5.13677392e-01, 4.58226522e-01, 4.00930535e-01,
3.42020143e-01, 2.81732557e-01, 2.20310533e-01, 1.58001396e-01,
9.50560433e-02, 3.17279335e-02, -3.17279335e-02, -9.50560433e-02,
-1.58001396e-01, -2.20310533e-01, -2.81732557e-01, -3.42020143e-01,
-4.00930535e-01, -4.58226522e-01, -5.13677392e-01, -5.67059864e-01,
-6.18158986e-01, -6.66769001e-01, -7.12694171e-01, -7.55749574e-01,
-7.95761841e-01, -8.32569855e-01, -8.66025404e-01, -8.95993774e-01,
-9.22354294e-01, -9.45000819e-01, -9.63842159e-01, -9.78802446e-01,
-9.89821442e-01, -9.96854776e-01, -9.99874128e-01, -9.98867339e-01,
-9.93838464e-01, -9.84807753e-01, -9.71811568e-01, -9.54902241e-01,
-9.34147860e-01, -9.09631995e-01, -8.81453363e-01, -8.49725430e-01,
-8.14575952e-01, -7.76146464e-01, -7.34591709e-01, -6.90079011e-01,
-6.42787610e-01, -5.92907929e-01, -5.40640817e-01, -4.86196736e-01,
-4.29794912e-01, -3.71662456e-01, -3.12033446e-01, -2.51147987e-01,
-1.89251244e-01, -1.26592454e-01, -6.34239197e-02, -2.44929360e-16])
3. 打印数组
NumPy以与嵌套列表类似的方式,具有以下布局:
- 最后一个轴从左到右打印,
- 倒数第二个从上到下打印,
- 其余的也从上到下打印,每个切片与下一个用空行分开。
一维数组被打印为行、二维为矩阵和三维为矩阵列表。
代码语言:javascript复制>>> a = np.arange(6) # 1D 数组
>>> print(a)
[0 1 2 3 4 5]
>>> b = np.arange(12).reshape(4,3) # 2D 数组
>>> print(b)
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
>>> c = np.arange(24).reshape(2,3,4) # 3D 数组
>>> print(c)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
过多的数据只打印两端的,中间的跳过
代码语言:javascript复制>>> print(np.arange(10000))
[ 0 1 2 ... 9997 9998 9999]
>>> print(np.arange(10000).reshape(100,100))
[[ 0 1 2 ... 97 98 99]
[ 100 101 102 ... 197 198 199]
[ 200 201 202 ... 297 298 299]
...
[9700 9701 9702 ... 9797 9798 9799]
[9800 9801 9802 ... 9897 9898 9899]
[9900 9901 9902 ... 9997 9998 9999]]
代码语言:javascript复制np.set_printoptions(threshold=10000)
#元素总数 > 阈值,显示部分,否则显示全部
代码语言:javascript复制>>> np.set_printoptions(threshold=140)
>>> print(np.arange(144).reshape(12,12))
[[ 0 1 2 ... 9 10 11]
[ 12 13 14 ... 21 22 23]
[ 24 25 26 ... 33 34 35]
...
[108 109 110 ... 117 118 119]
[120 121 122 ... 129 130 131]
[132 133 134 ... 141 142 143]]
>>> np.set_printoptions(threshold=145)
>>> print(np.arange(144).reshape(12,12))
[[ 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 25 26 27 28 29 30 31 32 33 34 35]
[ 36 37 38 39 40 41 42 43 44 45 46 47]
[ 48 49 50 51 52 53 54 55 56 57 58 59]
[ 60 61 62 63 64 65 66 67 68 69 70 71]
[ 72 73 74 75 76 77 78 79 80 81 82 83]
[ 84 85 86 87 88 89 90 91 92 93 94 95]
[ 96 97 98 99 100 101 102 103 104 105 106 107]
[108 109 110 111 112 113 114 115 116 117 118 119]
[120 121 122 123 124 125 126 127 128 129 130 131]
[132 133 134 135 136 137 138 139 140 141 142 143]]
4. 基本操作
一个新的数组被创建并填充结果
代码语言:javascript复制>>> a = np.array([20,30,40,50])
>>> b = np.arange(4)
>>> b
array([0, 1, 2, 3])
>>> c = a - b
>>> c
array([20, 29, 38, 47])
>>> b**2 #平方
array([0, 1, 4, 9], dtype=int32)
>>> 10*np.sin(a) #单位弧度
array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854])
>>> a<35
array([ True, True, False, False])
与许多矩阵语言不同,乘法运算符 * 的运算在NumPy数组中是元素级别的。矩阵乘积可以使用 dot 函数或方法执行:
代码语言:javascript复制>>> A = np.array( [[1,1],
... [0,1]] )
>>> B = np.array( [[2,0],
... [3,4]] )
>>> A*B #对应元素相乘
array([[2, 0],
[0, 4]])
>>> A.dot(B) #矩阵乘积 dot(matrix)
array([[5, 4],
[3, 4]])
>>> np.dot(A,B)
array([[5, 4],
[3, 4]])
>>> B.dot(A)
array([[2, 2],
[3, 7]])
某些操作(例如 =和*=)适用于修改现有数组,不创建新数组。
代码语言:javascript复制>>> a = np.ones((2,3),dtype=int)
>>> b = np.random.random((2,3))
>>> a
array([[1, 1, 1],
[1, 1, 1]])
>>> b
array([[0.43420493, 0.10561194, 0.44199609],
[0.07220352, 0.26078137, 0.24609001]])
>>> a *= 3
>>> a
array([[3, 3, 3],
[3, 3, 3]])
>>> b = a
>>> b
array([[3.43420493, 3.10561194, 3.44199609],
[3.07220352, 3.26078137, 3.24609001]])
>>> a = b # b 不能自动转化成int型
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
a = b
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
当不同类型的数组操作时,结果数组的类型对应于更精确的数组(向上转换的行为)。
代码语言:javascript复制>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a b
>>> c
array([ 1. , 2.57079633, 4.14159265])
>>> c.dtype.name
'float64'
>>> d = np.exp(c*1j)
>>> d
array([ 0.54030231 0.84147098j, -0.84147098 0.54030231j,
-0.54030231-0.84147098j])
>>> d.dtype.name
'complex128'
许多一元运算,例如计算数组中所有元素的总和,都是作为 ndarray
类的方法实现的。
>>> a = np.random.random((2,3)) # 2行3列 0-1之间的随机数
>>> a
array([[0.29421273, 0.96663251, 0.67232279],
[0.83508847, 0.58010047, 0.76200929]])
>>> a.sum()
4.110366271979025
>>> a.min()
0.29421272607104476
>>> a.max()
0.9666325116204056
默认情况下,这些操作适用于数组,就好像它是数字列表一样,无论其形状如何。但是,通过指定 axis
参数,你可以沿着数组的指定轴应用操作:
>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> b.sum(axis=0) #axis=0,表示按列操作
array([12, 15, 18, 21])
>>> b.min(axis=1) # axis=1,表示按行操作
array([0, 4, 8])
>>> b.cumsum(axis=1) #按行累积和
array([[ 0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38]], dtype=int32)
>>> b.cumsum(axis=0) #按列累积和
array([[ 0, 1, 2, 3],
[ 4, 6, 8, 10],
[12, 15, 18, 21]], dtype=int32)
5. 通用函数
NumPy提供了常见的数学函数,如sin,cos和exp。In NumPy, these are called “universal functions”( ufunc
). 在NumPy中,这些函数在数组上按元素级别操作,产生一个数组作为输出。
>>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([1. , 2.71828183, 7.3890561 ])
>>> np.sqrt(B)
array([0. , 1. , 1.41421356])
>>> C = np.array([2, -1, 4])
>>> np.add(B, C)
array([2, 0, 6])
6. 索引、切片、迭代
一维数组可以被索引,切片和迭代,就像列出和其他Python序列一样。
代码语言:javascript复制>>> 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 #从最开始到6(不含6),每2个元素置 -1000
>>> a
array([-1000, 1, -1000, 27, -1000, 125, 216, 343, 512,
729], dtype=int32)
>>> a[::-1] # 反向序列 a‘
array([ 729, 512, 343, 216, 125, -1000, 27, -1000, 1,
-1000], dtype=int32)
>>> for i in a:
print(i**(1/3))
Warning (from warnings module):
File "__main__", line 2
RuntimeWarning: invalid value encountered in power
nan
1.0
nan
3.0
nan
5.0
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998
代码语言:javascript复制>>> a = np.random.rand(5)
>>> a
array([0.44659638, 0.10928946, 0.54948707, 0.08119349, 0.92727562])
>>> a[-1] # 最后一个元素
0.9272756224719964
>>> a[:-1] # 除了最后一个的其余的
array([0.44659638, 0.10928946, 0.54948707, 0.08119349])
>>> a[::-1] # 逆序输出新的序列
array([0.92727562, 0.08119349, 0.54948707, 0.10928946, 0.44659638])
>>> a[2::-1] # 从下标2的元素向前全部读取
array([0.54948707, 0.10928946, 0.44659638])
多维(Multidimensional) 数组每个轴可以有一个索引。 这些索在元组中以逗号分隔给出:
代码语言:javascript复制>>> def f(x,y):
return 10*x y
>>> b = np.fromfunction(f,(5,4),dtype=int)
>>> b
array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33],
[40, 41, 42, 43]])
>>> b[2,3]
23
>>> b[0:5,1] # 0,1,2,3,4行,每行取下标1的列元素
array([ 1, 11, 21, 31, 41])
>>> b[ : ,1] # 所有行,取下标1的列元素
array([ 1, 11, 21, 31, 41])
>>> b[1:3,:] # 1,2行,所有的列元素
array([[10, 11, 12, 13],
[20, 21, 22, 23]])
当提供比轴数更少的索引时,缺失的索引被认为是一个完整切片 :
>>> b[-1] # 最后一行,即 b[-1, :]
array([40, 41, 42, 43])
b[i]
方括号中的表达式 i
被视为后面紧跟着 :
的多个实例,用于表示剩余轴。NumPy也允许你使用三个点写为 b[i,...]
。
三个点( ...
)表示产生完整索引元组所需的冒号。例如,如果 x
是rank为的5数组(即,它具有5个轴),则
x[1,2,...]
等于 x[1,2,:,:,:]
x[...,3]
等效于 x[:,:,:,:,3]
x[4,...,5,:]
等效于 x[4,:,:,5,:]
>>> c = np.array([[[0, 1, 2], # 3D 数组
[10,12,13]],
[[100,101,102],
[110,112,113]]])
>>> c.shape
(2, 2, 3)
>>> c[1,...] # 即 c[1,:,:] or c[1]
array([[100, 101, 102],
[110, 112, 113]])
>>> c[...,2] # 即 c[:,:,2]
array([[ 2, 13],
[102, 113]])
迭代(Iterating) 多维数组是相对于第一个轴完成的:
代码语言:javascript复制>>> for row in b:
print(row)
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
但是,如果想要对数组中的每个元素执行操作,可以使用 flat
属性,该属性是数组中所有元素的迭代器:
>>> for element in b.flat:
print(element)
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43