绘制分布曲线时出现多条线的原因及正态、对数正态分布拟合疑问
为什么绘制分布曲线时会出现多条线?
嘿,我来帮你捋捋这个问题~你现在看到的“多条线”其实是个视觉错觉,核心原因出在数据的顺序和绘图逻辑上:
你直接用原始数据里的Q值去计算对应概率密度(PDF),然后如果直接把Q和PDF值连线的话,因为你的Q数据是按年份排列的,并不是从小到大排序的(比如1894年的Q是16757,是目前数据里最大的,但下一个数据如果回到小值,线条就会从高跳到低),这样连线时就会在高低值之间来回跳转,看起来像是多条线,但本质是一条线被画乱了而已。
解决步骤&修正代码
1. 核心思路
不要用原始无序的Q值当横坐标,而是生成一组从Q的最小值到最大值的连续、排序后的数值,用这些有序的点去计算PDF值,画出来就是光滑的单条分布曲线了。
2. 完整修正代码
下面是包含正态分布、对数正态分布拟合和正确绘图的代码:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy import stats # 加载你的数据(这里用你提供的预览数据示例) data = { 'year': [1885,1886,1887,1888,1889,1890,1891,1892,1893,1894], 'Q': [7241,9164,7407,6870,9855,11887,8827,7546,8498,16757] } df = pd.DataFrame(data) # 计算正态分布参数 mean = df['Q'].mean() std = df['Q'].std() print(f"正态分布均值: {mean:.2f}, 标准差: {std:.2f}") # 生成排序后的横坐标(取1000个点保证曲线光滑) x = np.linspace(df['Q'].min(), df['Q'].max(), 1000) # 计算正态分布PDF pdf_normal = stats.norm.pdf(x, loc=mean, scale=std) # 拟合对数正态分布(scipy的lognorm参数需要注意:s是对数的标准差,scale是exp(对数均值)) log_q = np.log(df['Q']) log_mean = log_q.mean() log_std = log_q.std() pdf_lognorm = stats.lognorm.pdf(x, s=log_std, scale=np.exp(log_mean)) # 绘图展示 plt.figure(figsize=(10,6)) # 先画原始数据的直方图,直观对比分布 plt.hist(df['Q'], bins=8, density=True, alpha=0.3, label='原始数据直方图') # 绘制正态分布曲线 plt.plot(x, pdf_normal, label='正态分布拟合曲线', color='#1f77b4', linewidth=2) # 绘制对数正态分布曲线 plt.plot(x, pdf_lognorm, label='对数正态分布拟合曲线', color='#ff7f0e', linewidth=2) plt.xlabel('Q值') plt.ylabel('概率密度') plt.title('Q值的分布拟合对比') plt.legend() plt.show()
额外提醒
- 如果你之前用的是
plt.plot(df['Q'], distnormal)这种写法,因为df['Q']是无序的,线条必然会乱跳;换成排序后的x就能解决这个问题。 - 对数正态分布的拟合要注意
scipy.stats.lognorm的参数逻辑:它的scale参数对应对数正态分布的位置参数,需要用exp(对数均值),s参数是对数数据的标准差,这样拟合出来的曲线才是正确的。
内容的提问来源于stack exchange,提问作者maximusdooku
相关产品推荐
相关产品推荐

