web-dev-qa-db-ja.com

pylab.hist(data、normed = 1)。正規化は正しく動作しないようです

引数normed = 1でヒストグラムを作成しようとしています

例えば:

import pylab

data = ([1,1,2,3,3,3,3,3,4,5.1])    
pylab.hist(data, normed=1)
pylab.show()

ビンの合計は1になると予想しましたが、代わりに、ビンの1つが1より大きくなります。この正規化は何をしましたか。そして、ヒストグラムの積分が1になるような正規化でヒストグラムを作成する方法は?

enter image description here

41
smirnoffs

ヒストグラム内のすべてのビンの合計を1に等しくする方法については、他の投稿を参照してください: https://stackoverflow.com/a/16399202/1542814

コピーペースト:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

myarrayにはデータが含まれます

47
Carsten König

documentationnormed:Trueの場合、結果はビンでの確率密度関数の値であり、範囲全体の積分が1になるように正規化されます。ユニティ幅のビンが選択されない限り、ヒストグラム値の合計は1に等しくなりません。これは確率質量関数ではありません。これはnumpy docからのものですが、pylabでも同じです。

In []: data= array([1,1,2,3,3,3,3,3,4,5.1])
In []: counts, bins= histogram(data, normed= True)
In []: counts
Out[]: array([ 0.488,  0.,  0.244,  0.,  1.22,  0.,  0.,  0.244,  0.,  0.244])
In []: sum(counts* diff(bins))
Out[]: 0.99999999999999989

したがって、次のようなドキュメントに従って、単純に正規化が行われます。

In []: counts, bins= histogram(data, normed= False)
In []: counts
Out[]: array([2, 0, 1, 0, 5, 0, 0, 1, 0, 1])
In []: counts_n= counts/ sum(counts* diff(bins))
In []: counts_n
Out[]: array([ 0.488,  0.,  0.244,  0.,  1.22 ,  0.,  0.,  0.244,  0.,  0.244])
24
eat

ビンの高さとビンの内容を混同していると思います。各ビンの内容、つまりすべてのビンの高さ*幅を追加する必要があります。これは1でなければなりません。

8
juanchopanza

この正規化は何をしましたか?

シーケンスを正規化するには、ビンのサイズを考慮する必要があります。 documentation によると、デフォルトのビンの数は10です。したがって、ビンのサイズは(data.max() - data.min() )/10、つまり0.41です。 normed=1の場合、バーの高さは合計に0.41を掛けた値が1になるようになります。これが統合時に発生することです。

そして、ヒストグラムの積分が1になるような正規化でヒストグラムを作成する方法は?

積分ではなく、ヒストグラムの合計を1にしたいと思います。この場合、最も簡単な方法は次のように思われます。

h = plt.hist(data)
norm = sum(data)
h2 = [i/norm for i in h[0]]
plt.bar(h[1],h2)
6
altroware

私は同じ問題を抱えていましたが、解決中に別の問題が発生しました。正規化されたビンの頻度を、四捨五入値の目盛り付きのパーセンテージとしてプロットする方法です。誰にとっても役に立つ場合に備えて、ここに投稿しています。私の例では、y軸の最大値として10%(0.1)、10ステップ(0%から1%、1%から2%など)を選択しました。トリックは、nクラスを使用して次にパーセンテージに変換されるdataカウント(plt.histの出力リストFuncFormatter)にティックを設定することです。私がやったことは次のとおりです。

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

fig, ax = plt.subplots()

# The required parameters
num_steps = 10
max_percentage = 0.1
num_bins = 40

# Calculating the maximum value on the y axis and the yticks
max_val = max_percentage * len(data)
step_size = max_val / num_steps
yticks = [ x * step_size for x in range(0, num_steps+1) ]
ax.set_yticks( yticks )
plt.ylim(0, max_val)

# Running the histogram method
n, bins, patches = plt.hist(data, num_bins)

# To plot correct percentages in the y axis     
to_percentage = lambda y, pos: str(round( ( y / float(len(data)) ) * 100.0, 2)) + '%'
plt.gca().yaxis.set_major_formatter(FuncFormatter(to_percentage))

plt.show()

プロット

正規化前:y軸の単位は、x軸のビン間隔内のサンプル数です。 Before normalisation: the y axis unit is number of samples within the bin intervals in the x axis

正規化後:y軸の単位は、すべてのサンプルに対する割合としてのビン値の頻度です After normalisation: the y axis unit is frequency of the bin values as a percentage over all the samples

5

Numpyにもアナログがあります-numpy.historgramhttp://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html パラメーターの1つは「密度」です。density=True、出力は正規化されます。

normed:bool、optionalこのキーワードは、混乱/バグのある動作のためにNumpy 1.6で非推奨になりました。 Numpy 2.0では削除されます。代わりにdensityキーワードを使用してください。 Falseの場合、結果には各ビンのサンプル数が含まれます。 Trueの場合、結果は範囲の積分が1になるように正規化されたビンでの確率密度関数の値です。この後者の動作は、ビンの幅が等しくない場合にバグがあることがわかっています。代わりに密度を使用してください。

density:bool、オプションFalseの場合、結果には各ビンのサンプル数が含まれます。 Trueの場合、結果はビンでの確率密度関数の値であり、範囲全体の積分が1になるように正規化されます。1の幅のビンが選択されない限り、ヒストグラム値の合計は1になりません。確率質量関数ではありません。指定されている場合、normedキーワードをオーバーライドします。

3

あなたの期待は間違っています

ビンの高さの合計その幅は1に等しい。または、あなたが正しく言ったように、integralは1でなければなりません関数ではなく統合します。

probability(「20歳から40歳までの確率は...%」のように)は整数です( 「20〜40歳」))確率密度ビンの高さは確率密度を示し、幅と高さの積は、このビンにある特定のポイントの確率(ビンの始めからビンの終わりまで一定の仮定関数、ビンの高さを積分します)を示します。高さ自体は密度であり、確率ではありません。それは、幅ごとの確率であり、もちろん1よりも高くなる可能性があります。

簡単な例:0から0.9の値0を持つ0から1の確率密度関数を想像してください。関数はおそらく0.9から1の間にあるでしょうか?統合する場合は、試してみてください。 1よりも高くなります。

ところで、大まかな推測から、histのheightとwidthの合計はおよそ1になりますね。

1
Mayou36