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

如何在同一坐标轴绘制分布函数与正确的分布密度曲线?

修正分布密度曲线绘制错误的方法

问题背景

我有字典data_for_chart,键为x轴取值(单位mkm),值为y轴累积百分比,需要复刻包含**累积分布函数(左侧)和概率密度函数(右侧)**的对数x轴图表。当前代码的分布函数显示正确,但密度曲线完全不符合预期。

当前代码:

x_values = list(data_for_chart[index_data]['values'].keys())
y_values = list(data_for_chart[index_data]['values'].values())
fig = Figure()
ax = fig.subplots()
ax.plot(x_values, y_values, ':o', linewidth=2)
df = pd.DataFrame(y_values, index=x_values)
df.plot(kind='density', ax=ax, bw_method=3, secondary_y=True, label='Density function dQ3 ()d, %')
ax.set_xscale('log')
ax.grid(axis='x')
ax.legend()
ax.set_ylabel('%')
ax.set_xlabel('mkm')
buf = BytesIO()
fig.savefig(buf, format="png")

问题根源

你误用了pandas的密度图功能:

  • pandas的plot(kind='density')是对原始样本数据做核密度估计,而你传入的y_values是累积百分比(CDF值),不是原始样本;
  • 索引的x轴取值也没被当作样本的权重或真实取值,导致密度计算完全偏离需求。

解决方法

方法1:从累积分布函数(CDF)推导概率密度函数(PDF)

因为已有CDF数据,直接通过数值微分计算PDF(适配对数x轴):

import numpy as np
from matplotlib.figure import Figure
from io import BytesIO

# 转换为numpy数组方便计算
x_values = np.array(list(data_for_chart[index_data]['values'].keys()), dtype=float)
y_values = np.array(list(data_for_chart[index_data]['values'].values()), dtype=float)

fig = Figure()
ax = fig.subplots()

# 绘制正确的累积分布函数
ax.plot(x_values, y_values, ':o', linewidth=2, label='累积分布函数')
ax.set_xscale('log')
ax.grid(axis='x')
ax.set_ylabel('累积百分比(%)')
ax.set_xlabel('mkm')
ax.legend(loc='upper left')

# 计算PDF:对数刻度下的数值微分
log_x = np.log(x_values)
# 计算dy/d(logx),再转换为dy/dx = (dy/dlogx)/x(链式法则)
dy_dlogx = np.diff(y_values) / np.diff(log_x)
pdf = dy_dlogx / x_values[1:]
# 取x的几何中点作为PDF的对应x值(更准确)
x_pdf = np.sqrt(x_values[:-1] * x_values[1:])

# 在右侧y轴绘制密度曲线
ax2 = ax.twinx()
ax2.plot(x_pdf, pdf, 'r-', linewidth=2, label='概率密度函数')
ax2.set_ylabel('密度')
ax2.legend(loc='upper right')

buf = BytesIO()
fig.savefig(buf, format="png")

方法2:使用原始样本数据绘制(推荐)

如果能获取生成该CDF的原始颗粒度样本数据,直接用原始数据做核密度估计:

# 假设raw_data是原始样本数据的列表/数组
ax2 = ax.twinx()
# 用原始样本绘制密度图,自动适配对数x轴
pd.Series(raw_data).plot(kind='density', ax=ax2, bw_method=0.5, label='概率密度函数')
ax2.set_xscale('log')
ax2.set_ylabel('密度')
ax2.legend(loc='upper right')

注意事项

  • 对数刻度下的密度计算必须用链式法则转换,不能直接用线性空间的差分;
  • bw_method参数控制密度曲线的平滑程度,需根据数据调整(不要盲目设为3);
  • 两种方法都要保证左右轴的x范围一致,避免曲线错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:29:51