您可以使用
矩法来拟合任何特定的分布。
基本思路:先得到经验一、二等矩,然后从这些矩中推导出分布参数。
因此,在所有这些情况下,我们只需要两个矩。让我们来获取它们:
import pandas as pd
from scipy.stats import nbinom, poisson, geom
x = pd.Series(x)
mean = x.mean()
var = x.var()
likelihoods = {}
注意:我使用了pandas而不是numpy。这是因为numpy的
var()
和
std()
没有应用
贝塞尔矫正,而pandas的应用了。如果你有100个以上的样本,可能不会有太大差异,但在较小的样本中可能很重要。
现在,让我们获取这些分布的参数。
负二项式分布有两个参数:p、r。让我们估计它们并计算数据集的似然性:
# From the wikipedia page, we have:
# mean = pr / (1-p)
# var = pr / (1-p)**2
# without wiki, you could use MGF to get moments; too long to explain here
# Solving for p and r, we get:
p = 1 - mean / var # TODO: check for zero variance and limit p by [0, 1]
r = (1-p) * mean / p
更新: 维基百科和scipy使用不同的p定义,一个将其视为成功概率,另一个将其视为失败概率。因此,为了与scipy的概念保持一致,请使用:
p = mean / var
r = p * mean / (1-p)
更新结束
更新2:
我建议使用@thilak的代码来计算对数似然,它可以避免在大样本中丢失精度,这尤其重要。
更新2结束
计算似然:
likelihoods['nbinom'] = x.map(lambda val: nbinom.pmf(val, r, p)).prod()
对于泊松分布也是一样,只有一个参数:
lambda_ = mean
likelihoods['poisson'] = x.map(lambda val: poisson.pmf(val, lambda_)).prod()
同样适用于几何分布:
p = 1 / mean
likelihoods['geometric'] = x.map(lambda val: geom.pmf(val, p)).prod()
最后,让我们得到最佳匹配:
best_fit = max(likelihoods, key=lambda x: likelihoods[x])
print("Best fit:", best_fit)
print("Likelihood:", likelihoods[best_fit])
如果您有任何问题,请告知我