fill_between本身不支持渐变色,color参数仅接受单一颜色;真正实现需用PolyCollection配合facecolors数组,按分段索引映射colormap生成RGBA色值并手动构造闭合多边形。

fill_between 怎么用 color 参数实现基础渐变色?
直接传 color 参数只能设单一颜色,fill_between 本身不支持渐变填充。所谓“渐变色填充”其实是伪渐变:靠密集绘制多条微小宽度的填充带,每条带用不同颜色模拟过渡效果。
核心思路是把原始曲线拆成 N 段,对每一段调用一次 fill_between,颜色由 colormap 映射当前段索引或 y 值决定。
- 不要试图给
fill_between的color传LinearSegmentedColormap对象——它会静默忽略,只当透明色处理 - 真正起作用的是
facecolors参数,但它要求输入与填充段数严格对应的 RGBA 数组 - 推荐先用
np.linspace生成 x 分段点,再用plt.cm.viridis()等函数逐段取色
怎样用 facecolors + PolyCollection 手动构造渐变填充?
这是最可控的方式,绕过 fill_between 的限制,直接操作底层多边形集合。关键在于把上下边界转为一系列闭合路径(polygon),再批量设置每个路径的 facecolor。
示例逻辑:
立即学习“Python免费学习笔记(深入)”;
import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import PolyCollection <p>x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.sin(x) * 0.5</p><h1>拆成 50 段</h1><p>n_segments = 50 x_seg = np.array_split(x, n_segments) y1_seg = np.array_split(y1, n_segments) y2_seg = np.array_split(y2, n_segments)</p><p>verts = [] for i in range(n_segments): xs = np.concatenate([x_seg[i], x_seg[i][::-1]]) ys = np.concatenate([y1_seg[i], y2_seg[i][::-1]]) verts.append(list(zip(xs, ys)))</p><h1>生成颜色数组:按段序号映射 viridis</h1><p>cmap = plt.cm.viridis norm = plt.Normalize(vmin=0, vmax=n_segments-1) facecolors = cmap(norm(np.arange(n_segments)))</p><p>poly = PolyCollection(verts, facecolors=facecolors, edgecolors='none') plt.gca().add_collection(poly) plt.xlim(x.min(), x.max()) plt.ylim(min(y2.min(), y1.min()), max(y2.max(), y1.max()))
-
PolyCollection不自动调整坐标轴范围,必须手动调plt.xlim/plt.ylim - 每段顶点必须是闭合环(首尾点一致或显式首尾相连),否则填充区域错乱
- 如果 y1/y2 长度不等,
np.array_split会报错,务必提前对齐
为什么用 fill\_betweenx 而不是 fill\_between?
当你的数据是「水平区间」而非「垂直区间」时(比如时间序列中某指标在固定值上下浮动),fill_betweenx 更自然。它的渐变逻辑和 fill_between 完全对称,只是 x/y 角色互换。
- 错误写法:
fill_betweenx(y, x1, x2, facecolors=...)中若x1和x2是标量,会触发广播异常 - 正确做法:确保
x1、x2与y等长,且分段后每段仍保持单调——否则多边形自交,颜色覆盖顺序不可控 - 常见场景:Gantt 图、置信带横置显示、热力图边缘填充
colormap 选哪个?viridis 和 plasma 在填充中表现差异大吗?
差异非常大,不只是“好不好看”,更影响信息可读性。viridis 是为色盲友好设计的线性亮度递增 colormap,plasma 则是高对比度但亮度非线性的方案。
- 如果填充区域代表数值大小(如误差带、概率密度),优先用
viridis或inferno,避免中间段颜色过暗导致细节丢失 - 如果只是装饰性渐变(如背景强调),
plasma或coolwarm更醒目,但注意两端色差过大可能让小范围变化看起来被压缩 - 绝对不要用
jet:其绿色峰值会造成虚假“凸起”感知,已被 Matplotlib 默认弃用
实际填充中,人眼对亮度变化比色相变化敏感得多,所以 colormap 的 luminance profile 比 hue 排列更重要。


















