Question binning données en python avec scipy / numpy


Existe-t-il un moyen plus efficace de prendre en moyenne un tableau dans des bacs pré-spécifiés? Par exemple, j'ai un tableau de nombres et un tableau correspondant aux positions de début et de fin de ce tableau, et je veux juste prendre la moyenne dans ces cases? J'ai le code qui le fait ci-dessous mais je me demande comment il peut être réduit et amélioré. Merci.

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

80
2018-05-28 17:43


origine


Réponses:


Il est probablement plus rapide et plus facile à utiliser 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))]

Une alternative à cela est d'utiliser numpy.histogram():

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

Essayez vous-même lequel est le plus rapide ... :)


134
2018-05-28 17:53



La fonction Scipy (> = 0.11) scipy.stats.binned_statistic traite spécifiquement de la question ci-dessus.

Pour le même exemple que dans les réponses précédentes, la solution Scipy serait

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]

29
2017-11-12 10:19



Je ne sais pas pourquoi ce fil a été necroed; mais voici une réponse approuvée en 2014, qui devrait être beaucoup plus rapide:

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
2018-02-11 20:17



le numpy_indexed package (disclaimer: je suis son auteur) contient des fonctionnalités permettant d'effectuer efficacement des opérations de ce type:

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

Ceci est essentiellement la même solution que celle que j'ai publiée plus tôt; mais maintenant enveloppé dans une belle interface, avec des tests et tout :)


4
2018-04-02 15:40



J'ajouterais, et aussi pour répondre à la question trouver des valeurs de bin moyenne en utilisant histogram2d python que le scipy a également une fonction spécialement conçue pour calculer une statistique bimensuelle bidimensionnelle pour un ou plusieurs ensembles de données

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

la fonction scipy.stats.binned_statistic_dd est une généralisation de cette fonction pour les ensembles de données de dimensions supérieures


2
2017-07-26 10:50