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

如何为已有直方图实现Weibull拟合?Scipy使用问题求助

解决Weibull拟合曲线与直方图不匹配的问题

看起来你遇到的核心问题是直方图的频数尺度和Weibull概率密度函数(PDF)的概率尺度不匹配,再加上拟合参数的小细节可以优化,下面一步步帮你解决:

1. 匹配直方图与PDF的尺度

直方图展示的是每个区间的样本频数(即该区间内有多少个数据点),而stats.weibull_min.pdf()返回的是概率密度值(所有区间的密度积分总和为1)。要让两者在图上匹配,必须把PDF的值乘以两个关键系数:

  • 样本总数(len(X)):把概率转换为频数基数
  • 直方图的组距(这里你设置的是25,因为bins=np.arange(0,1500,25)):把密度值拉伸到对应区间的宽度

2. 优化拟合参数

你的数据是x>0的时间间隔,Weibull分布的位置参数loc理论上应该为0(时间间隔不可能为负),所以在fit()时指定floc=0,可以强制固定位置参数,避免拟合出不合理的loc值,让形状参数shape和尺度参数scale的估计更准确。

完整修改后的代码

把所有调整整合到你的原代码中:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

# 读取数据
hist = pd.read_excel('Histogram/Histogram.xlsx')
X = hist['DeltaT_-250_2017']
X = X[(X > 0)]

# 绘制直方图,同时获取频数和区间信息
bin_width = 25
bins = np.arange(0, 1500, bin_width)
plt.figure(figsize=(15,4))
n, bins, patches = plt.hist(X, bins=bins, color='#0504aa', edgecolor='red', rwidth=0.8)
plt.ylabel('Number of EL')
plt.xlabel('Delta T (years CE) between EL')
plt.xlim(0, 401)
plt.xticks(np.arange(0, 401, 25))
plt.yticks(np.arange(0, max(n)+1, 1))  # 自动匹配y轴的频数范围

# Weibull 拟合与适配尺度的曲线绘制
shape, loc, scale = stats.weibull_min.fit(X, floc=0)
x = np.linspace(0, 401, 100)  # 和直方图的x轴范围保持一致
# 计算匹配频数尺度后的PDF值
pdf_values = stats.weibull_min.pdf(x, shape, loc=loc, scale=scale) * len(X) * bin_width
plt.plot(x, pdf_values, 'r-', lw=2, alpha=0.8, label=f'Weibull Fit\nshape={shape:.2f}, scale={scale:.2f}')
plt.legend()

plt.show()

为什么原来的曲线不对?

你之前直接绘制的是原始概率密度值,其数值范围远小于直方图的频数(比如如果你的样本数是20,组距25,那么PDF需要乘以20*25才能和直方图的高度匹配),所以看起来会是一条和直方图完全不搭的扁平线条或者错位图形。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:25:14