Cela ne vaut la peine d'essayer de le faire sur place que si vous avez des contraintes d'espace importantes. Si c'est le cas, il est possible d'accélérer un peu votre code en itérant sur une vue aplatie du tableau. Puisque reshape
renvoie une nouvelle vue quand c'est possible les données elles-mêmes ne sont pas copiées (sauf si l'original a une structure inhabituelle).
Je ne connais pas de meilleur moyen de réaliser une application in situ authentique d'une fonction Python arbitraire.
>>> def flat_for(a, f):
... a = a.reshape(-1)
... for i, v in enumerate(a):
... a[i] = f(v)
...
>>> a = numpy.arange(25).reshape(5, 5)
>>> flat_for(a, lambda x: x + 5)
>>> a
array([[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29]])
Quelques horaires :
>>> a = numpy.arange(2500).reshape(50, 50)
>>> f = lambda x: x + 5
>>> %timeit flat_for(a, f)
1000 loops, best of 3: 1.86 ms per loop
C'est environ deux fois plus rapide que la version en boucle imbriquée :
>>> a = numpy.arange(2500).reshape(50, 50)
>>> def nested_for(a, f):
... for i in range(len(a)):
... for j in range(len(a[0])):
... a[i][j] = f(a[i][j])
...
>>> %timeit nested_for(a, f)
100 loops, best of 3: 3.79 ms per loop
Bien sûr, vectoriser est toujours plus rapide, donc si vous pouvez faire une copie, utilisez-la :
>>> a = numpy.arange(2500).reshape(50, 50)
>>> g = numpy.vectorize(lambda x: x + 5)
>>> %timeit g(a)
1000 loops, best of 3: 584 us per loop
Et si vous pouvez réécrire dim
en utilisant des ufuncs intégrés, alors s'il vous plaît, s'il vous plaît, ne vectorize
:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> %timeit a + 5
100000 loops, best of 3: 4.66 us per loop
numpy
fait des opérations comme +=
en place, comme on peut s'y attendre, ce qui vous permet de bénéficier gratuitement de la vitesse d'un ufunc avec une application en place. Parfois, c'est même plus rapide ! Voir aquí pour un exemple.
Au fait, ma réponse originale à cette question, qui peut être consultée dans son historique d'édition, est ridicule, et impliquait de vectoriser plus d'indices en a
. Non seulement il a dû faire des trucs bizarres pour contourner vectorize
's mécanisme de détection de type il s'est avéré être aussi lent que la version en boucle imbriquée. Voilà pour l'ingéniosité !