1.3.2.3 广播
- numpy数组的基本操作(相加等)是元素级别的
- 在相同大小的数组上仍然适用。 尽管如此, 也可能在不同大小的数组上进行这个操作,假如Numpy可以将这些数组转化为相同的大小:这种转化称为广播。
下图给出了一个广播的例子:
让我们验证一下:
In [127]:
a = np.tile(np.arange(0, 40, 10), (3, 1)).T
a
Out[127]:
array([[ 0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
In [128]:
b = np.array([0, 1, 2])
a + b
Out[128]:
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]])
在不知道广播的时候已经使用过它!:
In [129]:
a = np.ones((4, 5))
a[0] = 2 # 我们将一个数组的纬度0分配给另一个数组的纬度1
a
Out[129]:
array([[ 2., 2., 2., 2., 2.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
In [130]:
a = np.ones((4, 5))
print a[0]
a[0] = 2 # 我们将一个数组的纬度0分配给另一个数组的纬度
a
[ 1\. 1\. 1\. 1\. 1.]
Out[130]:
array([[ 2., 2., 2., 2., 2.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
一个有用的技巧:
In [133]:
a = np.arange(0, 40, 10)
a.shape
Out[133]:
(4,)
In [134]:
a = a[:, np.newaxis] # 添加一个新的轴 -> 2D 数组
a.shape
Out[134]:
(4, 1)
In [135]:
a
Out[135]:
array([[ 0],
[10],
[20],
[30]])
In [136]:
a + b
Out[136]:
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]])
广播看起来很神奇,但是,当我们要解决的问题是输出数据比输入数据有更多纬度的数组时,使用它是非常自然的。
实例:广播
让我们创建一个66号公路上城市之间距离(用公里计算)的数组:芝加哥、斯普林菲尔德、圣路易斯、塔尔萨、俄克拉何马市、阿马里洛、圣塔菲、阿尔布开克、Flagstaff、洛杉矶。
In [138]:
mileposts = np.array([0, 198, 303, 736, 871, 1175, 1475, 1544, 1913, 2448])
distance_array = np.abs(mileposts - mileposts[:, np.newaxis])
distance_array
Out[138]:
array([[ 0, 198, 303, 736, 871, 1175, 1475, 1544, 1913, 2448],
[ 198, 0, 105, 538, 673, 977, 1277, 1346, 1715, 2250],
[ 303, 105, 0, 433, 568, 872, 1172, 1241, 1610, 2145],
[ 736, 538, 433, 0, 135, 439, 739, 808, 1177, 1712],
[ 871, 673, 568, 135, 0, 304, 604, 673, 1042, 1577],
[1175, 977, 872, 439, 304, 0, 300, 369, 738, 1273],
[1475, 1277, 1172, 739, 604, 300, 0, 69, 438, 973],
[1544, 1346, 1241, 808, 673, 369, 69, 0, 369, 904],
[1913, 1715, 1610, 1177, 1042, 738, 438, 369, 0, 535],
[2448, 2250, 2145, 1712, 1577, 1273, 973, 904, 535, 0]])
许多基于网格或者基于网络的问题都需要使用广播。例如,如果要计算10X10网格中每个点到原点的数据,可以这样:
In [139]:
x, y = np.arange(5), np.arange(5)[:, np.newaxis]
distance = np.sqrt(x ** 2 + y ** 2)
distance
Out[139]:
array([[ 0\. , 1\. , 2\. , 3\. , 4\. ],
[ 1\. , 1.41421356, 2.23606798, 3.16227766, 4.12310563],
[ 2\. , 2.23606798, 2.82842712, 3.60555128, 4.47213595],
[ 3\. , 3.16227766, 3.60555128, 4.24264069, 5\. ],
[ 4\. , 4.12310563, 4.47213595, 5\. , 5.65685425]])
或者用颜色:
In [141]:
plt.pcolor(distance)
plt.colorbar()
Out[141]:
<matplotlib.colorbar.Colorbar instance at 0x10d8d7170>
评论 : numpy.ogrid
函数允许直接创建上一个例子中两个重要纬度向量X和Y:
In [142]:
x, y = np.ogrid[0:5, 0:5]
x, y
Out[142]:
(array([[0],
[1],
[2],
[3],
[4]]), array([[0, 1, 2, 3, 4]]))
In [143]:
x.shape, y.shape
Out[143]:
((5, 1), (1, 5))
In [144]:
distance = np.sqrt(x ** 2 + y ** 2)
因此, np.ogrid
就非常有用,只要我们是要处理网格计算。另一方面, 在一些无法(或者不想)从广播中收益的情况下,np.mgrid
直接提供了由索引构成的矩阵:
In [145]:
x, y = np.mgrid[0:4, 0:4]
x
Out[145]:
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]])
In [146]:
y
Out[146]:
array([[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]])