2017-11-22 11 views
0

私はデータ点数が多いので、データに正規分布を当てはめたいと思います。 scipyにはstats.norm.fitメソッドがありますが、これにはデータポイントのリストが1つ必要です。何かのように私のデータが2つのリストに含まれているのに対し、加重リストに正規分布を適合させる

data = [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5] 

のようなものです。

values = [1, 2, 3, 4, 5] 
counts = [4, 3, 6, 1, 3] 

このようにフォーマットされたデータに正規分布を適合させるにはどうすればよいですか?

答えて

1

(推定された)正常集団からのサンプルを特徴づける最も直接的な方法は、平均および標準偏差をとることです。 Martelli's lambda to flatten the sampleと一緒に組み込みライブラリを使用してこれを行うことができます。

>>> values = [1, 2, 3, 4, 5] 
>>> counts = [4, 3, 6, 1, 3] 
>>> import statistics 
>>> sample = [c*[v] for (c, v) in zip(counts, values)] 
>>> sample 
[[1, 1, 1, 1], [2, 2, 2], [3, 3, 3, 3, 3, 3], [4], [5, 5, 5]] 
>>> flatten = lambda l: [item for sublist in l for item in sublist] 
>>> sample = flatten(sample) 
>>> sample 
[1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5] 
>>> statistics.mean(sample) 
2.764705882352941 
>>> statistics.stdev(sample) 
1.3932610920384718 
+1

@DanielStandageあなたは、その確率密度関数を持つ正規分布を再作成することができます(HTTPS:/ /en.wikipedia.org/wiki/Normal_distribution)。 – KDecker

+0

@KDecker:まったく!平均と標準偏差を知っていれば*すべて*です。 –

3

あなたはnumpy.repeatでフルセットに値を展開し、scipy.stats.norm.fitを使用することができます。

In [54]: import numpy as np 

In [55]: from scipy.stats import norm 

In [56]: values = [1, 2, 3, 4, 5] 

In [57]: counts = [4, 3, 6, 1, 3] 

In [58]: full_values = np.repeat(values, counts) 

In [59]: full_values 
Out[59]: array([1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5]) 

In [60]: norm.fit(full_values) # Estimate mean and std. dev. 
Out[60]: (2.7647058823529411, 1.3516617991854185) 

scipy.stats.norm.fitはパラメータの最尤推定値を計算します。正規分布の場合、これらは単にサンプル平均と(偏った)サンプル分散の平方根です。 私が知る限り、numpyまたはscipyにおける唯一の関連する加重統計関数はnumpy.averageです。 weights引数としてcountsを使用して、numpy.averageで計算を自分で行うことができます。

In [62]: sample_mean = np.average(values, weights=counts) 

In [63]: sample_mean 
Out[63]: 2.7647058823529411 

In [64]: sample_var = np.average((values - sample_mean)**2, weights=counts) 

In [65]: sample_var 
Out[65]: 1.8269896193771626 

In [66]: sample_std = np.sqrt(sample_var) 

In [67]: sample_std 
Out[67]: 1.3516617991854185 

statistics.stdev公平標本分散に基づいていることに留意されたいです。それはあなたが望むなら、あなたはsum(counts)/(sum(counts) - 1)によってバイアスされ標本分散を乗じてスケーリングを調整することができます:平均値と標準偏差で

In [79]: n = sum(counts) 

In [80]: sample_var = n/(n-1)*np.average((values - sample_mean)**2, weights=counts) 

In [81]: sample_var 
Out[81]: 1.9411764705882353 

In [82]: sample_std = np.sqrt(sample_var) 

In [83]: sample_std 
Out[83]: 1.3932610920384718 
関連する問題