查看全课大纲(第 45 / 51 节)
  1. 1.Python 是什么?为什么值得学?
  2. 2.如何为 Python 编程准备一个“全家桶”环境?
  3. 3.Python 有哪几种执行方法?
  4. 4.行与缩进到底有什么用?
  5. 5.注释有什么用,怎么写?
  6. 6.变量:如何给数据起个好名字?
  7. 7.运算符的优先级和常见坑点是什么?
  8. 8.Python 中,数字和布尔值究竟有哪几种?
  9. 9.输入函数 `input()` 和文件读取 `open()` 怎么用?
  10. 10.如何将程序的结果展示给用户或保存下来?
  11. 11.CSV 文件怎么读怎么写才方便?
  12. 12.列表是什么,如何创建和访问它?
  13. 13.列表的修改操作,有哪些方法?
  14. 14.列表切片为什么能取到部分元素?排序和查找又该怎么用?
  15. 15.判断语句:如何让程序根据条件做不同的事?
  16. 16.for 循环如何遍历序列中的元素?
  17. 17.while 循环什么时候才会停?
  18. 18.while 循环的结束条件,你写对了吗?
  19. 19.循环中途想提前结束,怎么办?
  20. 20.`break` 和 `continue` 到底有什么区别?
  21. 21.列表推导式如何让代码更简洁高效?
  22. 22.字符串怎么定义、拼接和操作?
  23. 23.元组:为什么定义单个元素时要加逗号?
  24. 24.集合(set)怎么用?如何快速去重和做集合运算?
  25. 25.字典是什么,为什么比列表更方便?
  26. 26.字典的增删改查与遍历,如何避免 KeyError?
  27. 27.函数里的变量,为什么有的能用有的不能用?
  28. 28.在函数内部修改全局变量,为什么有时不生效?
  29. 29.函数里能修改全局变量吗?返回值怎么用?
  30. 30.匿名函数:如何用 lambda 快速定义简单函数?
  31. 31.面向对象编程是什么,为什么需要它?
  32. 32.类中的方法和属性到底怎么定义和使用?
  33. 33.如何控制对对象内部属性和方法的访问?
  34. 34.异常发生时,程序会怎样继续执行?
  35. 35.如何组织代码:包和模块
  36. 36.`if __name__ == '__main__'` 到底有什么用?
  37. 37.如何用 IDE 的 Debug 功能排查程序错误?
  38. 38.Matplotlib 绘图的第一步该做什么?
  39. 39.Figure 是什么,如何设置图形尺寸?
  40. 40.如何自定义 Matplotlib 的坐标轴?
  41. 41.如何为图表添加图例,让不同曲线一目了然?
  42. 42.饼图怎么画才能直观展示数据占比?
  43. 43.如何用 Matplotlib 绘制散点图?
  44. 44.柱状图怎么画?
  45. 45.如何使用 Matplotlib 绘制等高线图?
  46. 46.如何在 Matplotlib 中绘制子图?
  47. 47.zip 函数如何把多个列表“打包”在一起?
  48. 48.如何给可迭代对象加上索引?
  49. 49.random 模块如何生成随机数?
  50. 50.math 模块怎么用?
  51. 51.Counter 如何快速统计元素出现次数?

如何使用 Matplotlib 绘制等高线图?

约 10 分钟

小象实战讲义 · Python 编程从入门到实践

在之前的课程中,我们学习了如何使用 Matplotlib 绘制折线图、柱状图等,它们主要描述了两个变量(如 X 和 Y)之间的关系。本节我们将学习一种新的图形——等高线图,它用于可视化三个变量之间的关系:X、Y 以及一个由 X 和 Y 共同决定的函数值 Z。学完本节,你将能够使用 contourf 和 contour 函数绘制出带有颜色填充和边界线的等高线图,并理解其背后的数据准备过程。

💡 核心导读

  • 等高线图是什么:一种用于展示三维数据(X, Y, Z)在二维平面上投影的图形,其中 Z 是 X 和 Y 的函数。同一条等高线上的点,其 Z 值相等。
  • 核心绘制函数:plt.contourf 用于填充等高线之间的区域,plt.contour 用于绘制等高线边界。
  • 数据准备关键:绘制前需要使用 np.meshgrid 函数将一维的 X、Y 数组转换为二维网格矩阵,这是等高线函数能正确计算的基础。
  • 主要参数:contourf 和 contour 的前三个参数是必需的,分别是网格化的 X、Y 坐标以及 Z 值函数。其他参数如第四个位置参数(层级数量)、alpha(透明度)、cmap(颜色映射)用于控制图形样式。

什么是等高线图?

等高线图是一种将三维曲面投影到二维平面上的可视化方法。想象一座山,地图上用一圈圈的闭合曲线表示相同海拔高度的点,这些曲线就是等高线。

在数学和编程中,我们有一个关于 X 和 Y 的函数 Z = f(X, Y)。等高线图展示的就是所有满足 f(X, Y) = C(C 为某个常数)的 (X, Y) 点的集合。在同一条等高线上,函数值 Z 是相等的。

例如,函数 f(x, y) = x + y 的等高线就是一系列斜率为 -1 的直线,在同一条直线上的所有点,其 x + y 的和都相同。

如何绘制等高线图?

绘制等高线主要用到 Matplotlib 的两个函数:plt.contourf 和 plt.contour。前者用于填充等高线之间的区域(用颜色区分高度),后者用于绘制等高线的边界线。

绘制过程分为三步:

  1. 准备数据:生成 X 和 Y 的一维坐标数组,并用 np.meshgrid 将其转换为二维网格。
  2. 计算高度:根据函数关系 Z = f(X, Y) 计算网格上每个点的高度值。
  3. 调用绘图函数进行绘制。

下面我们通过一个具体例子来演示,绘制函数 f(x, y) = x² + y² 的等高线图。

import matplotlib
matplotlib.use("Agg")  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

# 1. 准备数据:生成一维坐标点
n = 256  # 点的数量,决定图形的精细度
x = np.linspace(-3, 3, n)  # 在-3到3之间生成256个等距点
y = np.linspace(-3, 3, n)  # Y轴同样范围

# 2. 关键步骤:使用 meshgrid 生成二维网格坐标矩阵
X, Y = np.meshgrid(x, y)
# 现在 X 和 Y 都是二维数组(矩阵),它们共同定义了整个坐标平面上的网格点

# 3. 定义高度函数 Z = f(X, Y)
def height_func(x, y):
    return x ** 2 + y ** 2

# 4. 计算网格上每个点的高度值 Z
Z = height_func(X, Y)

# 5. 开始绘图
plt.figure(figsize=(5, 5))

# 使用 contourf 填充颜色区域
# 参数:X, Y网格,Z值,8(将Z值范围分成8个区域进行填充),alpha(透明度),cmap(颜色映射)
plt.contourf(X, Y, Z, 8, alpha=0.75, cmap=plt.cm.hot)

# 使用 contour 绘制等高线边界
# 参数:X, Y网格,Z值,8(绘制8条等高线),colors(边界线颜色)
plt.contour(X, Y, Z, 8, colors='black')

# 释放图形资源,在实际脚本中,如果后续不再绘图,建议调用
plt.close()

执行上述代码会生成一个圆形区域的等高线图:黑色的同心圆环就是等高线。因为函数是 x² + y²,所以等高线是标准的圆形。

理解 meshgrid 的作用

为什么不能直接把一维数组 x 和 y 传给 contourf,而必须先用 meshgrid 处理?这是本节的一个关键点。

contourf 和 contour 需要知道平面上每一个点的 (X, Y) 坐标。一维数组 x 和 y 只是分别定义了 X 轴和 Y 轴上的坐标值。meshgrid 的作用就是根据这两个一维数组,生成覆盖整个矩形区域的所有点的坐标矩阵。

简化理解: 假设 x = [1, 2, 3], y = [4, 5]。

  • X, Y = np.meshgrid(x, y) 会生成:
    • X = [[1, 2, 3], [1, 2, 3]] (将 x 在垂直方向复制了 len(y) 次)
    • Y = [[4, 4, 4], [5, 5, 5]] (将 y 在水平方向复制了 len(x) 次)
  • 这样,X 和 Y 中相同位置的元素就配对形成了一个点的坐标。例如,X[0,1] 和 Y[0,1] 是 (2, 4)。

只有这样,我们才能方便地计算每个网格点上的函数值 Z[i, j] = f(X[i, j], Y[i, j])。

调整图形样式:参数详解

contourf 和 contour 函数提供了许多参数来定制图形外观。除了必须的 X, Y, Z,常用的还有:

  • 第四个参数(位置参数,层级数量):控制把 Z 值范围分成多少个层级。例如 plt.contourf(X, Y, Z, 8) 表示把 Z 值范围分成 8 个区域。
  • alpha:颜色填充的透明度,范围 0(完全透明)到 1(完全不透明)。
  • cmap:颜色映射(colormap),用于将 Z 值映射到颜色。例如 plt.cm.hot(热力图),其他可选值可查阅官方文档。
  • colors:指定等高线的颜色。contour 用它控制边界线颜色;contourf 也接受这个参数,但填充区域通常交给 cmap 按高度做颜色渐变。

让我们把填充区域和边界线的数量分别设置,看看效果变化:

import matplotlib
matplotlib.use("Agg")  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

# 数据准备
n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
Z = X ** 2 + Y ** 2

plt.figure(figsize=(5, 5))

# contourf 的第四个参数设为 8:把 Z 值范围分成 8 个区域填充
plt.contourf(X, Y, Z, 8, alpha=0.5, cmap=plt.cm.hot)
# contour 的第四个参数设为 4:只画 4 条边界线
plt.contour(X, Y, Z, 4, colors='blue')

plt.close()

这段代码里填充区域是 8 个,边界线只有 4 条:每两个区域之间才出现一条边界线。contourf 和 contour 的第四个参数分别起作用,可以设置成不同的数。

再换一个高度函数,看看等高线的形状有什么变化:

import matplotlib
matplotlib.use("Agg")  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
Z2 = X + Y  # 新的高度函数:f(x,y) = x + y

plt.figure(figsize=(5, 5))
plt.contourf(X, Y, Z2, 8, alpha=0.75, cmap=plt.cm.hot)
plt.contour(X, Y, Z2, 8, colors='green')
plt.close()

这里绘制函数 Z = X + Y 的等高线:等高线变成了平行的直线,因为对于固定的 Z,方程 X+Y=常数 是一条直线,同一条直线上所有点的 X+Y 值相同。

📝 动手练一练

  1. 修改函数与观察:把第一个示例的高度函数改成 Z = X + Y,同时把 contour 的第四个参数从 8 改成 4,运行后观察:填充区域有几个?边界线有几条?
👉 点击查看参考答案

思路:高度函数改成 X + Y 后,等高线会变成平行的直线;contourf 的第四个参数仍然是 8,contour 的参数改成 4,所以填充是 8 个区域、边界线是 4 条。

代码片段:

import matplotlib
matplotlib.use("Agg")  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
Z = X + Y  # 修改高度函数

plt.figure(figsize=(5,5))
plt.contourf(X, Y, Z, 8, alpha=.75, cmap=plt.cm.hot)
plt.contour(X, Y, Z, 4, colors='black')
plt.close()

观察结果:填充区域有 8 个,边界线只有 4 条,仍然是每两个区域一条边界线;等高线本身是一组平行直线。

常见错误

错误写法现象或报错原因正确写法
plt.contourf(x, y, f(x, y), 8)
(x, y为一维数组)
TypeError: Input z must be 2D, not 1D。contourf 要求 X, Y 是二维网格坐标数组,用于定位平面上每一个点。直接传入一维数组,函数无法构建完整的坐标网格。先用 X, Y = np.meshgrid(x, y) 生成网格,再传入 plt.contourf(X, Y, f(X,Y), 8)。
Z = f(x, y)
(计算 Z 时仍使用一维 x, y)
若 x、y 等长,得到一维 Z,后续报 TypeError: Input z must be 2D, not 1D;若 x、y 不等长,则报 ValueError: operands could not be broadcast together with shapes (2,) (3,)。一维的 x 和 y 没有形成网格,无法得到与网格对应的二维 Z 值数组。使用网格化后的 X, Y 计算 Z:Z = f(X, Y)。确保 f 能处理二维数组输入。
plt.contourf(X, Y, Z)
(省略第四个参数)
不会报错,但会使用默认的层级数量,层数不受你控制,可能不符合预期。不指定第四个参数时,函数会自动选择默认数量的层级。明确指定层级数量,如 plt.contourf(X, Y, Z, 8)。
在 Jupyter Notebook 中重复运行绘图代码未关闭图形新的图形会叠加在旧的图形上。Matplotlib 默认会将图形绘制到当前“图形”和“坐标轴”上,如果未清除,新的绘图会叠加在旧的之上。在绘图代码开始前使用 plt.figure() 创建新图,或在绘图后使用 plt.close() 关闭并释放图形资源。

小结

  1. 等高线图用于可视化三元函数 Z = f(X, Y),图中同一条曲线上的点具有相同的 Z 值。
  2. 绘制等高线的两个核心函数是 plt.contourf(填充颜色区域)和 plt.contour(绘制边界线),通常配合使用。
  3. 数据准备是关键:必须先用 np.meshgrid 将一维的 X、Y 坐标数组转换为二维网格矩阵(X, Y),再计算对应的二维 Z 值矩阵。
  4. 主要参数包括:网格数据 X, Y, Z,第四个位置参数(层级数量),填充透明度 alpha,颜色映射 cmap 和边界线颜色 colors。
  5. 通过调整层级数量、cmap 等参数,可以控制图形的精细度和视觉风格,以适应不同的展示需求。

📋 行动清单

  • 将示例代码中的高度函数 x**2 + y**2 改为 x**2 - y**2,运行并观察等高线形状的变化(从圆形变成了双曲线)。
  • 尝试在 contourf 函数中把 cmap 从 plt.cm.hot 换成官方文档里的其他颜色映射,感受颜色对图形表达的影响。
  • 查阅 Matplotlib 官方文档中关于 contourf 的页面,看看第四个参数还可以怎样指定。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第5章代码包:等高线(含1 个 Notebook)
    ZIP · 793B
    下载