有时在二维图上用等高线图或者彩色图来表示三维数据是个不错的方法。Matplotlib 提供了三个函数来解决这个问题:
用 plt.contour 画等高线图
、用 plt.contourf 画带有填充色的等高线图(filled contour plot)的色彩
、用 plt.imshow 显示图形
。
导入画图需要用的函数:
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
import numpy as np
首先用函数 z = f (x, y) 演示一个等高线图,按照下面的方式生成函数 f 样本数据:
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
等高线图可以用 plt.contour
函数来创建。它需要三个参数:x 轴、y 轴、z 轴三个坐标轴的网格数据。x 轴与 y 轴表示图形中的位置,而 z 轴将通过等高线的等级来表示。用np.meshgrid
函数来准备这些数据可能是最简单的方法,它可以从一维数组构建二维网格数据:
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
现在来看看标准的线形等高线图:
plt.contour(X, Y, Z, colors='black');
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
plt.contour(X, Y, Z, colors='black');
plt.show()
需要注意的是,当图形中只使用一种颜色时,默认使用虚线表示负数,使用实线表示正数。另外,你可以用 cmap 参数设置一个线条配色方案来自定义颜色。还可以让更多的线条显示不同的颜色——可以将数据范围等分为 20 份,然后用不同的颜色表示:
plt.contour(X, Y, Z, 20, cmap='RdGy');
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
plt.contour(X, Y, Z, 20, cmap='RdGy');
plt.show()
现在使用 RdGy (红 - 灰,Red-Gray 的缩写)
配色方案,这对于数据集中度的显示效果比较好。Matplotlib 有非常丰富的配色方案,可以在 IPython 里用 Tab 键浏览 plt.cm 模块对应的信息:
plt.cm.<TAB>
虽然上面那幅图看起来漂亮多了,但是线条之间的间隙还是有点大 。我们可以通过 plt.contourf()函数
来填充等高线图(需要注意结尾有字母 f ),它的语法和 plt.contour() 是一样的。
另外还可以通过 plt.colorbar()
命令自动创建一个表示图形各种颜色对应标签信息的颜色条:
plt.contourf(X, Y, Z, 20, cmap='RdGy')
plt.colorbar();
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
plt.contourf(X, Y, Z, 20, cmap='RdGy')
plt.colorbar();
plt.show()
通过颜色条可以清晰地看出,黑色区域是“波峰”(peak),红色区域是“波谷”(valley)
。但是图形还有一点不尽如人意的地方,就是看起来有点儿“污渍斑斑”,不是那么干净。
这是由于颜色的改变是一个离散而非连续的过程,这并不是我们想要的效果。你当然可以通过将等高线的数量设置得非常多来解决这个问题,但是最终获得的图形性能会很不好,因为 Matplotlib 必须渲染每一级的等高线。其实有更好的做法,那就是通过 plt.imshow()函数
来处理,它可以将二维数组渲染成渐变图。
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', cmap='RdGy')
plt.colorbar()
plt.axis(aspect='image');
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower',cmap='RdGy')
plt.colorbar()
plt.axis(aspect='image');
plt.show()
但是,使用 imshow() 函数时有一些注意事项。
• plt.imshow() 不支持用 x 轴和 y 轴数据设置网格,而是必须通过 extent 参数
设置图形的坐标范围 [xmin, xmax, ymin, ymax]
。
• plt.imshow() 默认使用标准的图形数组定义,就是原点位于左上角(浏览器都是如此),而不是绝大多数等高线图中使用的左下角。这一点在显示网格数据图形的时候必须调整。
• plt.imshow() 会 自 动 调 整 坐 标 轴 的 精 度 以 适 应 数 据 显 示。 你 可 以 通 过 plt.axis(aspect='image')
来设置 x 轴与 y 轴的单位。
最后还有一个可能会用到的方法,就是将等高线图与彩色图组合起来。例如,如果我们想创建以下图的效果,就需要用一幅背景色半透明的彩色图(可以通过 alpha 参数设置透明度),与另一幅坐标轴相同、带数据标签的等高线图叠放在一起(用 plt.clabel()
函数实现):
contours = plt.contour(X, Y, Z, 3, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', cmap='RdGy', alpha=0.5)
plt.colorbar();
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
contours = plt.contour(X, Y, Z, 3, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', cmap='RdGy', alpha=0.5)
plt.colorbar();
plt.show()
将 plt.contour
、 plt.contourf
与 plt.imshow
这三个函数组合起来之后,就打开了用二维图画三维数据的无尽可能。
各位老铁来个“关注”、“点赞”、“评论”三连击哦
各位老铁来个“关注”、“点赞”、“评论”三连击哦
各位老铁来个“关注”、“点赞”、“评论”三连击哦