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

如何在双张子图中为KDE曲线下区域着色?解决索引错误

在双张子图中为KDE曲线特定区间添加着色

问题解决代码

方法1:基于Seaborn绘图对象获取KDE数据

这种方法保留Seaborn的默认绘图风格,先绘制KDE曲线,再提取线条数据进行区间填充:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

fig, axs = plt.subplots(1, 2, figsize=(11, 4.5))
N = 500
X = np.concatenate((np.random.normal(0, 1, int(0.3 * N)),
                    np.random.normal(5, 1, int(0.7 * N))))

# 先绘制无填充的KDE曲线,确保线条被正确添加到轴对象
sns.kdeplot(data=X, linewidth=2, ax=axs[0])

# 获取KDE曲线的坐标数据
kde_line = axs[0].get_lines()[-1]
kde_x, kde_y = kde_line.get_data()

# 定义需要着色的x区间
mask = (kde_x > 1.8) & (kde_x < 3.2)
# 填充目标区间,可自定义颜色和透明度
axs[0].fill_between(kde_x[mask], kde_y[mask], color="#1f77b4", alpha=0.3)

# 绘制ECDF子图
sns.ecdfplot(X, stat='proportion', ax=axs[1])

plt.show()

方法2:手动计算KDE(更可靠,不依赖绘图对象内部结构)

通过scipy.stats.gaussian_kde直接计算核密度估计,完全控制绘图流程:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import gaussian_kde

fig, axs = plt.subplots(1, 2, figsize=(11, 4.5))
N = 500
X = np.concatenate((np.random.normal(0, 1, int(0.3 * N)),
                    np.random.normal(5, 1, int(0.7 * N))))

# 手动计算KDE
kde = gaussian_kde(X)
# 生成覆盖数据范围的x轴采样点
kde_x = np.linspace(X.min() - 1, X.max() + 1, 1000)
kde_y = kde(kde_x)

# 绘制KDE曲线
axs[0].plot(kde_x, kde_y, linewidth=2, color="#1f77b4")
# 填充目标区间
mask = (kde_x > 1.8) & (kde_x < 3.2)
axs[0].fill_between(kde_x[mask], kde_y[mask], color="#1f77b4", alpha=0.3)

# 绘制ECDF子图
sns.ecdfplot(X, stat='proportion', ax=axs[1])

plt.show()

错误原因解释

你参考的单图代码中调用了两次sns.kdeplot,第二次调用会在轴上新增一条KDE曲线,因此ax.get_lines()[-1]能获取到有效线条对象。但你的代码只调用了一次kdeplot且设置了fill=True:

  • 在部分Seaborn版本中,fill=True会优先创建填充多边形(PolyCollection),而KDE线条可能未被加入get_lines()列表,导致列表为空,触发IndexError。
  • 即使线条存在,直接使用fill=True会填充整个曲线下区域,和你需要的「特定区间着色」需求不符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:45:29