科学计算包Numpy
NumPy简介
声明:本文所有打印结果的顺序均是按照变量定义的顺序进行排列。
NumPy是Python中用于科学计算的基础包,也是大量Python数学和科学计算包的基础,不少数据分析与挖掘包都是在NumPy基础上开发的,如Pandas包。NumPy的核心基础是N维数组(N-dimensional array,ndarray),即由数据类型相同的元素组成的N维数组。
本文主要介绍一维数组与二维数组,包括数组的创建、运算、切片、连接、数据存取、以及线性代数运算等。
在使用该包前,首先要导入该包,一般导入该包的格式如下:
import numpy as np
数组
一、创建数组
本节主要介绍两种创建数组的方法,一种是利用NumPy中的array()函数将特定的数据类型转换为数组,另一种是利用内置函数创建指定尺寸的数组。
1.1 利用array()函数创建数组
基于array()函数,可以将列表、元组、嵌套列表、嵌套元组等给定的数据结构转化为数组,值得注意的是,利用array()函数之前,要导入NumPy。下面是一个示例:
#先预定义列表d1,元组d2,嵌套列表d3,d4和嵌套元组d5
import numpy as np
d1 = [1,2,3,4,0.1,7]
d2 = (1,2,3,4,2.3)
d3 = [[1,2,3,4],[5,6,7,8]]
d4 = [(1,2,3,4),(5,6,7,8)]
d5 = ((1,2,3,4),(5,6,7,8))
d11 = np.array(d1)
d21 = np.array(d2)
d31 = np.array(d3)
d41 = np.array(d4)
d51 = np.array(d5)
执行结果如下图所示:
1.2 利用内置函数创建数组
利用内置函数可以创建一些特殊的数组,例如,可以利用ones(n,m)函数创建n行m列全为1的数组,利用zeros(n,m)函数创建n行m列元素全为0的数组,利用arange(a,b,c)创建以a为初始值,b-1为末值,c为步长的一维数组。其中a和c可以省略,这时a默认为0,c默认为1。示例如下:
import numpy as np
z1 = np.zeros((1,3))#这里要注意几个维度就几层括号,这里是二维,所以两个。
z2 = np.ones((3,4))#同上
z3 = np.arange(10)
z4 = np.arange(2,10)
z5 = np.arange(2,10,2)
执行结果如下图所示:
二、数组尺寸
数组尺寸也称为数组大小,通过行数与列数来表现。通过数组中的shape属性,可以返回数组的尺寸,其返回值为元组。如果是一维数组,返回元组中仅一个元素,代表这个数组的长度,如果是二维数组,元组中有两个值,第一个值代表了这个数组的行数,第二个值代表了数组的列数。示例代码如下:
import numpy as np
d1 = [1,2,3,4,0.1,7]
d3 = [[1,2,3,4],[5,6,7,8]]
d11 = np.array(d1)
d31 = np.array(d3)
s11 = d11.shape
s31 = d31.shape
执行结果如下图所示:
从结果可以看出一维数组d11的长度为6,二维数组d31的行数为2,列数为4。在程序中,有时候需要将数组进行重排,可以通过reshape()函数进行实现,示例代码如下:
import numpy as np
r = np.array(range(9))
r1 = r.reshape((3,3))#几个维度就有几个括号同上。
执行结果如下图所示:
上图显示了通过reshape函数,将一维数组r转换为了3行3列的二维数组r1。
三、数组运算
数组的运算主要包括数组之间的加减乘除乘方运算,以及数组的数学函数运算。示例代码如下:
import numpy as np
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
C1 = A-B #对应元素做运算,下同
C2 = A+B
C3 = A*B
C4 = A/B
C5 = A/3
C6 = 1/A
C7 = A**2
C8 = np.array([1,2,3,3.1,4.5,6,7,8,9])
C9 = (C8-min(C8))/(max(C8)-min(C8))#对C8的元素做极差化处理
####数学运算
E1 = np.sqrt(C8)#对数组中所有元素去平方根,结果赋给E1
E2 = np.abs([-1])#对给定的参数数组中的元素全部取绝对值,将结果赋给E2
E3 = np.cos([1,-2,3])#取对应参数数组中元素的cos值
E4 = np.sin([1,-2,3])#同上
E5 = np.exp([1])#取指数函数值,也就是以e为底,数组中元素为指数,求值
执行结果如下图所示:
四、数组切片
数组切片即抽取数组中的部分元素构成新的数组,那么如何抽取呢?通过指定数组中的行下标和列下标来抽取元素,从而组成新的数组。下面介绍直接利用数组本身的索引机制来切片和利用ix_()函数构建索引器进行切片这两种方法,第一种方法称为常见的数组切片方法。
4.1 常见的数组切片方法
一般的,假设D为待访问或切片的数据变量,则访问或者切片的数据为D[n,m]。其中n为对D的行下标控制,m为对D的列下标控制,行和列下标控制通过整数列表来实现。但是需要注意的是n整数列表中的元素不能超出D中的最大行数,而m整数列表不能超过D的最大列数。
为了更灵活地操作数据,取所有的行或列,可以用“:”来实现。同时,行控制还可以通过逻辑列表来实现。示例代码如下:
import numpy as np
D = np.array([[1,2,3,4],[5,6,7,8]])
#访问D中行为1,列为2的数据,注意下标是从0开始。
D12 = D[1,2]
#访问D中第1、3列数据
D1 = D[:,[1,3]]
#访问D中第1、2行数据
D2 = D[[1,2],:]
#取D中满足第0列大于5的所有数
Dt1 = D[D[:,0]>5,:]
#------------------------------
TF = [True,False,False,True]
#取D中第0、3列所有数据
Dt3 = D[TF,:]
#取D中第0、3行的2、3列数据
Dt4 = D[TF,[2,3]]
#取D中大于4的所有元素
Dt5 = D[D>4]
执行结果如下图所示:
4.2 利用ix_()函数进行切片
数组的切片也可以通过ix_()函数进行构造、列下标索引器来实现。示例代码如下:
import numpy as np
D = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
#提取D中行数为1、2,列数为1、3的所有元素
D3 = D[np.ix_([1,2],[1,3])]
#提取D中行数为0、1,列数为1、3的所有元素
D4 = D[np.ix_(np.range(2),[1,3])]
#提取以D中第1列小于11的2、3列元素
D6 = D[np.ix_(D[:,1]<11,[1,2])]
#提取以D中第1列小于11的第2列元素
D7 = D[np.ix_(D[:,1]<11,[2])]
TF = [True,False,False,True]
#提取以D中第1行和第四行的第3列元素
D8 = D[np.ix_(TF,[2])]
执行结果如下图所示:
五、数组连接
在数据处理中,多个数据源的集成整合是经常发生的。数组见的集成与整合主要体现在数组间的连接,包括水平连接和垂直连接两种方式。水平连接用hstack()函数实现,垂直连接用vstack()函数实现。
注意输入参数为两个待连接数组组成的元组。示例代码如下:
import numpy as np
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
C = np.hstack((A,B)) #水平连接
D = np.vstack((A,B)) #垂直连接
执行结果如下图所示:
六、数据存取
利用NumPy包中的save()函数,可以将数据集保存为二进制数据文件,数据文件扩展名为.npy,示例代码如下:
import numpy as np
A = np.array([[1,2],[3,4]])
np.save('data',A)
执行结果如下图所示:
load()函数,可以加载该数据集。示例代码如下:
import numpy as np
load_result = np.load('data.npy')
执行结果如下图所示:
七、数组形态变换
NumPy包提供了reshape()函数用于改变数组的形状,reshape()函数仅改变原始数据的形状,不改变原始数据的值。示例代码如下:
import numpy as np
arr = np.arange(12)
arr1 = arr1.reshape(3,4)#设置ndarray的维度3行4列
arr_r = arr1.ravel()#将多维数组转换为一维数组
执行结果如下图所示:
八、数组排序与搜索
通过NumPy提供的sort()函数,可以将数组元素值按从小到大的顺序进行直接排序,示例代码如下:
import numpy as np
arr = np.array([1,2,5,3,6,5,8])
arr1 = np.sort(arr)
执行结果如下图所示:
通过NumPy包提供的argmax()和argmin函数,可以返回待搜索数组最大值和最小值元素的索引值。如果存在多个最大值和最小值,则返回第一次出现的索引值。对于二维数组,可以通过设置axis=0或axis=1返回各列或各行最大值或最小值的索引值。需要注意的是索引值是从0开始。示例代码如下:
import numpy as np
arr = np.array([5,2,3,4,5,1])
arr1 = arr.reshape(2,3)
maxindex = np.argmax(arr)
minindex = np.argmin(arr)
maxindex1 = np.argmax(arr1,axis=0)#返回各列最大值的索引值
minindex1 = np.argmin(arr1,axis=1)#返回各行最小值的索引值
执行结果如下图所示:
矩阵与线性代数运算
NumPy包的matrix()函数继承自NumPy的二维数组ndarray对象,不仅拥有二维ndarray的属性、方法与函数、还拥有诸多特有的属性与方法。同时,NumPy包中的matrix()函数与线性代数中的矩阵概念几乎完全相同,同样含有转置矩阵、共轭矩阵、逆矩阵等概念。
九、创建NumPy矩阵
在NumPy中可使用mat(),matrix()或bmat()函数来创建矩阵。使用mat()函数创建矩阵时,若输入matrix或ndarray对象,则不会为他们创建副本。因此调用mat()函数与调用matrix(data,copy=False)等价。示例代码如下:
import numpy as np
mat1 = np.mat("1 2 3;4 5 6;7 8 9")
mat2 = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
执行结果如下图所示:
在矩阵的日常使用中,将小矩阵组合成大矩阵是一种频率极高的操作。在NumPy中可以使用bmat()分块矩阵,示例代码如下:
import numpy as np
arr1 = np.eye(3)#创建一个3*3的单位矩阵
arr2 = 3*arr1
mat = np.bmat("arr1 arr2;arr1 arr2")
执行结果如下图所示:
十、矩阵的属性和基本运算
矩阵的特有属性及说明,如表:
特有属性 | 说明 |
---|---|
T | 返回自身的转置 |
H | 返回自身的共轭 |
I | 返回自身的逆矩阵 |
矩阵属性的具体查看方法,示例代码如下:
import numpy as np
mat = np.matrix(np.arange(4).reshape(2,2))
mT = mat.T
mH = mat.H
mI = mat.I
执行结果如下图所示:
在NumPy中,矩阵计算和ndarray计算类似,都能够作用于每个元素,比起使用for循环进行计算,矩阵计算更加高效,示例代码如下:
import numpy as np
mat1 = np.mat("1 2 3;4 5 6;7 8 9")
mat2 = mat1*3
mat3 = mat1+mat2
mat4 = mat1-mat2
mat5 = mat1*mat2#矩阵乘法
mat6 = np.multiply(mat1,mat2)#点乘,对应元素相乘
执行结果如下图所示:
10.1 计算逆矩阵
在线性代数中,矩阵A与A的逆矩阵相乘得到一个单位矩阵I。使用numpy.linalg模块中的inv()函数可以计算逆矩阵。示例代码如下:
import numpy as np
mat = np.mat('1 1 1;1 2 3;1 3 6')
inverse = np.linalg.inv(mat)#逆矩阵
A = np.dot(mat,inverse)#验证相乘是否为单位阵
执行结果如下图所示:
10.2 求解线性方程组
矩阵可以对向量进行线性变换,这个对应数学中的线性方程组。numpy.linalg模块中的solve()函数可以求解形如Ax=b的线性方程组,其中A为矩阵,b为一维或二维数组,x是未知变量。示例代码如下:
import numpy as np
A = np.mat("1,-1,1;2,1,0;2,1,-1")
b = np.array([4,3,-1])
x = np.linalg.solve(A,b)#线性方程组Ax=b的解
执行结果如下图所示:
10.3 求解特征值与特征向量
设A是n阶方阵,如果存在数a和非零n维列向量x,使得Ax=ax成立,则称a是A的一个特征值。NumPy中的linalg模块中的eigvals()函数可以求解矩阵的特征值,eig()函数可以返回一个包含特征值与特征向量的元组,示例代码如下:
import numpy as np
A = np.matrix([[1,0,2],[0,3,0],[2,0,1]])
A_value,A_vector = np.linalg.eig(A)
执行结果如下图所示:
10.4 奇异值分解
奇异值分解是线性代数中一种重要的矩阵分解,将一个矩阵分解为3个矩阵的乘积。numpy.linalg模块中的svd()函数可以对矩阵进行奇异值分解,返回U、Sigma、V这三个矩阵。其中,U和V是正交矩阵,Sigma是一维矩阵,其元素为进行奇异值分解的矩阵的非零奇异值。示例代码如下:
import numpy as np
A = np.mat("4,11,14;8,7,-2")
U,sigma,V = np.linalg.svd(A,full_matrices=False)
执行结果如下图所示:
10.5 计算矩阵行列式的值
矩阵行列式是指矩阵的全部元素构成的行列式,当构成行列式的矩阵为方阵时,行列式存在值。numpy.linalg模块中的det()函数可以计算矩阵行列式的值,示例代码如下:
import numpy as np
A = np.mat("3,4;5,6")
A_value = np.linalg.det(A)
执行结果如下图所示:
NumPy小结
本文介绍了Python用于科学计算的基础包Numpy,包括如何导入和使用Numpy包创建数组,以及相关的数组运算、获得数组的尺寸、数组的四则运算与数学函数的运算、数组的切片、数组的连接和数据的存取、数组形态的变换、数组元素的排序与搜索、矩阵及线性代数运算等相关知识。
由于NumPy借鉴了MATLAB矩阵开发思路,故NumPy的数组创建、运算、切片、连接及存取、排序与搜索、矩阵及线性代数运算均与MATLAB的矩阵操作极为相似。如果读者具有一定的MATLAB基础,可以将其与MATLAB进行对比和细细品味,相信一定会有所收获!
谢谢!