web-dev-qa-db-ja.com

pythonのデータをscipy / numpyでビニングする

事前に指定されたビンの配列の平均を取るより効率的な方法はありますか?たとえば、数値の配列と、その配列内のビンの開始位置と終了位置に対応する配列があり、それらのビンの平均を取得したいだけですか?私は以下でそれを行うコードを持っていますが、どのようにそれを削減して改善できるのか疑問に思っています。ありがとう。

from scipy import *
from numpy import *

def get_bin_mean(a, b_start, b_end):
    ind_upper = nonzero(a >= b_start)[0]
    a_upper = a[ind_upper]
    a_range = a_upper[nonzero(a_upper < b_end)[0]]
    mean_val = mean(a_range)
    return mean_val


data = Rand(100)
bins = linspace(0, 1, 10)
binned_data = []

n = 0
for n in range(0, len(bins)-1):
    b_start = bins[n]
    b_end = bins[n+1]
    binned_data.append(get_bin_mean(data, b_start, b_end))

print binned_data
92
user248237

おそらく numpy.digitize() を使用する方が高速で簡単です。

import numpy
data = numpy.random.random(100)
bins = numpy.linspace(0, 1, 10)
digitized = numpy.digitize(data, bins)
bin_means = [data[digitized == i].mean() for i in range(1, len(bins))]

これに代わる方法は、 numpy.histogram() を使用することです。

bin_means = (numpy.histogram(data, bins, weights=data)[0] /
             numpy.histogram(data, bins)[0])

どちらが速いか自分で試してみてください... :)

158
Sven Marnach

Scipy(> = 0.11)関数 scipy.stats.binned_statistic は、特に上記の質問に対処します。

前の回答と同じ例の場合、Scipyソリューションは次のようになります。

import numpy as np
from scipy.stats import binned_statistic

data = np.random.Rand(100)
bin_means = binned_statistic(data, data, bins=10, range=(0, 1))[0]
33
divenex

このスレッドが壊された理由はわかりません。しかし、これは2014年に承認された回答であり、はるかに高速です。

import numpy as np

data = np.random.Rand(100)
bins = 10
slices = np.linspace(0, 100, bins+1, True).astype(np.int)
counts = np.diff(slices)

mean = np.add.reduceat(data, slices[:-1]) / counts
print mean
15

numpy_indexed パッケージ(免責事項:私はその著者です)には、このタイプの操作を効率的に実行する機能が含まれています。

import numpy_indexed as npi
print(npi.group_by(np.digitize(data, bins)).mean(data))

これは、以前に投稿したものと本質的に同じソリューションです。しかし、テストとすべてを備えたNiceインターフェースにラップされました:)

4

私は追加し、質問に答えるために histogram2d pythonを使用して平均ビン値を見つける scipyには特別に設計された機能もあることを 1つ以上のデータセットの二次元ビン統計を計算します

import numpy as np
from scipy.stats import binned_statistic_2d

x = np.random.Rand(100)
y = np.random.Rand(100)
values = np.random.Rand(100)
bin_means = binned_statistic_2d(x, y, values, bins=10).statistic

関数 scipy.stats.binned_statistic_dd は、高次元のデータセットに対するこの関数の一般化です

1
Chmeul

もう1つの方法は、ufunc.atを使用することです。このメソッドは、指定されたインデックスで目的の操作をインプレースで適用します。 searchsortedメソッドを使用して、各データポイントのビンの位置を取得できます。次に、bin_indexesでインデックスが検出されるたびに、atを使用して、bin_indexesで指定されたインデックスのヒストグラムの位置を1ずつインクリメントできます。

np.random.seed(1)
data = np.random.random(100) * 100
bins = np.linspace(0, 100, 10)

histogram = np.zeros_like(bins)

bin_indexes = np.searchsorted(bins, data)
np.add.at(histogram, bin_indexes, 1)
0
kostas