使用NumPy数组进行面向数组编程

1使用数组进行面向数组编程

使用NumPy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无须写些大量循环。这种利用数组表达式来替代显示循环的方法,称为向量化。
假设我们想要对一些网格数据来计算函数sqrt(x ^ 2 + y ^ 2)的值。np.meshgrid函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵:

import numpy as np
points = np.arange(-5,5,0.01)
xs,ys = np.meshgrid(points,points)
print(ys)
-----------------------------------
[[-5.   -5.   -5.   ... -5.   -5.   -5.  ]
 [-4.99 -4.99 -4.99 ... -4.99 -4.99 -4.99]
 [-4.98 -4.98 -4.98 ... -4.98 -4.98 -4.98]
 ...
 [ 4.97  4.97  4.97 ...  4.97  4.97  4.97]
 [ 4.98  4.98  4.98 ...  4.98  4.98  4.98]
 [ 4.99  4.99  4.99 ...  4.99  4.99  4.99]]

我们也可以用和两个坐标值同样的表达式来使用函数:

z = np.sqrt(xs ** 2 + ys ** 2)
print(z)
-----------------------------------
[[7.07106781 7.06400028 7.05693985 ... 7.04988652 7.05693985 7.06400028]
 [7.06400028 7.05692568 7.04985815 ... 7.04279774 7.04985815 7.05692568]
 [7.05693985 7.04985815 7.04278354 ... 7.03571603 7.04278354 7.04985815]
 ...
 [7.04988652 7.04279774 7.03571603 ... 7.0286414  7.03571603 7.04279774]
 [7.05693985 7.04985815 7.04278354 ... 7.03571603 7.04278354 7.04985815]
 [7.06400028 7.05692568 7.04985815 ... 7.04279774 7.04985815 7.05692568]]

接下来使用matplotlib来生成这个二维数组的可视化:

plt.imshow(z,cmap = plt.cm.gray)
plt.colorbar()
plt.title("Image plot of $sqrt{x^2+y^2}$ for a grid of values")
plt.show()

生成的图像如图:
在这里插入图片描述

1.1将条件逻辑作为数组操作

np.where函数是三元表达式x if condition else y的向量化版本:

xarr = np.array([1.1,1.2,1.3,1.4,1.5])
yarr = np.array([2.1,2.2,2.3,2.4,2.5])
cond = np.array([True,False,True,True,False])
result = [(x if c else y)
          for x,y,c in zip(xarr,yarr,cond)]
print(result)
---------------------------------------------
[1.1, 2.2, 1.3, 1.4, 2.5]

上述这段代码表示当cond中的元素为True时,我们取xarr中的对应元素,否则取yarr中的元素。
使用np.where可以非常简单地完成:

xarr = np.array([1.1,1.2,1.3,1.4,1.5])
yarr = np.array([2.1,2.2,2.3,2.4,2.5])
cond = np.array([True,False,True,True,False])
result = np.where(cond,xarr,yarr)
print(result)
---------------------------------------------
[1.1 2.2 1.3 1.4 2.5]

np.where的第二个参数和第三个参数并不需要是数组,它们可以是标量。where在数据分析中的一个典型用法是根据一个数组来生成另一个新的数组:

arr = np.random.randn(4,4)
print(arr)
--------------------------------------------------
[[ 1.21632914 -1.50662094  0.62310929  0.2784616 ]
 [ 1.55591903  1.12405435  1.01905272 -0.35865934]
 [-0.1620057  -1.46639065  0.63714704  0.94117963]
 [-0.67466668 -0.18557065 -0.19931116  0.02813137]]
print(np.where(arr > 0,2,-2))
--------------------------------------------------
[[ 2 -2  2  2]
 [ 2  2  2 -2]
 [-2 -2  2  2]
 [-2 -2 -2  2]]

上述这段代码表示将随机生成的矩阵数据中的正值都替换为2,其余的值替换为-2。
使用下面这段代码仅将正值设为2:

np.where(arr > 0,2,arr)

传递给np.where的数组既可以是同等大小的数组,也可以是标量。

1.2数学和统计方法

许多关于计算整个数组统计值或关于轴向数据的数学函数,可以作为数组类型的方法被调用。我们可以使用聚合函数(缩进函数),比如sum、mean、std(标准差),既可以直接调用数组实例的方法,也可以使用顶层的NumPy函数。
我们可以生成一些正态分布的随机数,并且计算部分聚合统计数据:

arr = np.random.randn(5,4)
print(arr)
print(arr.mean()) #求矩阵中所有数据的平均数
print(np.mean(arr)) #求矩阵中所有数据的平均数
print(arr.sum()) #求矩阵中所有数据的和

像mean、sum等函数可以接收一个可选参数axis,这个参数可以用于计算给定轴向上的统计值,形成下降一维度的数组:

print(arr.mean(axis = 1)) #计算每一列的平均值
print(arr.sum(axis = 0)) #计算每一行的和

例如cumcum和cumprod等函数并不会聚合,它们会产生一个中间结果:

arr = np.array([0,1,2,3,4,5,6,7])
print(arr.cumsum()) #[ 0  1  3  6 10 15 21 28]

在多维数组中,可以在指定轴向上根据较低维度的切片进行部分聚合:

arr = np.array([[0,1,2],[3,4,5],[6,7,8]])
print(arr)
-----------------------------------------
[[0 1 2]
 [3 4 5]
 [6 7 8]]
print(arr.cumsum(axis = 0))
-----------------------------------------
[[ 0  1  2]
 [ 3  5  7]
 [ 9 12 15]]
print(arr.cumprod(axis = 1))
-----------------------------------------
[[  0   0   0]
 [  3  12  60]
 [  6  42 336]]

表1-1:基础数组统计方法

方法 描述
mean 数学平均,0长度的数组平均值为NaN
std,var 标准差和方差,可以选择自由度调整(默认分母是n)
argmin,argmax 最小值和最大值的位置
cumsum 从0开始的累积和
cumprod 从0开始的累积积

1.3布尔值数组的方法

sum函数也可以用于计算布尔值数组中的True的个数:

arr = np.random.randn(100)
print((arr > 0).sum()) #47

对于布尔值数组,有两个方法any和all。any检查数组中是否至少有一个True,而all检查是否每个值都是True:

bools = np.array([False,False,True,False])
print(bools.any()) #True
print(bools.all()) #False

这些方法也可适用于非布尔值数组,所有非0元素都会按True处理。

1.4排序

NumPy数组也可以使用sort方法按位置排序:

arr = np.random.randn(6)
print(arr)
-------------------------------------------------------------------------
[ 0.53632097  0.29496073  1.1998889   2.30062577 -0.04549287  0.76208047]
arr.sort()
print(arr)
-------------------------------------------------------------------------
[-0.04549287  0.29496073  0.53632097  0.76208047  1.1998889   2.30062577]

我们也可以在多维数组中根据传递的axis的值,沿着轴向对每个一维数据段进行排序:

arr = np.random.randn(5,3)
print(arr)
--------------------------------------
[[-0.33661808  0.89571615 -1.42058487]
 [-0.76615842 -1.13877178 -1.04613436]
 [-0.18069874 -1.18844477  1.21160409]
 [-1.16649883  2.54782531 -1.18748065]
 [-0.57765213  1.16266895 -0.55191486]]
arr.sort(1)
print(arr)
--------------------------------------
[[-1.42058487 -0.33661808  0.89571615]
 [-1.13877178 -1.04613436 -0.76615842]
 [-1.18844477 -0.18069874  1.21160409]
 [-1.18748065 -1.16649883  2.54782531]
 [-0.57765213 -0.55191486  1.16266895]]

1.5唯一值与其他集合逻辑

np.unique方法返回的是数组中唯一值排序后形成的数组:

names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
print(np.unique(names)) #['Bob' 'Joe' 'Will']

纯python是这样来实现的:

print(sorted(set(names))) #['Bob', 'Joe', 'Will']

另一个函数,np.in1d,可以检查一个数组中的值是否在另一个数组中,并返回一个布尔值数组:

values = np.array([6,0,0,3,2,5,6])
print(np.in1d(values,[2,3,6])) #[ True False False  True  True False  True]

猜你喜欢

转载自blog.csdn.net/weixin_43303087/article/details/84296632