Python で Matplotlib を使用して数値配列の経験的 CDF をプロットするにはどうすればよいですか? Pylab のhist
関数の CDF 類似物を探しています。
私が思いつくことの一つは、次のとおりです。
from scipy.stats import cumfreq
a = array([...]) # my array of numbers
num_bins = 20
b = cumfreq(a, num_bins)
plt.plot(b)
ベストアンサー1
linspace
ワンライナーが好みであれば、次のようにすることもできます。
plt.plot(np.sort(a), np.linspace(0, 1, len(a), endpoint=False))
私の好みを考えると、私はほとんどいつもこうします:
# a is the data array
x = np.sort(a)
y = np.arange(len(x))/float(len(x))
plt.plot(x, y)
これはデータ値があっても機能します>O(1e6)
。本当にダウンサンプリングする必要がある場合は、
x = np.sort(a)[::down_sampling_step]
編集endpoint=False
上記で定義した理由や使用方法に関するコメント/編集に応答しますy
。以下は技術的な詳細です。
経験的CDFは通常、次のように正式に定義される。
CDF(x) = "number of samples <= x"/"number of samples"
y = np.arange(1,len(x)+1)/float(len(x))
この正式な定義と正確に一致させるためには、を使う必要がありますy = [1/N, 2/N ... 1]
。この推定量は、無限サンプルの限界において真のCDFに収束する不偏推定量です。Wikipedia 参照。。
私は since を使用する傾向がありますy = [0, 1/N, 2/N ... (N-1)/N]
:
(a)コーディングが簡単/より慣用的である、
(b) しかし、収束証明でCDF(x)
は常に と交換できるため、形式的には正当化され、1-CDF(x)
(c) は、上記の (簡単な) ダウンサンプリング方法で機能します。
特定のケースでは、
y = (arange(len(x))+0.5)/len(x)
これは、これら 2 つの規則の中間です。つまり、実際には、「1/(2N)
サンプルでこれまでに見た最小値よりも小さい値になる可能性があり、1/(2N)
これまでに見た最大値よりも大きい値になる可能性もあります」ということです。
この規則の選択はwhere
、plt.step
CDF を区分定数関数として表示する方が便利と思われる場合。上記の正式な定義と正確に一致させるには、where=pre
提案されたy=[0,1/N..., 1-1/N]
規則を使用するか、規則where=post
に従う必要がありますy=[1/N, 2/N ... 1]
が、その逆はできません。
ただし、サンプル数が多く、分布が妥当な場合、回答の本文で示されている規則は記述が簡単で、真の CDF の不偏推定値となり、ダウンサンプリング手法で機能します。