Numpy

Numpy详解

ndarray 是多维数组对象, 也是numpy最核心的对象。 在numpy中数组的维度(dimensions)叫做轴(axes), 轴的个数叫做秩(rank). 通常, 夜歌numpy数组的所有元素都是同一类型的数据, 而这些数据的存储和数组的形式无关。

下面的例子, 创建了一个三维数组(numpy 导入时 简化为 np)

1 数组对象

import numpy as np  
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  
print(a)  
[[1 2 3]  
 [4 5 6]  
 [7 8 9]]  

1.1 数据类型

numpy支持比python原生更多的数据类型,常用数据类型[链接]

1.2 创建数组

通常np.array(), 一维数组:np.arange()或者np.linspace()的方法. np.zeros()、np.ones()、np.eys()则可以创建特殊的数据。np.random.randint()和np.random.random()可以构造随机数数组

np.array([[1, 2, 3], [4, 5, 6]])     # 默认类型为int32  
array([[1, 2, 3],  
       [4, 5, 6]])  
np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int8)  # 指定元素类型为int8  
array([[1, 2, 3],  
       [4, 5, 6]], dtype=int8)  
np.arange(5)      # 默认指定元素为int32  
array([0, 1, 2, 3, 4])  
np.arange(3, 8, dtype=np.int8) # 指定类型为int8  
array([3, 4, 5, 6, 7], dtype=int8)  
np.arange(12).reshape(3, 4)  # 改变shape  
array([[ 0,  1,  2,  3],  
       [ 4,  5,  6,  7],  
       [ 8,  9, 10, 11]])  
np.linspace(1, 2, 5)   # 从1到2生成5个浮点数  
array([1.  , 1.25, 1.5 , 1.75, 2.  ])  
np.zeros((2, 3))  # 全0数组  
array([[0., 0., 0.],  
       [0., 0., 0.]])  
np.ones((2, 3)) # 全一数组  
array([[1., 1., 1.],  
       [1., 1., 1.]])  
np.eye(3)  # 主对角线为一, 其他元素为0  
array([[1., 0., 0.],  
       [0., 1., 0.],  
       [0., 0., 1.]])  
np.random.random((2,3))  # 生成[0, 1) 之间的随机浮点数  
array([[0.05146009, 0.05024011, 0.67549961],  
       [0.3244844 , 0.24009114, 0.71975804]])  
np.random.randint(0, 10, (3 ,2)) # 生成[0, 10) 之间的随机整数  
array([[5, 7],  
       [1, 2],  
       [9, 7]])  

1.3 构建复杂数组

很多时候,我们需要从简单的数据结构,构造出复杂的数组。例如,用一维的数据生成二维的数据

1.3.1 重复数组:tile

a = np.arange(5)  
a  
array([0, 1, 2, 3, 4])  
np.tile(a, 2)  
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4])  
np.tile(a, (3, 2))  
array([[0, 1, 2, 3, 4, 0, 1, 2, 3, 4],  
       [0, 1, 2, 3, 4, 0, 1, 2, 3, 4],  
       [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]])  

1.3.2 一维数组网格化:meshgrid

a = np.arange(5)  
b = np.arange(5, 10)  
np.meshgrid(a, b)  
[array([[0, 1, 2, 3, 4],  
        [0, 1, 2, 3, 4],  
        [0, 1, 2, 3, 4],  
        [0, 1, 2, 3, 4],  
        [0, 1, 2, 3, 4]]), array([[5, 5, 5, 5, 5],  
        [6, 6, 6, 6, 6],  
        [7, 7, 7, 7, 7],  
        [8, 8, 8, 8, 8],  
        [9, 9, 9, 9, 9]])]  

1.3.3 指定范围和分割方式的网格化:mgrid

np.mgrid[0:1:2j, 1:2:3j]  
array([[[0. , 0. , 0. ],  
        [1. , 1. , 1. ]],  

       [[1. , 1.5, 2. ],  
        [1. , 1.5, 2. ]]])  
np.mgrid[0:1:0.3, 1:2:0.4]  
array([[[0. , 0. , 0. ],  
        [0.3, 0.3, 0.3],  
        [0.6, 0.6, 0.6],  
        [0.9, 0.9, 0.9]],  

       [[1. , 1.4, 1.8],  
        [1. , 1.4, 1.8],  
        [1. , 1.4, 1.8],  
        [1. , 1.4, 1.8]]])  

上述例子中用到了虚数。构造虚数的方法如下:

complex(2, 5)  
(2+5j)  

1.4 数组的属性

numpy的数组除了一些常规的属性外,也有几个类似转置、扁平迭代器等看起来更像是方法的属性。扁平迭代器也许是遍历多为数组的一个简明方法,下面的代码给出了一个例子。

a = np.array([[1, 2, 3], [4, 5, 6]])  
a.dtype    # 数组元素的数据类型  
dtype('int32')  
a.dtype.itemsize  #数组元素占据的内存字节数  
4  
a.shape   # 数组的维度  
(2, 3)  
a.size # 数组元素的个数  
6  
a.T   # 数组行变列,类似于矩阵的转置  
array([[1, 4],  
       [2, 5],  
       [3, 6]])  
a.flat # 返回一个扁平迭代器,用于遍历多维数组  
print(a.flat)  
for item in a.flat:  
    print(item)  
<numpy.flatiter object at 0x00000287DCA5DC60>  
1  
2  
3  
4  
5  
6  

1.5 改变数组的维度

numpy数组的存储顺序和数组的维度是不相干的,一次改变数组的维度是非常便捷的操作,除resize()外,这一类操作不会改变所操作的数组本身的存储顺序。

a = np.array([[1, 2, 3], [4, 5, 6]])  
print(a.shape) # 查看数组维度  
(2, 3)  
a.reshape(3, 2) # 返回3行2列的数组  
array([[1, 2],  
       [3, 4],  
       [5, 6]])  
a.ravel() # 返回一维数组  
array([1, 2, 3, 4, 5, 6])  
a.resize((3, 2)) # 类似于reshape,但会改变所操作的数组  
a  
array([[1, 2],  
       [3, 4],  
       [5, 6]])  

1.6 索引与切片

对于一维数组的索引和切片,numpy和python的list一样,甚至更灵活

a = np.arange(9)  
a[-1] #最后一个元素  
8  
a[2:5]    # 返回第2到第5个元素  
array([2, 3, 4])  
a[:7:3] # 返回第0到第7个元素,步长为3  
array([0, 3, 6])  
a[::-1]  # 返回逆序数组  
array([8, 7, 6, 5, 4, 3, 2, 1, 0])  

假设有一栋2层楼,每层楼内的房间都是3排4列,那我们可以用一个三维数组来保存每个房间的居住人数(当然,也可以是房间面积等其他数值信息)。

a = np.arange(24).reshape(2, 3, 4)   # 2层3排4列  
a  
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]]])  
a[1][2][3]      #虽然可以这样  
23  
a[1,2,3]        # 但这才是规范的用法  
23  
a[:,0,0] #所有楼层的1排1列  
array([ 0, 12])  
a[0, :, :] #一楼所用房间,等价于a[0]或a[0,...]  
array([[ 0,  1,  2,  3],  
       [ 4,  5,  6,  7],  
       [ 8,  9, 10, 11]])  
a[:,:,1:3]   #所有楼层所有排的第2到4列  
array([[[ 1,  2],  
        [ 5,  6],  
        [ 9, 10]],  

       [[13, 14],  
        [17, 18],  
        [21, 22]]])  
a[1,:,-1]   # 2层每一排的最后一个房间  
array([15, 19, 23])  

1.7 数组合并

数组合并触雷下面介绍的水平合并、垂直合并、深度合并外,还有行合并、列合并,以及concatenat()等方式。假如你比我还懒,那就只了解前三种方法,足够用了

a = np.arange(9).reshape(3, 3)  
b = np.arange(9, 18).reshape(3, 3)  
a  
array([[0, 1, 2],  
       [3, 4, 5],  
       [6, 7, 8]])  
b  
array([[ 9, 10, 11],  
       [12, 13, 14],  
       [15, 16, 17]])  
np.hstack((a, b)) # 水平合并  
array([[ 0,  1,  2,  9, 10, 11],  
       [ 3,  4,  5, 12, 13, 14],  
       [ 6,  7,  8, 15, 16, 17]])  
np.vstack((a, b))  # 垂直合并  
array([[ 0,  1,  2],  
       [ 3,  4,  5],  
       [ 6,  7,  8],  
       [ 9, 10, 11],  
       [12, 13, 14],  
       [15, 16, 17]])  
np.dstack((a, b))   # 深度合并  
array([[[ 0,  9],  
        [ 1, 10],  
        [ 2, 11]],  

       [[ 3, 12],  
        [ 4, 13],  
        [ 5, 14]],  

       [[ 6, 15],  
        [ 7, 16],  
        [ 8, 17]]])  

1.8 数组拆分

a = np.arange(9).reshape(3, 3)  
np.hsplit(a, 3)    #水平拆分,返回list  
[array([[0],  
        [3],  
        [6]]), array([[1],  
        [4],  
        [7]]), array([[2],  
        [5],  
        [8]])]  
np.vsplit(a, 3)   # 垂直拆分,返回list  
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]  
a = np.arange(27).reshape(3, 3, 3)  
np.dsplit(a, 3)    #深度拆分,返回list  
[array([[[ 0],  
         [ 3],  
         [ 6]],  

        [[ 9],  
         [12],  
         [15]],  

        [[18],  
         [21],  
         [24]]]), array([[[ 1],  
         [ 4],  
         [ 7]],  

        [[10],  
         [13],  
         [16]],  

        [[19],  
         [22],  
         [25]]]), array([[[ 2],  
         [ 5],  
         [ 8]],  

        [[11],  
         [14],  
         [17]],  

        [[20],  
         [23],  
         [26]]])]  

1.9 数组运算

数组和常数的四则运算,是数组的每一个元素分别和常数运算;数组和数组的四则运算则是两个数组对应元素的运算(两个数组有相同的shape,否则抛出异常)

import numpy as np  
a = np.arange(4, dtype=np.float32).reshape(2, 2)  
b = np.arange(4, 8, dtype=np.float32).reshape(2, 2)  
a + 2     # 数组和常数可以进行四则运算  
array([[2., 3.],  
       [4., 5.]], dtype=float32)  
a / b    # 数组和数组可以进行四则运算  
array([[0.        , 0.2       ],  
       [0.33333334, 0.42857143]], dtype=float32)  
a == b    # 最神奇的是, 数组可以判断对应元素是否相等  
array([[False, False],  
       [False, False]])  
(a == b).all()   # 判断数组是否相等  
False  

特别提示:如果相对数组内符合特定条件的元素做特殊处理,下面的代码也许有用

a = np.arange(6).reshape((2, 3))  
a  
array([[0, 1, 2],  
       [3, 4, 5]])  
(a > 2)&(a<=4)  
array([[False, False, False],  
       [ True,  True, False]])  
a[(a>2)&(a<=4)] # a中满足条件的数组成的数组  
array([3, 4])  
a[(a>2)&((a<=4))] += 10  # 满足条件的进行后面的运算  
a  
array([[ 0,  1,  2],  
       [13, 14,  5]])  

1.10 数组方法和常用函数

数组对象本身提供了计算算数平均值、求最大值最小值等内置方法,numpy也提供了很多实用的函数。为了缩减篇幅,下面的代码仅以一维数组为例,展示了这些方法和函数的用法。事实上,大多是情况下这些方法和函数对于多维数组同样有效,只有少数例外,比如compress函数。

import numpy as np  
a = np.array([3, 2, 4])  
a.sum()   # 所有元素之和  
9  
a.prod()   #所有元素的乘积  
24  
a.mean()   #所有元素的算数平均值  
3.0  
a.max()     # 所有元素的最大值  
4  
a.min()     # 所有元素的最小值  
2  
a.clip(3, 4)    # 小于3的元素替换为3,大于4的元素替换为4  
array([3, 3, 4])  
a.compress(a>2)   # 返回大于2的元素构成的数组  
array([3, 4])  
a.tolist()     # 返回python的list  
[3, 2, 4]  
a.var()    # 计算方差(元素与均值之差的平方的均值)  
0.6666666666666666  
a.std()    # 计算标准差  
0.816496580927726  
a.ptp()   # 返回数组的最大值和最小值之差  
2  
a.argmin()    # 返回最小值在扁平数组中的索引  
1  
a.argmax()    # 返回最大值在扁平数组中的索引  
2  
np.where(a == 2)    # 返回所有值为2的元素的索引  
(array([1], dtype=int64),)  
np.diff(a)    # 返回相邻元素的差  
array([-1,  2])  
np.log(a)    # 返回对数数组  
array([1.09861229, 0.69314718, 1.38629436])  
np.exp(a)    # 返回指数数组  
array([20.08553692,  7.3890561 , 54.59815003])  
np.sqrt(a)    # 返回开方数组  
array([1.73205081, 1.41421356, 2.        ])  
np.msort(a)    # 数组排序  
array([2, 3, 4])  
a = np.array([1, 4, 7])  
b = np.array([8, 5, 2])  
np.maximum(a, b)     # 返回多个数组中对应位置元素的最大值数组  
array([8, 5, 7])  
np.minimum(a,b)    # 返回多个数组中对应位置元素的最小值  
array([1, 4, 2])  
np.true_divide(a,b)     # 对整数实现真正的数学除法运算  
array([0.125, 0.8  , 3.5  ])  

2 矩阵对象

矩阵有的特性可以加速运算, matrix是矩阵对象,继承自ndarray类型,因此含有ndarray的所有数据属性和方法,不过当你吧矩阵对象当作数组操作时需要注意以下几点:

  • matrix对象总是二维的,即使是展平(ravel函数)操作或者是成员选择,返回值也是二维的
  • matrix队形和darray对象回合的运算总是返回matrix对象

2.1 创建矩阵

matrix对象可以使用一个matlab风格的字符串来创建(以空格分隔列,已分号分隔行的字符床),也可以用数组来创建。

np.mat('1 4 5; 2 3 5; 56 3 1')  
matrix([[ 1,  4,  5],  
        [ 2,  3,  5],  
        [56,  3,  1]])  
np.mat(np.arange(1, 10).reshape(3, 3))  
matrix([[1, 2, 3],  
        [4, 5, 6],  
        [7, 8, 9]])  

2.2 矩阵特有的属性

m = np.mat(np.arange(1, 10).reshape(3, 3))  
m  
matrix([[1, 2, 3],  
        [4, 5, 6],  
        [7, 8, 9]])  
m.T # 返回矩阵的转置  
matrix([[1, 4, 7],  
        [2, 5, 8],  
        [3, 6, 9]])  
m.H # 返回矩阵的共轭转置  
matrix([[1, 4, 7],  
        [2, 5, 8],  
        [3, 6, 9]])  
m.I # 返回自身的逆矩阵  
matrix([[ 3.15251974e+15, -6.30503948e+15,  3.15251974e+15],  
        [-6.30503948e+15,  1.26100790e+16, -6.30503948e+15],  
        [ 3.15251974e+15, -6.30503948e+15,  3.15251974e+15]])  
m.A #返回自身数据的二维数组的一个视图  
array([[1, 2, 3],  
       [4, 5, 6],  
       [7, 8, 9]])  

2.3 矩阵乘法

对ndarray对象而言,星号是按元素相乘,dot()函数则当作矩阵相乘。对于matrix而言,星号和dot()函数都是矩阵相乘。特别的,对于一维数组,dot()函数实现的是向量点乘,但星号实现的却不是叉乘

a = np.array([1, 2, 3])  
b = np.array([4, 5, 6])  
a * b # 一维数组元素相乘  
array([ 4, 10, 18])  
np.dot(a, b) # 一维数组元素相乘,再求和  
32  
a = np.array([[1, 2], [3, 4]])  
b = np.array([[5, 6], [7, 8]])  
a * b # 多维数组,元素相乘  
array([[ 5, 12],  
       [21, 32]])  
np.dot(a, b) #多维数组,实现矩阵相乘  
array([[19, 22],  
       [43, 50]])  
m = np.mat(a)  
n = np.mat(b)  
np.dot(m, n) # 矩阵相乘  
matrix([[19, 22],  
        [43, 50]])  
m * n # 矩阵相乘  
matrix([[19, 22],  
        [43, 50]])  

3 线性代数模块

numpy.linalg是numpy的线性代数模块, 可以用来解决逆矩阵、特征值、线性方程组以及行列式等问题

3.1 计算逆矩阵

尽管matrix对象本身有逆矩阵属性,但用numpy.linalg模块来求解矩阵的逆,也是非常简单的。

m = np.mat('0 1 2; 1 0 3; 4 -3 8')  
mi = np.linalg.inv(m) # mi即为m的逆矩阵  
m * mi  
matrix([[1., 0., 0.],  
        [0., 1., 0.],  
        [0., 0., 1.]])  

3.2 计算行列式

m = np.mat('0 1 2; 1 0 3; 4 -3 8')  
np.linalg.det(m)  
-2.0  

3.3 计算特征值和特征向量

m = np.mat('0 1 2; 1 0 3; 4 -3 8')  
np.linalg.eigvals(m)  # 计算特征值  
array([ 7.96850246, -0.48548592,  0.51698346])  
np.linalg.eig(m) # 返回特征值及其对应的特征向量的元组  
(array([ 7.96850246, -0.48548592,  0.51698346]),  
 matrix([[ 0.26955165,  0.90772191, -0.74373492],  
         [ 0.36874217,  0.24316331, -0.65468206],  
         [ 0.88959042, -0.34192476,  0.13509171]]))  

3.4 求解线性方程组

x - 2y + z = 0

2y - 8z = 8

-4x + 5y + 9z = -9

A = np.mat('1 -2 1; 0 2 -8; -4 5 9')  
b = np.array([0, 8, -9])  
np.linalg.solve(A, b) # x = 29, y=16, z=3  
array([29., 16.,  3.])  

写个博客不容易,可怜可怜博主,点个广告再走呗(✿◕‿◕✿)。


   转载规则


《Numpy》 ZS 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Matplotlib Matplotlib
matplotlib 用来作图特别的方便,很好用,也是为了数学建模学的,但是呢学过就忘,哎。。
2019-07-24
下一篇 
TCP的三次握手 TCP的三次握手
TCP三次握手TCP/IP协议简介TCP/IP协议是一个协议族,里面包括了IP协议,IMCP协议,TCP协议,以及我们更加熟悉的http、ftp、pop3协议等等,这些协议类似于国际语言,大家在交流时同一使用的语言。 TCP/IP协议的
2019-06-29
  目录