如何在同一坐标轴绘制分布函数与正确的分布密度曲线?
修正分布密度曲线绘制错误的方法
问题背景
我有字典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
相关产品推荐
相关产品推荐

