如何制作Y轴为观测计数的平滑堆叠面积图?
堆叠平滑面积图(Y轴为观测计数)
需求背景
需要制作堆叠面积图,满足两个核心要求:
- Y轴显示实际观测计数,而非0-1的比例值
- 图形为平滑的分布曲线样式,保留堆叠的重叠分布效果
示例数据
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from scipy.stats import gaussian_kde np.random.seed(365) # 保证结果可复现 start_date = pd.date_range(start="2015-09-13", periods=200, freq="13D") duration = np.random.exponential(scale=5, size=len(start_date)).round(1) boolean = np.random.randint(2, size=len(start_date)) boolean = [bool(x) for x in boolean] df = pd.DataFrame({"duration": duration, "terminated": boolean})
现有方法的局限
- 用
groupby+plot能得到计数Y轴,但图形是尖刺状的堆叠柱状图,缺乏平滑感:df.groupby(by=["terminated", "duration"]).size().unstack(level=0)\ .plot(use_index=True, kind="area", stacked=True) - 用
sns.kdeplot能生成平滑堆叠曲线,但Y轴是比例密度,不是实际计数:sns.kdeplot(data=df, x="duration", hue="terminated", multiple="stack")
解决方案:手动转换KDE密度为计数,绘制平滑堆叠面积图
核心逻辑:先计算每组的KDE密度曲线,再将密度值乘以对应组的样本数量,把比例刻度转换成实际计数,最后用matplotlib绘制堆叠填充的平滑曲线。
完整代码:
# 拆分两组数据 df_false = df[df["terminated"] == False]["duration"] df_true = df[df["terminated"] == True]["duration"] # 生成连续X轴取值范围(保证曲线平滑) x_values = np.linspace(df["duration"].min(), df["duration"].max(), 200) # 计算两组的KDE密度 kde_false = gaussian_kde(df_false) kde_true = gaussian_kde(df_true) # 将密度转换为计数:密度值 × 组内样本数 y_false = kde_false(x_values) * len(df_false) y_true = kde_true(x_values) * len(df_true) # 绘制堆叠面积图 plt.figure(figsize=(10, 6)) # 绘制上层组(terminated=True) plt.fill_between(x_values, y_false + y_true, y_false, color="#ff7f0e", alpha=0.6, label="terminated=True") # 绘制下层组(terminated=False) plt.fill_between(x_values, y_false, color="#1f77b4", alpha=0.6, label="terminated=False") # 添加平滑曲线轮廓 plt.plot(x_values, y_false, color="#1f77b4", linewidth=1) plt.plot(x_values, y_false + y_true, color="#ff7f0e", linewidth=1) # 设置图表标签与标题 plt.xlabel("Duration") plt.ylabel("Observation Count") plt.title("Stacked Smooth Area Plot (Count Y-axis)") plt.legend() plt.show()
关键说明
- 使用
scipy.stats.gaussian_kde计算核密度估计,确保曲线的平滑度 - 密度值乘以组内样本数,直接将比例刻度转换为实际观测计数,精准匹配需求
- 通过
fill_between实现堆叠填充,叠加两组Y值得到堆叠后的总高度,同时保留平滑曲线的视觉效果
内容的提问来源于stack exchange,提问作者JoMcGee
相关产品推荐
相关产品推荐

