Python中的数组-NumPy数组

Python的NumPy包提供了NumPy数组,它是为数组运算,特别是比较大型的数组运算设计的。NumPy包是Python科学计算方面的基础包,也是很重要,必须掌握的一个包。

NumPy包及其安装

NumPy数组在数据输入输出性能和存储效率方面比Python的嵌套列表好很多,一方面,NumPy底层是使用C语言编写的,效率远胜于纯Python代码;另一方面,NumPy使用矢量运算的技术,避免了多重嵌套for循环的使用,极大地提高了计算速度。所以,NumPy非常适用于多维数组的计算,数组越大,优势越明显。NumPy是Python实现数据分析、机器学习、深度学习的基础,SciPy, pandas, scikit-learn和tensorflow等包都是在它的基础上开发出来的。

本书是使用Python官网上下载的软件Python 3.7.7进行介绍的,软件并不包含NumPy模块,所以,使用它们之前需要先进行安装。在DOS命令窗口用pip工具安装它们。

在DOS命令窗口的提示符后键入下面的命令行,安装NumPy。

code.python
python –m pip install numpy

安装位置一般在C:\Users\用户名\ AppData\Local\Programs\Python\Python3x下。最后的Python3x对应于Python软件的版本,如果版本为3.7,则为Python37。

创建NumPy数组

在NumPy中创建数组的方法很简单,只需要用逗号间隔数组元素,然后用方括号括起来作为array方法的参数就行了。当然,也可以理解为将一个列表转换为NumPy数组,如

code.python
>>> import numpy as np
>>> a=np.array([1,2,3])
>>> print a
array([1, 2, 3])

可以使用numpy.arange方法用增量法创建向量。该方法返回一个ndarray对象,包含给定范围内的等间隔值。语法格式为:

code.python
numpy.arange(start, stop, step, dtype)

其中,start表示范围的起始值,默认为0;stop表示范围的终止值(不包含);step表示两个值的间隔,默认值为1;dtype表示返回的ndarray对象的数据类型,如果没有提供,则会使用输入数据的数据类型。

下面的例子展示如何使用该函数:

code.python
>>> x=np.arange(5)
>>> print(x)
[0  1  2  3  4]

下面用dtype参数设置数据的数据类型。

code.python
>>> x = np.arange(5, dtype = float)
>>> print(x)
[0.  1.  2.  3.  4.]

当起始值大于终止值,并且步长值为负数时生成逆序排列的数据序列。

code.python
>>> x = np.arange(10,0,-2)
>>> print(x)
[10  8  6  4  2]

使用linspace函数和logspace函数,可以创建等差数列和等比数列。

linspace函数类似于arange函数,但是它指定范围之间的均匀间隔数,而不是步长。 该函数的语法格式为:

code.python
numpy.linspace(start, stop, num, endpoint, retstep, dtype)

其中,start表示序列的起始值;stop表示序列的终止值,如果endpoint为true,该值包含于序列中;num为要生成的等间隔数,默认值为50;endpoint表示序列中是否包含stop值,默认值为ture,此时间隔步长取为(stop-start)/(num-1) ,否则间隔步长取为(stop-start)/num;retstep的值如果为true时,输出数据序列和连续数字之间的步长值;dtype表示输出ndarray的数据类型。

下面的例子展示了linspace函数的用法。

code.python
>>> x=np.linspace(10,20,5)
>>> print(x)
[10.   12.5   15.   17.5  20.]

将endpoint参数的值设置为False,此时步长值为(20-10)/5=2。序列不包含终止值。

code.python
>>> x=np.linspace(10,20, 5, endpoint = False)
>>> print(x)
[10.   12.   14.   16.   18.]

使用logspace函数,可以生成等比数列。它返回一个ndarray对象,其中包含在对数刻度上均匀分布的数字。 刻度的起始值和终止值是某个底数的幂,通常为 10。

code.python
numpy.logscale(start, stop, num, endpoint, base, dtype)

其中,start表示起始值是base ** start;stop表示终止值是base ** stop;num表示范围内的取值个数,默认值为50;endpoint为true时,终止值包含在输出数组当中;base表示对数空间的底数,默认值为10;dtype表示输出数据的数据类型,如果没有提供,则取决于其它参数。

下面的例子展示了logspace函数的用法。

code.python
# 默认时以10为底
>>> x = np.logspace(1.0, 2.0, num = 10)
>>> print(x)
[ 10.           12.91549665     16.68100537      21.5443469  27.82559402
  35.93813664   46.41588834     59.94842503      77.42636827    100.    ]
# 将对数空间的底数设置为 2
>>> x = np.logspace(1,10,num = 10, base = 2)
>>> print(x)
[ 2.     4.     8.    16.    32.    64.   128.   256.    512.   1024.]

使用fromiter函数,可以通过迭代的方法从任何可迭代对象构建一个ndarray对象,返回一个新的一维数组。该函数的语法格式为:

code.python
numpy.fromiter(iterable, dtype, count = -1)

其中,iterable表示任何可迭代对象;dtype表示返回数据的数据类型;count表示需要读取的数据个数,默认为-1,读取所有数据。

下面的例子从给定列表获得迭代器,然后使用该迭代器创建向量。

code.python
>>> lst = range(5)
>>> it = iter(lst)
>>> x = np.fromiter(it, dtype = float)
>>> print(x)
 [0.   1.   2.   3.   4.]

通过列表嵌套的方法,可以直接创建二维和多维数组。例如,下面创建一个2*2的矩阵。

code.python
>>> c=np.array([[1.,2.],[3.,4.]])
>>> print(c)
[[1. 2.]
[3. 4.]]

NumPy数组的索引和切片

通过索引或切片,可以从NumPy数组中获取单个的值或者连续获取多个值。下面用arange方法创建一个NumPy数组。

code.python
>>> a=np.arange(8)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7])

获取数组中的第3个值。注意索引号的基数为0。

code.python
>>> a[2]
2

获取数组中第3-5范围内的值。注意包头不包尾原则,即索引号5对应的第6个值不包括进来。

code.python
>>> a[2:5]
array([2, 3, 4])

获取数组中第3个及后面所有的值。注意冒号的用法,冒号表示连续取值,即进行切片操作。冒号在前面,表示前面的值全取;冒号在后面,表示后面的值全取;冒号在两个数之间,表示取这两个数确定的范围内的所有值。

code.python
>>> a[2:]
array([2, 3, 4, 5, 6, 7])

获取数组中前5个数据。

code.python
>>> a[:5]
array([0, 1, 2, 3, 4])

获取数组中倒数第3个值。

code.python
>>> a[-3]
5

获取数组中倒数第3个及它后面所有的值。

code.python
>>> a[-3:]
array([5, 6, 7])

NumPy数组计算

作为Python科学计算的基础包,NumPy封装了大量基础数学、统计分析、线性代数和数值分析等相关的函数。使用这些函数,可以很方便地进行计算,也可以利用它们进行二次开发。

一、数学函数

NumPy提供的基础数学函数如表7-3所示,包括求绝对值的函数、求平方、平方根、指数、对数、圆整和三角函数等。

表7-3 NumPy包提供的数学函数

函 数 说 明
abs, fabs 绝对值。对于非复数,用fabs函数更快
square 元素取平方
sqrt 元素取平方根
exp 元素的指数
log, log10, log2 元素的自然对数、10为底的对数、2为底的对数
sign 计算元素的正负号,1为正数,0为零,-1为负数
cell 元素取大于等于该值的最小整数
floor 元素取小于等于该值的最大整数
rint 元素取原值四舍五入的整数
cos, cosh, sin, sinh, tan, tanh 三角函数
arccos, arccosh, arcsin, arcsinh, arctan, arctanh 反三角函数

下面导入NumPy包,对于给定的列表,计算列表元素的平方值和正弦值。

code.python
>>> import numpy as np
>>> a=[3,2,5,1,4]
>>> np.square(a)  #平方
array([ 9,  4, 25,  1, 16], dtype=int32)
>>> np.sin(a)  #正弦
array([ 0.14112001,  0.90929743, -0.95892427,  0.84147098, -0.7568025 ])

二、统计计算

NumPy包提供的统计分析函数如表7-4所示,包括求最大值、最小值、均值、中值、和、方差等统计量的函数。

表7-4 NumPy包提供的统计函数

函 数 说 明
min 最小值
max 最大值
mean 均值
median 中值
sum
prod 乘积
cumsum 累加求和
cumprod 累加求积
std 标准差
var 方差
argmin 最小值的索引
argmax 最大值的索引

下面导入NumPy包,对于给定的列表数据,计算指定的统计量。

code.python
>>> import numpy as np
>>> a=[3,2,5,1,4]
>>> np.max(a)  #最大值
5
>>> np.mean(a)  #均值
3.0
>>> np.sum(a)  #和
15
>>> np.median(a)  #中值
3.0
>>> np.var(a)  #方差
2.0

三、构造特殊矩阵

矩阵计算中常常需要构造一些特殊矩阵,比如元素全为0的矩阵、元素全为1的矩阵、单位矩阵等。表7-5列出了NumPy包提供的构造特殊矩阵的函数。

表7-5 NumPy包提供的构造特殊矩阵的函数

函 数 说 明
numpy.zeros 创建一个元素全部为0的矩阵
numpy.ones 创建一个元素全部为1的矩阵
numpy.eye 创建一个对角线元素为1,其余元素为0的矩阵
numpy.identity 创建一个指定大小的单位矩阵
numpy.random.randn 创建一个指定大小的矩阵,元素为随机数
numpy.empty 创建一个新矩阵

下面导入NumPy包,用NumPy包提供的函数构造特殊矩阵。

code.python
>>> import numpy as np
>>> np.ones((3,2))  #3行2列的矩阵,值全为1
array([[1., 1.],
       [1., 1.],
       [1., 1.]])
>>> np.zeros((2,4))  #2行4列的矩阵,值全为0
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.]])
>>> np.random.randn(2,3)  #2行3列的矩阵,值全为随机数
array([[ 0.76904717, -0.33417294,  0.89698686],
       [-1.88668519,  0.057794  ,  0.60373711]])

四、表达式运算

可以对NumPy数组进行算术运算、比较运算和逻辑运算等,NumPy包提供的表达式运算函数如表7-6中所示。

表7-6 NumPy包提供的数组表达式运算函数

函 数 说 明
add 数组对应的元素相加
subtract 数组对应的元素相减
multiply 数组对应的元素相乘
divide, floor_divide 数组对应的元素相除或相除后向下圆整
power 第1个数组的元素用第2个数组的对应元素进行指数运算
maximum, fmax 元素的最大值,fmax函数忽略空值
minimum, fmin 元素的最小值,fmin函数忽略空值
mod 元素求模运算
copysign 第2个数组中元素的符号复制给第1个数组中的元素
greater, greater_equal, less, less_equal, equal, not_equal 比较运算,大于、大于等于、小于、小于等于、等于、不等于,相当于>, >=, <, <=, ==, !=
logical_and, logical_or, logical_xor 逻辑运算,逻辑与、逻辑或、逻辑异或,相当于&, |, ^

下面导入NumPy包,用NumPy包提供的函数对给定数组进行四则运算和比较运算。

code.python
>>> import numpy as np
>>> a=np.array([[1,2,3],[4,5,6]])
>>> b=np.array([[5,8,2],[4,9,3]])
>>> np.add(a,b)  #元素求和
array([[ 6, 10,  5],
       [ 8, 14,  9]])
>>> np.multiply(a,b)  #元素相乘
array([[ 5, 16,  6],
       [16, 45, 18]])
>>> np.greater(a,b)  #元素比较
array([[False, False,  True],
       [False, False,  True]])

五、线性代数

NumPy包提供了一些线性代数计算的函数如表7-7所示,包括矩阵转置、相乘、行列式、求逆和解方程等。

表7-7 NumPy包提供的线性代数计算函数

函 数 说 明
numpy.transpose 转置
numpy.dot 点积,数组对应元素相乘
numpy.vdot 两个向量的点积
numpy.inner 内积
numpy.matmul 矩阵相乘
numpy.linalg.det 行列式
numpy.linalg.solve 解线性方程
numpy.linalg.inv 矩阵求逆

下面导入NumPy包,用NumPy包提供的函数进行线性代数运算。

code.python
>>> import numpy as np
>>> a=[[1,2,3],[4,5,6],[7,8,9]]
>>> np.transpose(a)  #矩阵转置
array([[1, 4, 7],
       [2, 5, 8],
       [3, 6, 9]])
>>> np.linalg.det(a)  #矩阵行列式
6.66133814775094e-16
>>> np.linalg.inv(a)   #矩阵求逆
array([[-4.50359963e+15,  9.00719925e+15, -4.50359963e+15],
       [ 9.00719925e+15, -1.80143985e+16,  9.00719925e+15],
       [-4.50359963e+15,  9.00719925e+15, -4.50359963e+15]])

Excel工作表与NumPy数组交换数据

使用Python的xlwings包可以很方便地实现NumPy数组数据在Excel工作表中的读写。下面将一个二维NumPy数组写入到Excel工作表中B2单元格为左上角的区域。

code.python
>>> import numpy as np
>>> sht=xw.Book().sheets(1)
>>> sht.range('B2').value=np.array([[1,2,3],[4,5,6],[7,8,9]])

写入效果如图7-12所示。

Document Image

图7-12 在Excel工作表中写入NumPy数据

将工作表中指定区域内的数据读取到NumPy数组中,用选项工具指定np.array值即可。下面将B2单元格所在区域内的数据读取到arr数组中。

code.python
>>> arr=sht.range('B2').options(np.array, expand='table').value
>>> arr
array([[1., 2., 3.],
      [4., 5., 6.],
      [7., 7., 9.]])