我有一系列粒度分布数据按体积分数百分比排列,如下所示:
size %
6.68 0.05
9.92 1.15
etc.
我需要将这些数据拟合到对数正态分布,我计划使用python的stats.lognorm.fit
函数进行,但这似乎期望输入为变量数组而不是分箱数据,判断我所做的read。
我计划使用for循环遍历数据并.extend
每个大小条目到占位符数组所需的次数,以创建一个数组,其中包含与分箱数据相对应的变量列表。
这看起来非常丑陋和低效,而且那种事情可能是一种简单的方法。有没有办法将分箱数据输入stats.lognorm.fit
函数?
答案 0 :(得分:0)
我猜一种可能的解决方法是手动将pdf拟合到bin数据,假设x值是每个间隔的中点,y值是相应的bin频率。然后使用scipy.optimize.curve_fit
根据x和y值拟合曲线。我认为结果的准确性将取决于您拥有的垃圾箱数量。示例如下所示:
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
def pdf(x, mu, sigma):
"""pdf of lognormal distribution"""
return (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2)) / (x * sigma * np.sqrt(2 * np.pi)))
mu, sigma = 3., 1. # actual parameter value
data = np.random.lognormal(mu, sigma, size=1000) # data generation
h = plt.hist(data, bins=30, normed = True)
y = h[0] # frequencies for each bin, this is y value to fit
xs = h[1] # boundaries for each bin
delta = xs[1] - xs[0] # width of bins
x = xs[:-1] + delta / # midpoints of bins, this is x value to fit
popt, pcov = curve_fit(pdf, x, y, p0=[1, 1]) # data fitting, popt contains the fitted parameters
print(popt)
# [ 3.13048122 1.01360758] fitting results
fig, ax = plt.subplots()
ax.hist(data, bins=30, normed=True, align='mid', label='Histogram')
xr = np.linspace(min(xs), max(xs), 10000)
yr = pdf(xr, mu, sigma)
yf = pdf(xr, *popt)
ax.plot(xr, yr, label="Actual")
ax.plot(xr, yf, linestyle = 'dashed', label="Fitted")
ax.legend()