web-dev-qa-db-fra.com

Comment calculer la somme de toutes les colonnes d'un tableau 2D numpy (efficacement)

Disons que j'ai le tableau 2D numpy suivant composé de quatre lignes et trois colonnes:

>>> a = numpy.arange(12).reshape(4,3)
>>> print(a)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]

Quel serait un moyen efficace de générer un tableau 1D contenant la somme de toutes les colonnes (comme [18, 22, 26])? Cela peut-il être fait sans avoir besoin de parcourir toutes les colonnes?

43
Puggie

Consultez la documentation de numpy.sum , en prêtant une attention particulière au paramètre axis. Pour résumer en colonnes: 

>>> import numpy as np
>>> a = np.arange(12).reshape(4,3)
>>> a.sum(axis=0)
array([18, 22, 26])

Ou, pour résumer sur les lignes:

>>> a.sum(axis=1)
array([ 3, 12, 21, 30])

D'autres fonctions d'agrégation, telles que numpy.mean , numpy.cumsum et numpy.std , prennent par exemple le paramètre axis.

Extrait du Didacticiel Numpy provisoire :

De nombreuses opérations unaires, telles que le calcul de la somme de tous les éléments dans le tableau, sont implémentées en tant que méthodes de la classe ndarray. Par Par défaut, ces opérations s’appliquent au tableau comme s’il s’agissait d’une liste de chiffres, quelle que soit sa forme. Cependant, en spécifiant axis paramètre, vous pouvez appliquer une opération le long de l’axe spécifié d’un fichier tableau:

82
John Vinyard

Utilisez numpy.sum . pour votre cas, c'est

sum = a.sum(axis=0)
4
Chunliang Lyu

D'autres alternatives pour sommer les colonnes sont

numpy.einsum('ij->j', a)

et

numpy.dot(a.T, numpy.ones(a.shape[0]))

Si le nombre de lignes et de colonnes est dans le même ordre de grandeur, toutes les possibilités sont à peu près aussi rapides:

 enter image description here

Cependant, s'il n'y a que quelques colonnes, les solutions einsum et dot surpassent de manière significative les sum de numpy (notez l'échelle du journal):

 enter image description here


Code pour reproduire les parcelles:

import numpy
import perfplot


def numpy_sum(a):
    return numpy.sum(a, axis=1)


def einsum(a):
    return numpy.einsum('ij->i', a)


def dot_ones(a):
    return numpy.dot(a, numpy.ones(a.shape[1]))


perfplot.show(
    # setup=lambda n: numpy.random.Rand(n, n),
    setup=lambda n: numpy.random.Rand(n, 3),
    n_range=[2**k for k in range(15)],
    kernels=[numpy_sum, einsum, dot_ones],
    logx=True,
    logy=True,
    xlabel='len(a)',
    )
3
Nico Schlömer

Utilisez l'argument axis:

>> numpy.sum(a, axis=0)
  array([18, 22, 26])
3
Ben Allison

Puis la fonction NumPy sum prend un argument d'axe facultatif qui spécifie le long de l'axe sur lequel vous souhaitez effectuer la somme:

>>> a = numpy.arange(12).reshape(4,3)
>>> a.sum(0)
array([18, 22, 26])

Ou équivalent:

>>> numpy.sum(a, 0)
array([18, 22, 26])
2
bogatron
a.sum(0)

devrait résoudre le problème. Il s'agit d'un 2c np.array et vous obtiendrez la somme de toutes les colonnes. axis=0 est la dimension qui pointe vers le bas et axis=1 celle qui pointe vers la droite.

0
ibozkurt79