NumPy快速入门--基础知识

2021-02-20 11:07:43 浏览数 (1)

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. 数组的创建

  1. 直接python列表 [ ] 创建
代码语言:javascript复制
>>> 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
  1. 多维数组
代码语言:javascript复制
>>> 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')
  1. 可以预先分配大小,避免数组频繁扩容
代码语言:javascript复制
>>> 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. ]])
  1. 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 类的方法实现的。

代码语言:javascript复制
>>> 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 参数,你可以沿着数组的指定轴应用操作:

代码语言:javascript复制
>>> 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中,这些函数在数组上按元素级别操作,产生一个数组作为输出。

代码语言:javascript复制
>>> 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]])

当提供比轴数更少的索引时,缺失的索引被认为是一个完整切片 :

代码语言:javascript复制
>>> 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,:]

代码语言:javascript复制
>>> 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 属性,该属性是数组中所有元素的迭代器:

代码语言:javascript复制
>>> 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

0 人点赞