HOWTO · Matplotlib
如何在 Matplotlib 中用线连接散点图点
使用 `plot()` 按数据顺序连接 Matplotlib 散点图中的点,设置线条样式,并用 `zorder` 控制哪个图层显示在上方。
本页内容
要按数据顺序连接散点图中的点,请将相同的 x 和 y 值传递给 scatter() 和 plot(),然后调用 show() 显示图形。scatter() 将标记绘制为一个独立的集合,plot() 按提供的顺序绘制连接各点的路径,show() 则显示完成的图形。
本教程中的示例均已在 Python 3.12 上使用 Matplotlib 3.11.2 运行并验证,下面的每张图都是其正上方示例实际渲染的输出。
使用 scatter() 和 plot() 按数据顺序连接散点图点
为两个函数提供相同的坐标序列。plot() 按提供的顺序连接每一对点,因此顺序决定了路径;Matplotlib 不会按 x 坐标对点进行排序。请保持每个 x 值与其对应的 y 值配对:第一个 x 值对应第一个 y 值,第二个对应第二个,依此类推。如果按 x 对观测值排序,请将 y 值与这些相同的观测值一起重新排序,而不是独立排序两个列表。
当数据代表路线、时间序列或其他顺序具有意义的序列时,这一点很重要。例如,x 值从 1 前进到 3 然后再回到 2,产生的路径先向右移动,然后向左移动。对于轨迹来说,这可能是正确的。如果您的目标是从左到右推进的曲线,请先对配对的观测值进行排序。当相邻观测值共享一个 x 值时,线条也可能包含垂直段;plot() 仍会按提供的顺序连接它们。
此示例使用一组坐标叠加标记和连接线:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [2, 1, 3, 2]
plt.scatter(x, y)
plt.plot(x, y)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
使用相同的 x 和 y 输入可使标记和线条保持对齐。如果两个图层看起来错位,请检查是否有序列仅针对其中一次调用进行了变换或重新排序。对于存储在表格中的数据,请从相同的行中以相同的顺序选择两列。本示例使用 pyplot 接口,因此不需要单独的 figure 变量;使用面向对象接口时,先通过 fig, ax = plt.subplots() 创建 figure 和 axes,然后在该 axes 上调用 ax.scatter(...) 和 ax.plot(...)。
使用 plot() 设置线条和标记的样式
使用 linestyle 和 color 设置 plot() 绘制的路径的样式。下一个示例为标记保留一个单独的 scatter() 图层,并将连接路径绘制为蓝色虚线:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [2, 1, 3, 2]
plt.scatter(x, y, color="blue")
plt.plot(x, y, linestyle="--", color="blue")
plt.xlabel("x")
plt.ylabel("y")
plt.show()
分别调用 scatter() 和 plot() 可以独立控制点集合和连接路径:标记的大小和颜色可以更改而不触及线条,这在需要更突出点、同时让路径在视觉上保持简单时非常有用。为两个调用提供相同的坐标序列,使每个标记都位于其在线条中对应的点上。
单个 plot() 调用也可以通过 "xb-" 等格式字符串一次绘制两个图层,其中 x 选择标记形状,b 选择蓝色,- 选择实线。当一次调用应该绘制所有内容时,格式字符串很简洁;当您需要其他属性(如标记大小、线宽或透明度)时,color、marker 和 linestyle 等关键字参数更清晰。无论选择哪种方法,show() 都应位于所有样式和图层调用之后,因为它只在这些元素被添加后才显示图形。
使用 zorder 控制哪个图层显示在上方
zorder 较高的元素绘制在数值较低的元素之上。这仅改变绘制顺序;它不会改变坐标或路径。当粗线穿过标记并遮挡其中心,或线条需要在密集的标记中保持可见时,此设置很重要。
下一个示例故意使线条变粗,并为标记指定更高的 zorder,这样当线条从下方穿过时,每个圆形标记都保持完整:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [2, 1, 3, 2]
plt.plot(x, y, linewidth=6, zorder=2)
plt.scatter(x, y, s=120, zorder=3)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
要使标记位于线条之上,请为散点集合指定较大的值,例如上文中 scatter() 的 zorder=3 与 plot() 的 zorder=2。要将线条放在标记上方,请交换这两个值。使用适度的差值来表达预期的顺序,并且当叠放顺序需要明确无歧义时,在两个元素上都设置 zorder。同样的比较适用于您以后添加的任何其他绘图元素:zorder 最高的元素会绘制在其他元素之上。
使 x 和 y 的长度一致以避免大小不匹配错误
两个函数都按位置逐一配对值,因此两个序列的长度必须相同。否则,调用将引发 ValueError,并且不会绘制任何图形。此示例错误地漏掉了最后一个 y 值:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [2, 1, 3]
plt.scatter(x, y)
plt.plot(x, y)
plt.show()
运行它会在 scatter() 调用处失败,并显示:
ValueError: x and y must be the same size
单独使用相同的输入调用 plot() 也会失败,只是对同一问题的表述不同:ValueError: x and y must have same first dimension, but have shapes (4,) and (3,)。要修复此错误,请找到缺失或多余的观测值,并使两个序列重新描述相同的点。在绘图之前比较 len(x) 和 len(y) 可以指出哪一侧较短。当数据来自表格时,请将行筛选一次,然后从筛选后的行中获取两列,而不是分别筛选每一列并让它们的长度偏离。
两个空序列是另一种情况:它们会被接受,并生成一组空的坐标轴而不会出错。因此,图形为空通常意味着输入数据为空,而不是长度不匹配。