You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Matplotlib绘制填充颜色依赖于第三变量z的X-Y曲线

解决Matplotlib fill_between填充色依赖第三变量的问题

我明白你想实现的效果——让曲线下方的填充色跟着第三变量z动态变化,直接用color=cm(z)确实行不通,因为fill_between的color参数不支持传入颜色数组来逐段映射颜色。下面给你两种可行的解决办法:

方法1:分段填充(简单直观)

思路是把x轴分成一个个小的区间,对每个区间单独调用fill_between,并用对应位置的z值来获取颜色。这种方法容易理解,适合快速实现:

import numpy as np
import matplotlib.pyplot as plt

cm = plt.get_cmap('gist_rainbow')
x = np.linspace(0, 10, 100)
y = np.sin(x) + 1.3
z = 0.5*(np.cos(x) + 1.0)  # z范围0到1,刚好适配colormap

fig, ax = plt.subplots(figsize=(8,4))
ax.set(xlim=(0.0, 10.0), ylim=(0.0, 3.0))

# 绘制主曲线
ax.plot(x, y, lw=2, color='black')

# 遍历每个x区间,分段填充
for i in range(len(x)-1):
    # 取当前区间的x和y值
    x_segment = x[i:i+2]
    y_segment = y[i:i+2]
    # 用区间中点的z值获取颜色
    z_val = (z[i] + z[i+1])/2
    ax.fill_between(x_segment, y_segment, 0, color=cm(z_val))

plt.show()

这段代码会把每个小线段下方的区域用对应z值的颜色填充,虽然是分段的,但如果x的采样点足够多(比如你用的100个点),视觉上已经比较连贯了。

方法2:使用pcolormesh实现平滑渐变(更美观)

如果想要更平滑的颜色过渡,可以用pcolormesh结合路径裁剪,让颜色只显示在曲线下方的区域:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch

cm = plt.get_cmap('gist_rainbow')
x = np.linspace(0, 10, 100)
y = np.sin(x) + 1.3
z = 0.5*(np.cos(x) + 1.0)

fig, ax = plt.subplots(figsize=(8,4))
ax.set(xlim=(0.0, 10.0), ylim=(0.0, 3.0))

# 绘制主曲线
ax.plot(x, y, lw=2, color='black')

# 创建网格用于pcolormesh
X, Y = np.meshgrid(x, np.linspace(0, ax.get_ylim()[1], 100))
# 将z扩展为和网格匹配的二维数组
Z = np.tile(z, (Y.shape[0], 1))

# 绘制pcolormesh
pcm = ax.pcolormesh(X, Y, Z, cmap=cm, shading='gouraud')

# 创建裁剪路径:只保留曲线下方的区域
path = Path(np.column_stack([np.concatenate([x, x[::-1]]), 
                             np.concatenate([y, np.zeros_like(y)])]))
patch = PathPatch(path, facecolor='none')
ax.add_patch(patch)
pcm.set_clip_path(patch)

plt.colorbar(pcm, label='z value')
plt.show()

这种方法利用pcolormesh生成平滑的颜色渐变,再通过路径裁剪只显示曲线下方的部分,视觉效果更流畅,还能添加颜色条来展示z值和颜色的对应关系。

为什么你的原代码不行?

原代码中ax.fill_between(x, y, interpolate=True, color=cm(z))的问题在于:fill_between的color参数只能接受单个颜色值或者一个循环的颜色列表(用于多个填充区域),但无法直接传入一个和x长度匹配的颜色数组来实现逐段颜色变化。cm(z)返回的是一个形状为(100,4)的RGBA数组,fill_between无法解析这个数组作为颜色输入,所以只会用默认的颜色或者取数组的第一个元素来填充。

内容的提问来源于stack exchange,提问作者Morten Grum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 07:47:39