En supposant que j'ai un tableau numpy comme: [1,2,3,4,5,6] et un autre tableau: [0,0,1,2,2,1] Je veux additionner les éléments du premier tableau par groupe (le deuxième tableau) et obtenir les résultats des n-groupes dans l'ordre des numéros de groupe (dans ce cas, le résultat serait [3, 9, 9]). Comment puis-je le faire en numpy?Somme tableau par nombre en numpy
Répondre
Il y a plus d'une façon de faire, mais voici une façon:
import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])
unique_groups = np.unique(groups)
sums = []
for group in unique_groups:
sums.append(data[groups == group].sum())
Vous pouvez choses vectoriser afin qu'il n'y ait pas de boucle du tout, mais je recommanderais contre elle. Il devient illisible, et nécessitera quelques tableaux temporaires 2D, ce qui pourrait nécessiter une grande quantité de mémoire si vous avez beaucoup de données.
Editer: Voici une façon de vectoriser entièrement. Gardez à l'esprit que cela peut (et sera probablement) plus lent que la version ci-dessus. (Et il peut y avoir une meilleure façon de le vectoriser, mais il est tard et je suis fatigué, donc c'est juste la première chose à entrer dans ma tête ...)
Cependant, gardez à l'esprit que c'est un mauvais exemple ... Vous êtes vraiment mieux (en termes de vitesse et de lisibilité) avec la boucle au-dessus ...
import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])
unique_groups = np.unique(groups)
# Forgive the bad naming here...
# I can't think of more descriptive variable names at the moment...
x, y = np.meshgrid(groups, unique_groups)
data_stack = np.tile(data, (unique_groups.size, 1))
data_in_group = np.zeros_like(data_stack)
data_in_group[x==y] = data_stack[x==y]
sums = data_in_group.sum(axis=1)
Merci! La mémoire n'est pas un problème et j'aimerais éviter les boucles. Comment le vectoriserais-tu? –
@Scribble Master - Voir le montage ... Il n'y a rien de mal à boucler sur les groupes uniques, cependant. La deuxième version sera probablement lente, et sacrément difficile à lire. Avec la boucle, vous bouclerez seulement (en python, de toute façon) sur le nombre de groupes uniques. La comparaison interne 'data [groups == group]' sera assez rapide. –
Merci encore! –
pure mise en œuvre du python:
l = [1,2,3,4,5,6]
g = [0,0,1,2,2,1]
from itertools import izip
from operator import itemgetter
from collections import defaultdict
def group_sum(l, g):
groups = defaultdict(int)
for li, gi in izip(l, g):
groups[gi] += li
return map(itemgetter(1), sorted(groups.iteritems()))
print group_sum(l, g)
[3, 9, 9]
Si les groupes sont indexé par des entiers consécutifs, vous pouvez abuser de la fonction numpy.histogram()
pour obtenir le résultat:
data = numpy.arange(1, 7)
groups = numpy.array([0,0,1,2,2,1])
sums = numpy.histogram(groups,
bins=numpy.arange(groups.min(), groups.max()+2),
weights=data)[0]
# array([3, 9, 9])
Cela évitera toutes les boucles Python.
Bon point! +1 de moi! –
Ceci est une méthode vectorisée de faire cette somme basée sur l'implémentation de numpy.unique. Selon mes timings, il est jusqu'à 500 fois plus rapide que la méthode de la boucle et jusqu'à 100 fois plus rapide que la méthode de l'histogramme.
def sum_by_group(values, groups):
order = np.argsort(groups)
groups = groups[order]
values = values[order]
values.cumsum(out=values)
index = np.ones(len(groups), 'bool')
index[:-1] = groups[1:] != groups[:-1]
values = values[index]
groups = groups[index]
values[1:] = values[1:] - values[:-1]
return values, groups
Fonctionne avec brio! – Nate
La fonction numpy bincount
a été fait exactement à cette fin et je suis sûr que ce sera beaucoup plus rapide que les autres méthodes pour toutes les tailles d'entrées:
data = [1,2,3,4,5,6]
ids = [0,0,1,2,2,1]
np.bincount(ids, weights=data) #returns [3,9,9] as a float64 array
L'élément i-ième la sortie est la somme de tous les éléments data
correspondant à "id" i
.
Espérons que cela aide.
Peut confirmer que c'est très rapide. Environ 10 fois plus rapide que la méthode sum_by_group fournie par Bi Rico sur de petites entrées. –
que se passe-t-il si 'données' sont des vecteurs? – zzh1996
Il semble que l'argument des poids doive être unidimensionnel. Une solution consiste à exécuter binaire une fois pour chaque dimension du vecteur (c'est-à-dire deux fois si les données sont un ensemble de vecteurs 2-d). Une légère modification de la réponse de Peter devrait également fonctionner. – Alex
J'ai essayé des scripts de tout le monde et mes considérations sont:
Joe: ne fonctionnera que si vous avez quelques groupes.
kevpie: Trop lent à cause des boucles (ce n'est pas ainsi pythonique)
Bi_Rico et Sven: effectuer bon, mais ne fonctionnera que pour Int32 (si la somme dépasse 2^32/2, il échouera) Alex: est le plus rapide, bon pour la somme.
Mais si vous voulez plus de flexibilité et la possibilité de regrouper par d'autres statistiques utilisent SciPy:
from scipy import ndimage
data = np.arange(10000000)
groups = np.arange(1000).repeat(10000)
ndimage.sum(data, groups, range(1000))
Ce qui est bon parce que vous avez beaucoup de statistiques à groupe (somme, moyenne, variance, ...).
Je remarqué la balise numpy
mais dans le cas où vous ne me dérange pas en utilisant pandas
, cette tâche devient un one-liner:
import pandas as pd
import numpy as np
data = np.arange(1, 7)
groups = np.array([0, 0, 1, 2, 2, 1])
df = pd.DataFrame({'data': data, 'groups': groups})
Alors df
ressemble alors à ceci:
data groups
0 1 0
1 2 0
2 3 1
3 4 2
4 5 2
5 6 1
maintenant vous pouvez utiliser les fonctions groupby()
et sum()
print df.groupby(['groups'], sort=False).sum()
qui vous donne la sortie désirée
data
groups
0 3
1 9
2 9
Par défaut, le dataframe serait réglé, donc j'utiliser le drapeau sort=False
qui pourrait améliorer la vitesse pour dataframes énormes.
Vous avez tous tort! La meilleure façon de le faire est:
a = [1,2,3,4,5,6]
ix = [0,0,1,2,2,1]
accum = np.zeros(np.max(ix)+1)
np.add.at(accum, ix, a)
print accum
> array([ 3., 9., 9.])
- 1. Somme d'une ligne d'un tableau NumPy
- 2. tableau de diffusion Numpy
- 3. Tableau d'objets avec numpy
- 4. Python/Numpy: tableau de division
- 5. problème d'affectation de tableau numpy
- 6. Diffusion d'un tableau avec numpy
- 7. Convertir la liste en tuple en un tableau numpy?
- 8. tableau php somme récursive
- 9. Somme des différences carrées (SSD) dans numpy/scipy
- 10. Comment lire csv en tableau record en numpy?
- 11. Conversion (en partie) d'un recarray numpy en un tableau 2d?
- 12. voulez calculer la somme du nombre rendu par le groupe par l'option
- 13. Python Numpy Tableau (Structured recarray) attribuer des valeurs en tranches
- 14. Zombie messaged par [nombre de tableau]
- 15. Ajout d'un tableau en numpy à un emplacement spécifié
- 16. Tableau d'objets Numpy de tableaux numériques
- 17. Réplication de tableau par élément en fonction d'un nombre
- 18. Convertir une liste de tableaux numpy 2D en un tableau numpy 3D?
- 19. Comment accéder au tableau numpy dans PyCXX
- 20. Conversion de type place d'un tableau NumPy
- 21. Problème de mémoire de tableau Numpy
- 22. Redimensionnement et étirer un tableau numpy
- 23. Ajout ou redimensionnement pour un tableau numpy
- 24. Convertir un tableau python numpy en C++ stl vector
- 25. indices Sélection pour un tableau 2d numpy
- 26. comment afficher un tableau numpy avec pyglet?
- 27. Modification de tableau masqué de Numpy
- 28. Ajout d'un tableau numpy à un scipy.sparse.dok_matrix
- 29. Comment convertir un tableau de chaînes en un tableau de nombres flottants en numpy?
- 30. combinaisons linéaires en python/numpy
Pourquoi avez-vous besoin de numpy pour cela? N'utilisez-vous pas seulement les listes vanilla python? Sinon, quel type chiffré utilisez-vous? –
J'ai besoin de numpy pour cela parce que je ne veux pas parcourir le tableau n fois pour n groupes, puisque mes tailles de tableaux peuvent être arbitrairement grandes. Je n'utilise pas les listes python, je montrais juste un exemple de jeu de données entre parenthèses. Le type de données est int. –
connexes http://stackoverflow.com/questions/7089379/most-efficient-way-to-sum-huge-2d-numpy-array-grouped-by-id-column – TooTone