Multiplier deux tableaux par élément, où l'un des tableaux a des tableaux comme éléments

j'ai la situation suivante dans laquelle je veux multiplier deux tableaux par élément, où l'un des tableaux a des tableaux comme éléments:

>>> import numpy as np
>>> base = np.array( [100., 111.,] )
>>> c = np.array( [9., 11.] )
>>> n0 = np.zeros(len(base))
>>> nn = 3 + n0     # This is the gist of a bunch of intermediate operations
>>> grid = [np.ones(i) for i in nn]
>>> base
array([ 100.,  111.])
>>> c
array([  9.,  11.])
>>> nn
array([ 3.,  3.])
>>> grid
[array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.])]

jusqu'à présent tout semble bien. grid semble avoir deux éléments, trois éléments de longueur chacune. Je pense que je devrais pouvoir le multiplier avec c

>>> a = grid * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

cela ne va pas comme je l'avais espéré. L'erreur est prometteur. Je peux faire quelques trucs de transposition et obtenir mon résultat:

un = (grille.T * c).T Traceback (most recent call last): File "", line 1, in AttributeError: l'objet 'list' n'a pas d'attribut 'T'

qui échoue plus que je ne le pensais. Je pensais travailler avec un tableau, mais j'apprends que j'ai maintenant une liste. J'ai essayé ma main à une bonne vieille brute force:

>>> grid_mod = np.array( [np.ones(3), np.ones(3) ] )
>>> grid_mod
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> grid_mod * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

j'étais sûr que ça marcherait! Je remarque un espace extérieur après mon dernier élément, donc je l'enlève:

>>> grid_mod2 = np.array( [np.ones(3), np.ones(7)] )
>>> grid_mod2
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)
>>> grid_mod2 * c
array([array([ 9.,  9.,  9.]),
       array([ 11.,  11.,  11.,  11.,  11.,  11.,  11.])], dtype=object)

que le dernier fonctionne comme prévu.

mes questions sont:

  1. Comment puis-je définir grid de sorte que le résultat est un tableau de tableaux au lieu d'une liste de tableaux.
  2. Ce qui se passe réellement dans tout cela? Pourquoi le supplément l'espace à la fin du tableau me donne un résultat complètement différent.
  3. y a-t-il une façon plus pythonique de faire ça?
1
demandé sur Ricardo 2013-10-29 19:47:35

1 réponses

ces deux morceaux de code produisent des choses différentes, bien que l'espace n'ait pas d'effet:

>>> np.array([np.ones(3), np.ones(3)])
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

parce que les deux tableaux de votre liste ont la même dimension, ceci est converti en un seul tableau de 2 lignes et 3 colonnes.

>>> np.array([np.ones(3), np.ones(7)])
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)

Dans ce cas, les longueurs des tableaux ne correspondent pas, donc numpy crée un tableau 1D, deux articles de long, de type object et chacun de ces objets se trouve être un tableau numpy.

quand vous multipliez le premier avec c , vous essayez de multiplier un tableau de la forme (2, 3) avec un tableau de la forme (2,) , quelque chose que numpy ne sait pas faire. Vous pouvez obtenir ce que vous voulez si vous avez remodelé votre tableau c pour avoir la forme (2, 1) , par exemple

>>> grid_mod * c[:, np.newaxis]
array([[  9.,   9.,   9.],
       [ 11.,  11.,  11.]])

quand vous multipliez la seconde par c , vous essayez de multiplier deux tableaux de forme (2,) , donc numpy fait des éléments multiplication sans problème. Et, puisque chacun des éléments de votre tableau est lui-même un tableau, lorsque vous essayez de multiplier par un scalaire, numpy aussi savoir comment le faire. Bien que cela fonctionne, il est beaucoup, beaucoup plus lent que l'approche précédente, environ 100x pour 10000 tableaux de rangée:

c = np.random.rand(10000)
a = np.random.rand(10000, 3)
b = np.empty((10000,), dtype=object)
for j in xrange(10000):
    b[j] = a[j]

%timeit a*c[:, np.newaxis]
10000 loops, best of 3: 176 us per loop

%timeit b*c
10 loops, best of 3: 16.5 ms per loop
2
répondu Jaime 2013-10-29 16:21:34