web-dev-qa-db-ja.com

Pythonで累積分布関数(CDF)を計算する

python 累積分布関数(CDF) で計算するにはどうすればよいですか?

たとえば、scipyが持っている連続分布ではなく、私が持っている点の配列(離散分布)から計算したい。

13
wizbcn

(質問の解釈が間違っている可能性があります。質問が離散PDFから離散CDFに到達する方法である場合、np.cumsumサンプルが等間隔の場合、適切な定数で除算されます。配列が等間隔でない場合、np.cumsumは、ポイント間の距離を掛けた配列になります。

サンプルの離散配列があり、サンプルのCDFを知りたい場合は、配列を並べ替えるだけです。ソートされた結果を見ると、最小値は0%を表し、最大値は100%を表していることがわかります。分布の50%の値を知りたい場合は、ソートされた配列の中央にある配列要素を見てください。

簡単な例でこれを詳しく見てみましょう。

import matplotlib.pyplot as plt
import numpy as np

# create some randomly ddistributed data:
data = np.random.randn(10000)

# sort the data:
data_sorted = np.sort(data)

# calculate the proportional values of samples
p = 1. * np.arange(len(data)) / (len(data) - 1)

# plot the sorted data:
fig = figure()
ax1 = fig.add_subplot(121)
ax1.plot(p, data_sorted)
ax1.set_xlabel('$p$')
ax1.set_ylabel('$x$')

ax2 = fig.add_subplot(122)
ax2.plot(data_sorted, p)
ax2.set_xlabel('$x$')
ax2.set_ylabel('$p$')

これにより、右側のプロットが従来の累積分布関数である次のプロットが得られます。ポイントの背後にあるプロセスのCDFを反映する必要がありますが、当然、ポイントの数が有限である限りそうではありません。

cumulative distribution function

この関数は簡単に反転でき、必要なフォームはアプリケーションによって異なります。

25
DrV

データの分布方法を知っている(つまり、データのpdfを知っている)と仮定すると、 scipy はcdfの計算時に離散データをサポートします

_import numpy as np
import scipy
import matplotlib.pyplot as plt
import seaborn as sns

x = np.random.randn(10000) # generate samples from normal distribution (discrete data)
norm_cdf = scipy.stats.norm.cdf(x) # calculate the cdf - also discrete

# plot the cdf
sns.lineplot(x=x, y=norm_cdf)
plt.show()
_

enter image description here

Cdfの最初のいくつかの値を印刷して、それらが離散的であることを示すこともできます。

_print(norm_cdf[:10])
>>> array([0.39216484, 0.09554546, 0.71268696, 0.5007396 , 0.76484329,
       0.37920836, 0.86010018, 0.9191937 , 0.46374527, 0.4576634 ])
_

Cdfを計算する同じ方法は、複数のディメンションでも機能します。以下の2dデータを使用して説明します

_mu = np.zeros(2) # mean vector
cov = np.array([[1,0.6],[0.6,1]]) # covariance matrix
# generate 2d normally distributed samples using 0 mean and the covariance matrix above
x = np.random.multivariate_normal(mean=mu, cov=cov, size=1000) # 1000 samples
norm_cdf = scipy.stats.norm.cdf(x)
print(norm_cdf.shape)
>>> (1000, 2)
_

上記の例では、データが正常に配信されることを事前に知っていたため、scipy.stats.norm()を使用しました-scipyがサポートする複数の配信があります。ただし、このような機能を使用するには、事前にデータがどのように配布されているかを事前に知る必要があります。データの分布方法がわからず、分布を使用してcdfを計算するだけの場合、ほとんどの場合、誤った結果が得られます。

3
PyRsquared