verileri scipy / numpy ile python'da binning


108

Önceden belirlenmiş kutulardaki ortalama bir diziyi almanın daha verimli bir yolu var mı? örneğin, bir sayı dizim ve bu dizideki bölme başlangıç ​​ve bitiş konumlarına karşılık gelen bir dizi var ve bu bölmelerdeki ortalamayı almak istiyorum. Aşağıda bunu yapan kodum var ama nasıl kesilip iyileştirilebileceğini merak ediyorum. Teşekkürler.

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

Yanıtlar:


181

Muhtemelen daha hızlı ve kullanımı daha kolay 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))]

Buna bir alternatif kullanmaktır numpy.histogram():

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

Hangisinin daha hızlı olduğunu kendiniz deneyin ... :)


1
Fark görmüyorum - hangisi daha hızlı?

4
@user: Verileriniz ve parametreleriniz için hangisinin daha hızlı olduğunu bilmiyorum. Her iki yöntem de sizinkinden daha hızlı olmalı ve histogram()yöntemin çok sayıda kutu için daha hızlı olmasını bekliyorum . Ama kendi profilini çıkarman gerekecek, bunu senin için yapamam.
Sven Marnach

39

Scipy (> = 0.11) işlevi scipy.stats.binned_statistic özellikle yukarıdaki soruyu ele alır.

Önceki cevaplarla aynı örnek için, Scipy çözümü şöyle olacaktır:

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]

16

Bu iş parçacığının neden necroed edildiğinden emin değilim; ancak işte çok daha hızlı olması gereken 2014 onaylı bir cevap:

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

3
farklı bir soruya cevap veriyorsun. Örneğin mean[0] = np.mean(data[0:10]), doğru cevap şu olmalıdırnp.mean(data[data < 10])
Ruggero Turra

5

Numpy_indexed paketi (uyarı: Ben onun yazarım) verimli bu tip işlemleri gerçekleştirmek için işlevsellik içerir:

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

Bu aslında daha önce yayınladığım çözümün aynısı; ama şimdi güzel bir arayüzle, testlerle ve hepsiyle birlikte :)


3

Eklemek ve ayrıca soruyu cevaplamak için histogram2d python kullanarak ortalama bin değerlerini bulun , scipy ayrıca bir veya daha fazla veri kümesi için iki boyutlu bir ikili istatistiği hesaplamak için özel olarak tasarlanmış bir işleve sahiptir .

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 işlevi, daha yüksek boyutlu veri kümeleri için bu işlevin bir genellemesidir


1

Diğer bir alternatif de ufunc.at dosyasını kullanmaktır. Bu yöntem, belirtilen endekslerde istenen bir işlemi yerinde uygular. Searchsorted yöntemini kullanarak her veri noktası için depo konumunu alabiliriz. Daha sonra, bin_indexes tarafından verilen indeksteki histogramın konumunu, bin_indexes'de bir indeksle her karşılaştığımızda 1 artırmak için at kullanabiliriz.

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.