web-dev-qa-db-ja.com

ヒストグラムビンでデータを取得する方法

ヒストグラムのビンに含まれているデータのリストを取得したい。私はnumpyとMatplotlibを使用しています。データをトラバースしてビンの端を確認する方法を知っています。ただし、2Dヒストグラムに対してこれを実行したいので、これを実行するコードはかなり醜いです。 numpyにはこれを簡単にするための構造がありますか?

1Dの場合、searchsorted()を使用できます。ただし、ロジックはそれほど優れているわけではなく、必要がないときに各データポイントでバイナリ検索を実行する必要はありません。

厄介なロジックのほとんどは、ビンの境界領域が原因です。すべての領域には、[左端、右端)のような境界があります。次のような領域を持つ最後のビンを除いて:[左端、右端]。

1Dの場合のサンプルコードは次のとおりです。

import numpy as np

data = [0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3]

hist, edges = np.histogram(data, bins=3)

print 'data =', data
print 'histogram =', hist
print 'edges =', edges

getbin = 2  #0, 1, or 2

print '---'
print 'alg 1:'

#for i in range(len(data)):
for d in data:
    if d >= edges[getbin]:
        if (getbin == len(edges)-2) or d < edges[getbin+1]:
            print 'found:', d
        #end if
    #end if
#end for

print '---'
print 'alg 2:'

for d in data:
    val = np.searchsorted(edges, d, side='right')-1
    if val == getbin or val == len(edges)-1:
        print 'found:', d
    #end if
#end for

2Dの場合のサンプルコードは次のとおりです。

import numpy as np

xdata = [0, 1.5, 1.5, 2.5, 2.5, 2.5, \
         0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, \
         0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3]
ydata = [0, 5,5, 5, 5, 5, \
         15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \
         25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30]

xbins = 3
ybins = 3
hist2d, xedges, yedges = np.histogram2d(xdata, ydata, bins=(xbins, ybins))

print 'data2d =', Zip(xdata, ydata)
print 'hist2d ='
print hist2d
print 'xedges =', xedges
print 'yedges =', yedges

getbin2d = 5  #0 through 8

print 'find data in bin #', getbin2d

xedge_i = getbin2d % xbins
yedge_i = int(getbin2d / xbins) #IMPORTANT: this is xbins

for x, y in Zip(xdata, ydata):
    # x and y left edges
    if x >= xedges[xedge_i] and y >= yedges[yedge_i]:
        #x right Edge
        if xedge_i == xbins-1 or x < xedges[xedge_i + 1]:
            #y right Edge
            if yedge_i == ybins-1 or y < yedges[yedge_i + 1]:
                print 'found:', x, y
            #end if
        #end if
    #end if
#end for

これを行うためのよりクリーンで効率的な方法はありますか? numpyはこれに何かを持っているようです。

18
Ben

digitize 、コアNumPyから、ビンのindexが得られます。ヒストグラムが属する:

import numpy as NP
A = NP.random.randint(0, 10, 100)

bins = NP.array([0., 20., 40., 60., 80., 100.])

# d is an index array holding the bin id for each point in A
d = NP.digitize(A, bins)     
24
doug

次のようなものはどうですか?

In [1]: data = numpy.array([0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3])
In [2]: hist, edges = numpy.histogram(data, bins=3)
In [3]: for l, r in Zip(edges[:-1], edges[1:]):
    print(data[(data > l) & (data < r)])
   ....:     
   ....:     
[ 0.5]
[ 1.5  1.5  1.5]
[ 2.5  2.5  2.5]
In [4]: 

edgeのケースを処理するためのコードが少しあります。

4
Autoplectic

pyplot.hist in matplotlibはヒストグラムを作成します(ただし、画面に描画しますが、これは望ましくない場合があります)。別の回答で概説されているように、ビンだけの場合は、numpy.histogramを使用できます。

ここ はpyploy.histとnumpy.histogramを比較する例です。

0
pwdyson