binning des données en python avec scipy/numpy

est-il un moyen plus efficace de prendre une moyenne d'un tableau dans prédéterminés de bacs? par exemple, j'ai un tableau de nombres et un tableau correspondant aux positions bin start et end dans ce tableau, et je veux juste prendre la moyenne dans ces bacs? J'ai le code ci-dessous mais je me demande comment il peut être coupé et amélioré. grâce.

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
82
demandé sur user248237dfsf 2011-05-28 21:43:00

5 réponses

c'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 pour vous-même lequel est le plus rapide... :)

139
répondu Sven Marnach 2013-08-28 08:20:14

la fonction Scipy (>=0,11) scipy.statistique.binned_statistic répond spécifiquement à la question ci-dessus.

pour le même exemple que dans les réponses précédentes, la solution de 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]
31
répondu divenex 2014-11-12 10:24:39

Je ne sais pas pourquoi ce fil a été nécrosé; 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
répondu Eelco Hoogendoorn 2014-02-11 20:17:50

le paquet numpy_indexed (disclaimer: je suis son auteur) contient des fonctionnalités pour effectuer efficacement des opérations de ce type:

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

c'est essentiellement la même solution que celle que j'ai posté plus tôt; mais maintenant enveloppé dans une interface agréable, avec des tests et tout:)

4
répondu Eelco Hoogendoorn 2016-04-02 20:52:21

j'ajouterais, et aussi pour répondre à la question trouver des valeurs moyennes bin en utilisant histogram2d python que le scipy ont également une fonction spécialement conçue pour calculer une statistique bidimensionnelle binnée 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.statistique.binned_statistic_dd est une généralisation de cette fonction pour les ensembles de données de dimensions supérieures

2
répondu Chmeul 2017-05-23 12:26:25