numpy是Python的高级数组处理扩展库,提供了Python中没有的数组对象,支持N维数组运算、处理大型矩阵、成熟的广播函数库、矢量运算、线性代数、傅里叶变换以及随机数生成等功能,可与C++、FORTRAN等语言无缝结合,树莓派Python v3默认安装就已包含了numpy。

根据Python社区的习惯,首先使用下面的方式来导入numpy模块:

>>> import numpy as np

(1)生成数组

>>> np.array((1, 2, 3, 4, 5))  #把Python列表转换成数组
array([1, 2, 3, 4, 5])
>>> np.array(range(5)) #把Python的range对象转换成数组
array([0, 1, 2, 3, 4])
>>> np.array([[1, 2, 3], [4, 5, 6]])
array([[1, 2, 3],
       [4, 5, 6]])
>>> np.linspace(0, 10, 11)  #生成等差数组
array([  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.])
>>> np.linspace(0, 1, 11)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
>>> np.logspace(0, 100, 10)    #对数数组
array([  1.00000000e+000,   1.29154967e+011,   1.66810054e+022,
        2.15443469e+033,   2.78255940e+044,   3.59381366e+055,
        4.64158883e+066,   5.99484250e+077,   7.74263683e+088,
        1.00000000e+100])
>>> np.zeros((3,3))   #全0二维数组
[[ 0.  0.  0.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]]
>>> np.zeros((3,1)) #全0一维数组
array([[ 0.],
     [ 0.],
     [ 0.]])
>>> np.zeros((1,3))
array([[ 0.,  0.,  0.]])
>>> np.ones((3,3)) #全1二维数组
array([[ 1.,  1.,  1.],
     [ 1.,  1.,  1.],
     [ 1.,  1.,  1.]])
>>> np.ones((1,3))  #全1一维数组
array([[ 1.,  1.,  1.]])
>>> np.identity(3) #单位矩阵
array([[ 1.,  0.,  0.],
     [ 0.,  1.,  0.],
     [ 0.,  0.,  1.]])
>>> np.identity(2)
array([[ 1.,  0.],
     [ 0.,  1.]])
>>> np.empty((3,3))  #空数组,只申请空间而不初始化,元素值是不确定的
array([[ 0.,  0.,  0.],
     [ 0.,  0.,  0.],
     [ 0.,  0.,  0.]])

(2)数组与数值的算术运算

>>> x = np.array((1, 2, 3, 4, 5))   #创建数组对象
>>> x
array([1, 2, 3, 4, 5])
>>> x * 2  #数组与数值相乘,所有元素与数值相乘
array([ 2, 4, 6, 8, 10])
>>> x / 2    #数组与数值相除
array([ 0.5, 1. , 1.5, 2. , 2.5])
>>> x // 2   #数组与数值整除
array([0, 1, 1, 2, 2], dtype=int32)
>>> x ** 3   #幂运算
array([1, 8, 27, 64, 125], dtype=int32)
>>> x + 2   #数组与数值相加
array([3, 4, 5, 6, 7])
>>> x % 3  #余数
array([1, 2, 0, 1, 2], dtype=int32)

(3)数组与数组的算术运算

>>> a = np.array((1, 2, 3))
>>> b = np.array(([1, 2, 3], [4, 5, 6], [7, 8, 9]))
>>> c = a * b   #数组与数组相乘
>>> c #a中的每个元素乘以b中的每一列元素
array([[ 1, 4, 9],
     [ 4, 10, 18],
     [ 7, 16, 27]])
>>> c / b   #数组之间的除法运算
array([[ 1.,  2.,  3.],
     [ 1.,  2.,  3.],
     [ 1.,  2.,  3.]])
>>> c / a
array([[ 1.,  2.,  3.],
     [ 4.,  5.,  6.],
     [ 7.,  8.,  9.]])
>>> a + a   #数组之间的加法运算
array([2, 4, 6])
>>> a * a   #数组之间的乘法运算
array([1, 4, 9])
>>> a - a  #数组之间的减法运算
array([0, 0, 0])
>>> a / a   #数组之间的除法运算
array([ 1.,  1.,  1.])

(4)二维数组转置

>>> b = np.array(([1, 2, 3], [4, 5, 6], [7, 8, 9]))
>>> b
array([[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]])
>>> b.T   #转置
array([[1, 4, 7],
     [2, 5, 8],
     [3, 6, 9]])
>>> a = np.array((1, 2, 3, 4))
>>> a
array([1, 2, 3, 4])
>>> a.T  #一维数组转置以后和原来是一样的
array([1, 2, 3, 4])

(5)向量内积

>>> a = np.array((5, 6, 7))
>>> b = np.array((6, 6, 6))
>>> a.dot(b)    #向量内积
108
>>> np.dot(a,b)
108
>>> c = np.array(([1,2,3],[4,5,6],[7,8,9]))  #二维数组
>>> cT = c.T    #转置
>>> c.dot(a)     #二维数组的每行与一维向量计算内积
array([ 38, 92, 146])
>>> c[0].dot(a)   #两个一维向量计算内积
38
>>> c[1].dot(a)
92
>>> c[2].dot(a)
146
>>> a.dot(c)   #一维向量与二维向量的每列计算内积
array([ 78, 96, 114])
>>> a.dot(cT[0])
78
>>> a.dot(cT[1])
96
>>> a.dot(cT[2])
114

(6)数组元素访问

>>> b = np.array(([1,2,3],[4,5,6],[7,8,9]))
>>> b
array([[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]])
>>> b[0]  #第0行
array([1, 2, 3])
>>> b[0][0]  #第0行第0列的元素值
1
数组元素还支持多元素同时访问,例如
>>> x = np.arange(0, 100, 10, dtype=np.floating)  #创建等差数组
>>> x
array([0., 10., 20., 30., 40., 50., 60., 70., 80., 90.])
>>> index = np.random.randint(0, len(x), 5)   #生成5个随机整数作为下标
>>> index
array([5, 4, 1, 2, 9])
>>> x[index]    #同时访问多个元素的值
array([50., 40., 10., 20., 90.])
>>> x[index] = [1, 2, 3, 4, 5]  #同时修改多个下标指定的元素值
>>> x
array([0., 3., 4., 30., 2., 1., 60., 70., 80., 5.])
>>> x[[1,2,3]]   #同时访问多个元素的值
array([3., 4., 30.])

(7)对数组进行函数运算

>>> x = np.arange(0, 100, 10, dtype=np.floating)
>>> np.sin(x)  #一维数组中所有元素求正弦值
array([ 0.        , -0.54402111,  0.91294525, -0.98803162,  0.74511316,
      -0.26237485, -0.30481062,  0.77389068, -0.99388865,  0.89399666])
>>> b = np.array(([1, 2, 3], [4, 5, 6], [7, 8, 9]))
>>> np.cos(b)   #二维数组中所有元素求余弦值
array([[ 0.54030231, -0.41614684, -0.9899925 ],
     [-0.65364362,  0.28366219,  0.96017029],
     [ 0.75390225, -0.14550003, -0.91113026]])
>>> np.round(_)  #四舍五入
array([[ 1., -0., -1.],
      [-1.,  0.,  1.],
      [ 1., -0., -1.]])
>>> x = np.random.rand(10)   #包含10个随机数的数组
>>> x = x*10
>>> x
array([6.03635335,  3.90542305,  0.05402166,  0.97778005,  8.86122047,
     8.68849771,  8.43456386,  6.10805351,  1.01185534,  5.52150462])
>>> np.floor(x)   #所有元素向下取整
array([6., 3., 0., 0., 8., 8., 8., 6., 1., 5.])
>>> np.ceil(x)    #所有元素向上取整
array([7., 4., 1., 1., 9., 9., 9., 7., 2., 6.])

(8)对矩阵不同维度上的元素进行计算

>>> x = np.arange(0,10).reshape(2,5)   #创建二维数组
>>> x
array([[0, 1, 2, 3, 4],
     [5, 6, 7, 8, 9]])
>>> np.sum(x)    #二维数组所有元素求和
45
>>> np.sum(x, axis=0)   #二维数组纵向求和
array([ 5,  7,  9, 11, 13])
>>> np.sum(x, axis=1)   #二维数组横向求和
array([10, 35])
>>> np.mean(x, axis=0)  #二维数组纵向计算算术平均值
array([ 2.5,  3.5,  4.5,  5.5,  6.5])
>>> weight = [0.3, 0.7]   #权重
>>> np.average(x, axis=0, weights=weight)  #二维数组纵向计算加权平均值
array([ 3.5,  4.5,  5.5,  6.5,  7.5])
>>> np.max(x)  #所有元素最大值
9
>>> np.max(x, axis=0)   #每列元素的最大值
array([5, 6, 7, 8, 9])
>>> x = np.random.randint(0, 10, size=(3,3))  #创建二维数组
>>> x
array([[4, 9, 1],
     [7, 4, 9],
     [8, 9, 1]])
>>> np.std(x)  #所有元素标准差
3.1544599036840864
>>> np.std(x, axis=1)   #每行元素的标准差
array([3.29983165, 2.05480467, 3.55902608])
>>> np.var(x, axis=0)  #每列元素的标准差
array([2.88888889, 5.55555556, 14.22222222])
>>> np.sort(x, axis=0)  #纵向排序
array([[4, 4, 1],
     [7, 9, 1],
     [8, 9, 9]])
>>> np.sort(x, axis=1)   #横向排序
array([[1, 4, 9],
     [4, 7, 9],
     [1, 8, 9]])

(9)改变数组大小

>>> a = np.arange(1, 11, 1)
>>> a
array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> a.shape = 2, 5    #改为2行5列
>>> a
array([[ 1,  2,  3,  4,  5],
     [ 6,  7,  8,  9, 10]])
>>> a.shape = 5, -1    #-1表示自动计算
>>> a
array([[ 1,  2],
     [ 3,  4],
     [ 5,  6],
     [ 7,  8],
     [ 9, 10]])
>>> b = a.reshape(2,5)   #reshape()方法返回新数组
>>> b
array([[ 1,  2,  3,  4,  5],
     [ 6,  7,  8,  9, 10]])
(10)切片操作
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[::-1]  #反向切片
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
>>> a[::2]   #隔一个取一个元素
array([0, 2, 4, 6, 8])
>>> a[:5]    #前5个元素
array([0, 1, 2, 3, 4])
>>> c = np.arange(25)   #创建数组
>>> c.shape = 5,5    #修改数组大小
>>> c
array([[ 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]])
>>> c[0, 2:5]    #第0行中下标[2,5)之间的元素值
array([2, 3, 4])
>>> c[1]   #第0行所有元素
array([5, 6, 7, 8, 9])
>>> c[2:5, 2:5]    #行下标和列下标都介于[2,5)之间的元素值
array([[12, 13, 14],
       [17, 18, 19],
       [22, 23, 24]])

(11)布尔运算

>>> x = np.random.rand(10)  #包含10个随机数的数组
>>> x
array([ 0.56707504,  0.07527513,  0.0149213 ,  0.49157657,  0.75404095,
      0.40330683,  0.90158037,  0.36465894,  0.37620859,  0.62250594])
>>> x > 0.5    #比较数组中每个元素值是否大于0.5
array([ True, False, False, False,  True, False,  True, False, False,  True], dtype=bool)
>>> x[x>0.5]   #获取数组中大于0.5的元素
array([ 0.56707504,  0.75404095,  0.90158037,  0.62250594])
>>> a = np.array([1, 2, 3])
>>> b = np.array([3, 2, 1])
>>> a > b   #两个数组中对应位置上的元素比较
array([False, False,  True], dtype=bool)
>>> a[a>b]
array([3])
>>> a == b
array([False,  True, False], dtype=bool)
>>> a[a==b]
array([2])

(12)广播

>>> a = np.arange(0,60,10).reshape(-1,1)    #列向量
>>> b = np.arange(0,6)   #行向量
>>> a
array([[ 0],
     [10],
     [20],
     [30],
     [40],
     [50]])
>>> b
array([0, 1, 2, 3, 4, 5])
>>> a + b   #广播
array([[ 0,  1,  2,  3,  4,  5],
     [10, 11, 12, 13, 14, 15],
     [20, 21, 22, 23, 24, 25],
     [30, 31, 32, 33, 34, 35],
     [40, 41, 42, 43, 44, 45],
     [50, 51, 52, 53, 54, 55]])
>>> a * b
array([[  0,   0,   0,   0,   0,   0],
     [  0,  10,  20,  30,  40,  50],
     [  0,  20,  40,  60,  80, 100],
     [  0,  30,  60,  90,  120, 150],
     [  0,  40,  80,  120, 160, 200],
     [  0,  50,  100, 150,  200, 250]])

(13)分段函数

>>> x = np.random.randint(0, 10, size=(1,10))
>>> x
array([[0, 4, 3, 3, 8, 4, 7, 3, 1, 7]])
>>> np.where(x<5, 0, 1)   #小于5的元素值对应0,其他对应1
array([[0, 0, 0, 0, 1, 0, 1, 0, 0, 1]])
#小于4的元素乘以2,大于7的元素乘以3,其他元素变为0
>>> np.piecewise(x,[x<4, x>7],[lambda x:x*2,lambda x:x*3])
array([[ 0,  0,  6,  6, 24,  0,  0,  6,  2,  0]])

(14)计算唯一值以及出现次数

>>> x = np.random.randint(0,10,7)
>>> x
array([8, 7, 7, 5, 3, 8, 0])
>>> np.bincount(x)   #元素出现次数,0出现1次
array([1, 0, 0, 1, 0, 1, 0, 2, 2], dtype=int64)   #1、2没出现,3出现1次,以此类推
>>> np.sum(_)      #所有元素出现次数之和等于数组长度
7
>>> len(x)
7
>>> np.unique(x)   #返回唯一元素值
array([0, 3, 5, 7, 8])
>>> x = np.random.randint(0,10,2)
>>> x
array([2, 1])
>>> np.bincount(x)  #结果数组的长度取决于原始数组中最大元素值
array([0, 1, 1], dtype=int64)
>>> x = np.random.randint(0, 10, 10)
>>> x
array([3, 6, 4, 5, 2, 9, 7, 0, 9, 0])
>>> y = np.random.rand(10)  #随机小数,模拟权重
>>> y = np.round_(y, 1)   #保留一位小数
>>> y
array([ 0.6,  0.8,  0.8,  0. ,  0.6,  0.1,  0. ,  0.2,  0.8,  0.7])
>>> np.sum(x*y)/np.sum(np.bincount(x))  #加权总和/出现总次数或元素个数
2.9199999999999999

(15)矩阵运算

>>> a_list = [3, 5, 7]
>>> a_mat = np.matrix(a_list)    #创建矩阵
>>> a_mat
matrix([[3, 5, 7]])
>>> a_mat.T   #矩阵转置
matrix([[3],
      [5],
      [7]])
>>> a_mat.shape  #矩阵形状
(1, 3)
>>> a_mat.size
3
>>> b_mat = np.matrix((1, 2, 3))
>>> b_mat
matrix([[1, 2, 3]])
>>> a_mat * b_mat.T   #矩阵相乘
matrix([[34]])
>>> a_mat.mean()  #元素平均值
5.0
>>> a_mat.sum()   #所有元素之和
15
>>> a_mat.max()
7
>>> c_mat = np.matrix([[1, 5, 3], [2, 9, 6]])  #创建二维矩阵
>>> c_mat
matrix([[1, 5, 3],
      [2, 9, 6]])
>>> c_mat.argsort(axis=0)  #纵向排序后的元素序号
matrix([[0, 0, 0],
      [1, 1, 1]], dtype=int64)
>>> c_mat.argsort(axis=1)   #横向排序后的元素序号
matrix([[0, 2, 1],
      [0, 2, 1]], dtype=int64)
>>> d_mat = np.matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> d_mat.diagonal()   #矩阵对角线元素
matrix([[1, 5, 9]])
>>> d_mat.flatten()   #矩阵平铺
matrix([[1, 2, 3, 4, 5, 6, 7, 8, 9]])

本文内容节选自《Python可以这样学》(董付国著,清华大学出版社,2017.1出版)