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

如何制作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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:07:46