如何在百分比直方图(非原始数据)上绘制拟合曲线
绘制贴合分箱百分比的拟合曲线
你遇到的问题核心是:seaborn的kde=True是对原始数据集做核密度估计(KDE),而非针对分箱后的百分比数据,所以会出现不符合分箱趋势的额外凸起。要实现贴合分箱百分比的拟合曲线,需要先提取直方图的分箱统计数据,再针对这些数据做拟合。
步骤1:绘制百分比直方图并提取分箱信息
先复用你原有的直方图代码,同时获取直方图返回的分箱边界、每个分箱的百分比等关键数据:
import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter # 替换为你的实际数据集 np.random.seed(42) data = np.random.normal(loc=50, scale=15, size=1000) # 绘制百分比直方图,同时捕获分箱统计结果 bin_percentages, bin_edges, _ = plt.hist( data, weights=np.ones(len(data)) / len(data), bins=5 ) plt.gca().yaxis.set_major_formatter(PercentFormatter(1)) plt.grid() # 计算每个分箱的中点(用于拟合的x值) bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
步骤2:拟合贴合分箱的曲线
根据需求可以选择两种拟合方式:
方式1:多项式拟合(严格贴合分箱趋势)
适合需要曲线完全匹配分箱百分比变化趋势的场景,这里以二次多项式为例(可根据数据调整阶数):
from scipy.optimize import curve_fit # 定义拟合函数(示例为二次多项式,可修改为更高阶或其他形式) def polynomial_fit(x, a, b, c): return a * x**2 + b * x + c # 拟合分箱中点与对应百分比 fit_params, _ = curve_fit(polynomial_fit, bin_centers, bin_percentages) # 生成平滑的拟合曲线x轴数据 x_fit = np.linspace(bin_edges[0], bin_edges[-1], 100) # 计算拟合曲线的y值(百分比) y_fit = polynomial_fit(x_fit, *fit_params) # 绘制拟合曲线 plt.plot(x_fit, y_fit, 'r-', linewidth=2, label='多项式拟合曲线') plt.legend() plt.show()
方式2:加权核密度估计(平滑贴合分箱分布)
如果想要更平滑的曲线,同时保留分箱的分布特征,可以基于分箱中点和百分比做加权KDE:
from scipy.stats import gaussian_kde # 创建加权KDE,权重为每个分箱的百分比 kde = gaussian_kde(bin_centers, weights=bin_percentages) # 生成拟合曲线的x轴数据 x_fit = np.linspace(bin_edges[0], bin_edges[-1], 100) # 计算拟合曲线的y值(已归一化到百分比范围) y_fit = kde(x_fit) # 绘制拟合曲线 plt.plot(x_fit, y_fit, 'g-', linewidth=2, label='加权KDE拟合曲线') plt.legend() plt.show()
关键说明
- 两种方法都是基于分箱后的百分比数据做拟合,不会出现原始数据KDE的额外凸起
- 多项式拟合的阶数可根据分箱的分布趋势调整(比如线性、三次多项式)
- 加权KDE的平滑程度可通过
gaussian_kde的bw_method参数调整(比如bw_method=0.5缩小带宽,曲线更贴合分箱)
内容的提问来源于stack exchange,提问作者navid
相关产品推荐
相关产品推荐

