我们将演示如何借助于ufunc的广播运算计算下述二元函数的在一个xy平面上的值并将其绘制成3D曲面。其中,x和y的取值范围均为[-2,+2]。
$$
z = xe^{-x^{2}-y^{2}}
$$

为了达到目的,我们需要一个二维的结果数组z,其元素的下标对应参数x,y的取值,其元素的值则为上述函数的函数值。这可以通过广播计算来得到。

版权声明

本文可以在互联网上自由转载,但必须:注明出处(作者:海洋饼干叔叔)并包含指向本页面的链接。

本文不可以以纸质出版为目的进行改编、摘抄。

np.ogrid是个特殊对象,通过切片下标来生成用于广播运算的数组。先看下述程序:

1
2
3
4
5
6
#ogrid.py
x,y = np.ogrid[0:3:4j,0:4:5j]
print("x=\n",x)
print("y=\n",y)
print("x.shape=",x.shape)
print("y.shape=",y.shape)

执行结果:

1
2
3
4
5
6
7
8
9
x=
[[0.]
[1.]
[2.]
[3.]]
y=
[[0. 1. 2. 3. 4.]]
x.shape= (4, 1)
y.shape= (1, 5)

0:3:4j这种切片语法类似于np.linspace(0,3,4),它表示生成从0到3的包含4个元素的等差数列。这里的j并不表示复数的虚部,它只是一种语法格式。由于广播的需要,x的形状被设置为(4,1)。同理,由于广播需要,y的形状被设置成了(1,5)。这样,通过ogrid生成的x和y数组符合广播运算的规则,可以进行广播运算。

下述代码将x = [-2,+2],y = [-2, +2]的函数值矩阵以平面图形式绘制。

1
2
3
4
5
6
7
8
9
10
11
12
#func2d.py
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm

y,x = np.ogrid[-2:2:200j,-2:2:200j]
z = x * np.exp(-x**2-y**2)
extent = [np.min(x),np.max(x),np.min(y),np.max(y)]

plt.imshow(z,extent=extent,cmap=cm.gray)
plt.colorbar()
plt.show()

根据ogrid的输出,y,x分别是形状为(200,1)和(1,200)的数组。z = x * np.exp(-x**2-y**2)的执行过程中将发生广播,结果数组z将会是一个形状为(200,200)的二维数组,元素值为对应x,y的函数值。如果将z视为一个图像,那么其横向x取值范围对应[-2,+2],纵向y取值范围取应[-2,+2]。

extent = [np.min(x),np.max(x),np.min(y),np.max(y)]将x及y的取值范围放入一个列表。plt.imshow()函数将二维数组z作为图像显示,extent参数指明了横纵坐标的范围,cmap则指定了颜色映射对象,该颜色映射对象负责把z中的元素值转换成像素点的颜色。plt.colorbar()则“聪明”通过颜色条显示z中的函数值与颜色之间的对应关系。plt.show()真正地把图表显示出来。执行结果如下:

1545239941222

下述代码将x = [-2,+2],y = [-2, +2]的函数值矩阵以3D图形式绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
#func3d.py
import numpy as np
import mpl_toolkits.mplot3d
from matplotlib import pyplot as plt
from matplotlib import cm

x,y = np.mgrid[-2:2:20j,-2:2:20j]
z = x * np.exp(- x**2 - y**2)

fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_surface(x,y,z,cmap=cm.ocean)
plt.show()

ax是表示一个子图,由于ax.plot_surface()函数要求x,y,z三个数组都必须是相同形状的二维数组,所以上述代码中没有使用ogrid来生成广播数组,而是使用了mgrid。mgrid的功能与ogrid相近,区别在于其返回的是已经进行了形状扩充的数组。也就是说,上述通过mgrid生成出来的x,y数组的形状已经是(20,20)。读者可以自行打印x,y的值出来观察mgrid对象的用法。读者如果对matplotlib相关代码感到疑惑,请先略过,本书后续部分将解读matplotlib包的使用。上述程序执行结果如下:

1545240678047


本文内容节选自作者编著的《Python编程基础及应用》(高等教育出版社)一书。

Python编程基础及应用

免费随书B站MOOC: