13

数値を特定の範囲にビン化する良い方法は何ですか? たとえば、値のリストがあり、それらを範囲ごとに N 個のビンにビン化したいとします。今、私は次のようなことをしています:

from scipy import *
num_bins = 3 # number of bins to use
values = # some array of integers...
min_val = min(values) - 1
max_val = max(values) + 1
my_bins = linspace(min_val, max_val, num_bins)
# assign point to my bins
for v in values:
  best_bin = min_index(abs(my_bins - v))

ここで、min_index は最小値のインデックスを返します。アイデアは、どのビンとの差が最も小さいかを確認することで、ポイントが該当するビンを見つけることができるということです。

しかし、これには奇妙なエッジケースがあると思います。私が探しているのは、ビンの適切な表現です。理想的には、半分閉じて半分開いているビンです (したがって、1 つのポイントを 2 つのビンに割り当てる方法はありません)。

bin1 = [x1, x2)
bin2 = [x2, x3)
bin3 = [x3, x4)
etc...

numpy/scipyを使用してPythonでこれを行う良い方法は何ですか? ここでは、整数値のビニングのみに関心があります。

どうもありがとうございました。

4

2 に答える 2

27

numpy.histogram()あなたが望むことを正確に行います。

関数のシグネチャは次のとおりです。

numpy.histogram(a, bins=10, range=None, normed=False, weights=None, new=None)

私たちは主に と に興味がaありbinsます。 aビニングする必要がある入力データです。 binsビンの数 (あなたのnum_bins) にすることも、ビンのエッジ (ハーフ オープン) を表す一連のスカラーにすることもできます。

import numpy
values = numpy.arange(10, dtype=int)
bins = numpy.arange(-1, 11)
freq, bins = numpy.histogram(values, bins)
# freq is now [0 1 1 1 1 1 1 1 1 1 1]
# bins is unchanged

ドキュメントを引用するには:

最後 (一番右) のビン以外はすべて半分開いています。つまり、次の場合bins:

[1, 2, 3, 4]

最初のビンは[1, 2)(1 を含むが 2 を除く) で、2 番目のビンは[2, 3)です。ただし、最後のビンは で[3, 4]、4 が含まれています。

編集:各要素のビンのインデックスを知りたいです。これには、 を使用できますnumpy.digitize()。ビンが一体型になる場合はnumpy.bincount()、同様に使用できます。

>>> values = numpy.random.randint(0, 20, 10)
>>> values
array([17, 14,  9,  7,  6,  9, 19,  4,  2, 19])
>>> bins = numpy.linspace(-1, 21, 23)
>>> bins
array([ -1.,   0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,
        10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.,
        21.])
>>> pos = numpy.digitize(values, bins)
>>> pos
array([19, 16, 11,  9,  8, 11, 21,  6,  4, 21])

区間は上限で開いているため、インデックスは正しいです。

>>> (bins[pos-1] == values).all()
True
>>> import sys
>>> for n in range(len(values)):
...     sys.stdout.write("%g <= %g < %g\n"
...             %(bins[pos[n]-1], values[n], bins[pos[n]]))
17 <= 17 < 18
14 <= 14 < 15
9 <= 9 < 10
7 <= 7 < 8
6 <= 6 < 7
9 <= 9 < 10
19 <= 19 < 20
4 <= 4 < 5
2 <= 2 < 3
19 <= 19 < 20
于 2010-01-27T03:59:54.683 に答える
1

これはブロードキャストを使用した numpy ではかなり簡単です。以下の例は 4 行のコードです (ビンとデータ ポイントを作成するための最初の 2 行は数えませんが、もちろん通常は提供されます)。

import numpy as NP
# just creating 5 bins at random, each bin expressed as (x, y, z) although, this code
# is not limited by bin number or bin dimension
bins = NP.random.random_integers(10, 99, 15).reshape(5, 3) 
# creating 30 random data points
data = NP.random.random_integers(10, 99, 90).reshape(30, 3)
# for each data point i want the nearest bin, but before i can generate a distance
# matrix, i need to 'conform' the array dimensions
# 'broadcasting' is an excellent and concise way to do this
bins = bins[:, NP.newaxis, :]
data2 = data[NP.newaxis, :, :]
# now i can calculate the distance matrix
dist_matrix = NP.sqrt(NP.sum((data - bins)**2, axis=-1)) 
bin_assignments = NP.argmin(dist_matrix, axis=0)

「bin_assignments」は、0 から 4 までの整数値で構成されるインデックスの 1 次元配列であり、5 つのビン (上記の「data」行列の 30 個の元の点のそれぞれに対するビンの割り当て) に対応します。

于 2010-01-31T00:08:56.283 に答える