使用log_scale=True时Seaborn histplot与拟合对数正态PDF不匹配
对数正态分布拟合后直方图与PDF不匹配问题
问题复现步骤:
- 基于对数正态分布生成随机变量
- 用合成数据拟合对数正态分布
- 使用拟合参数计算概率密度函数(PDF)
- 绘制合成变量的直方图并叠加PDF
- 两者无法匹配
错误代码示例:
import seaborn as sns from scipy.stats import lognorm import numpy as np import matplotlib.pyplot as plt # 原代码缺少matplotlib导入 mu = 25 samples = lognorm.rvs(s=1, loc=0, scale=np.log(mu), size=10000) shape, loc, scale = lognorm.fit(samples) print(shape, loc, scale) fig, ax = plt.subplots() sns.histplot(samples, bins=50, stat="density", log_scale=True, ax=ax) xs = np.linspace(0.1, 100, 10000) ys = lognorm.pdf(xs, s=shape, loc=loc, scale=scale) ax.plot(xs, ys, "r-") plt.show()
问题原因及修正方案
样本生成的scale参数错误
scipy的lognorm分布定义为:若$X \sim \text{lognorm}(s, loc, scale)$,则$X = loc + scale \cdot \exp(Z)$(其中$Z \sim N(0,1)$)。如果期望$\ln(X)$的均值为$\mu$,那么scale应该是$\exp(\mu)$,而非$\log(\mu)$。原代码的参数完全搞反,导致生成的样本不符合预期的对数正态分布。对数刻度下的PDF适配问题
当直方图启用log_scale=True时,x轴为对数变换后的刻度,此时需对PDF做变量变换适配:对于$Y = \ln(X)$,概率密度满足$f_Y(y) = f_X(e^y) \cdot e^y$,直接绘制原始PDF会与对数刻度的直方图不匹配。
修正后的代码:
import seaborn as sns from scipy.stats import lognorm import numpy as np import matplotlib.pyplot as plt mu = 25 # 修正scale参数:使用exp(mu)而非log(mu) samples = lognorm.rvs(s=1, loc=0, scale=np.exp(mu), size=10000) shape, loc, scale = lognorm.fit(samples) print(f"拟合参数:shape={shape:.2f}, loc={loc:.2f}, scale={scale:.2f}") # 方案1:不使用对数刻度,直接匹配原始PDF fig, ax = plt.subplots() sns.histplot(samples, bins=50, stat="density", ax=ax) xs = np.linspace(samples.min(), samples.max(), 1000) ys = lognorm.pdf(xs, s=shape, loc=loc, scale=scale) ax.plot(xs, ys, "r-", label="拟合PDF") ax.legend() # 方案2:使用对数刻度,同时适配PDF fig, ax = plt.subplots() sns.histplot(samples, bins=50, stat="density", log_scale=True, ax=ax) xs = np.linspace(0.1, samples.max(), 1000) # 对数刻度下的PDF:变量变换后密度 = 原始PDF值 * x ys = lognorm.pdf(xs, s=shape, loc=loc, scale=scale) * xs ax.plot(xs, ys, "r-", label="对数刻度适配PDF") ax.legend() plt.show()
修正后直方图与PDF即可完美匹配。
内容的提问来源于stack exchange,提问作者Blademaster
相关产品推荐
相关产品推荐

