189 votes

Numpy : Diviser chaque ligne par un élément de vecteur

Supposons que j'ai un tableau numpy :

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

et j'ai un "vecteur" correspondant :

vector = np.array([1,2,3])

Comment puis-je opérer sur data le long de chaque ligne pour soustraire ou diviser de sorte que le résultat soit :

sub_result = [[0,0,0], [0,0,0], [0,0,0]]
div_result = [[1,1,1], [1,1,1], [1,1,1]]

En résumé : Comment effectuer une opération sur chaque ligne d'un tableau 2D avec un tableau 1D de scalaires qui correspondent à chaque ligne ?

264voto

JoshAdel Points 15911

Ici, voici. Vous devez simplement utiliser None (ou alternativement np.newaxis) avec la diffusion :

In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

19voto

IanH Points 1587

Comme mentionné précédemment, découper avec None ou avec np.newaxes est un excellent moyen de le faire. Une autre alternative consiste à utiliser des transpositions et du broadcast, comme dans

(data.T - vecteur).T

et

(data.T / vecteur).T

Pour des tableaux de dimensions plus élevées, vous voudrez peut-être utiliser la méthode swapaxes des tableaux NumPy ou la fonction rollaxis de NumPy. Il y a vraiment beaucoup de façons de faire cela.

Pour une explication plus détaillée du broadcast, consultez http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

10voto

meow Points 685

Ajoutant à la réponse de stackoverflowuser2010, dans le cas général vous pouvez simplement utiliser

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

vector = np.array([1,2,3])

data / vector.reshape(-1,1)

Cela transformera votre vecteur en une matrice/vecteur colonne. Vous permettant d'effectuer des opérations élément par élément comme vous le souhaitez. Au moins pour moi, c'est la façon la plus intuitive de procéder et étant donné que (dans la plupart des cas) numpy utilisera simplement une vue de la même mémoire interne pour le remodelage, c'est aussi efficace.

9voto

shantanu pathak Points 111

La manière pythonique de le faire est ...

np.divide(data.T,vector).T

Cela prend en charge le remodelage et les résultats sont également au format flottant. Dans d'autres réponses, les résultats sont au format entier arrondi.

#REMARQUE : Le nombre de colonnes dans les données et le vecteur doit correspondre

4voto

La solution de JoshAdel utilise np.newaxis pour ajouter une dimension. Une alternative consiste à utiliser reshape() pour aligner les dimensions en préparation à la diffusion.

data = np.array([[1,1,1],[2,2,2],[3,3,3]])
vector = np.array([1,2,3])

data
# array([[1, 1, 1],
#        [2, 2, 2],
#        [3, 3, 3]])
vector
# array([1, 2, 3])

data.shape
# (3, 3)
vector.shape
# (3,)

data / vector.reshape((3,1))
# array([[1, 1, 1],
#        [1, 1, 1],
#        [1, 1, 1]])

Effectuer le reshape() permet d'aligner les dimensions pour la diffusion :

data:            3 x 3
vector:              3
vector reshaped: 3 x 1

Notez que data/vector est correct, mais cela ne vous donne pas la réponse que vous souhaitez. Cela divise chaque colonne du array (au lieu de chaque ligne) par chaque élément correspondant du vector. C'est ce que vous obtiendriez si vous remodeliez explicitement vector pour être 1x3 au lieu de 3x1.

data / vector
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])
data / vector.reshape((1,3))
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X