webentwicklung-frage-antwort-db.com.de

daten in Python mit scipy/numpy binning

gibt es eine effizientere Methode, um einen Durchschnitt eines Arrays in vorgegebenen Bins zu ermitteln? Ich habe zum Beispiel ein Zahlenfeld und ein Feld, das den Anfangs- und Endpositionen der Behälter in diesem Feld entspricht, und ich möchte nur den Mittelwert in diesen Bereichen verwenden. Ich habe Code, der dies tut, aber ich frage mich, wie er reduziert und verbessert werden kann. Vielen Dank.

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
84
user248237dfsf

Es ist wahrscheinlich schneller und einfacher zu bedienen 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))]

Eine Alternative dazu ist die Verwendung von numpy.histogram() :

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

Probiere selbst welche schneller ist ... :)

142
Sven Marnach

Die Funktion Scipy (> = 0,11) scipy.stats.binned_statistic befasst sich speziell mit der obigen Frage.

Für das gleiche Beispiel wie in den vorherigen Antworten wäre die Scipy-Lösung

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]
32
divenex

Ich bin nicht sicher, warum dieser Thread geknackt wurde. Aber hier ist eine 2014 genehmigte Antwort, die viel schneller sein sollte:

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
14

Das Paket numpy_indexed (Haftungsausschluss: Ich bin sein Autor) enthält Funktionen, um Operationen dieses Typs effizient auszuführen:

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

Dies ist im Wesentlichen die gleiche Lösung wie die, die ich zuvor veröffentlicht habe. aber jetzt in ein schönes Interface verpackt, mit Tests und allem :)

4

Ich würde hinzufügen und auch die Frage find mean bin mit Hilfe von histogram2d python beantworten, dass der scipy auch eine Funktion hat, die speziell dafür entwickelt wurde, eine bidimensionale binierte Statistik für einen oder mehrere Datensätze

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

die Funktion scipy.stats.binned_statistic_dd ist eine Verallgemeinerung dieser Funktion für Datensätze mit höheren Dimensionen

1
Chmeul

Eine andere Alternative ist die Verwendung von ufunc.at. Diese Methode wendet eine gewünschte Operation direkt an den angegebenen Indizes an .. _. Wir können die Bin-Position für jeden Datenpunkt mithilfe der searchsorted-Methode ermitteln. Dann können wir at verwenden, um die Position des Histogramms an dem von bin_indexes angegebenen Index um 1 zu erhöhen, jedes Mal, wenn wir bei bin_indexes einen Index finden. 

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