web-dev-qa-db-fra.com

Evaluation efficace d'une fonction à chaque cellule d'un tableau NumPy

Etant donné un NumPy array [~ # ~] a [~ # ~], quel est le moyen le plus rapide/le plus efficace d'appliquer le Même fonction , f, to chaque cellule ?

  1. Supposons que nous assignions à A (i, j) le f (A (i, j)).

  2. La fonction, f, n'a pas de sortie binaire, ainsi les opérations de masque (ing) ne vous aideront pas.

La double itération "évidente" (à travers chaque cellule) est-elle la solution optimale?

121
Peter

Vous pouvez simplement vectoriser la fonction, puis l’appliquer directement à un tableau Numpy chaque fois que vous en avez besoin:

import numpy as np

def f(x):
    return x * x + 3 * x - 2 if x > 0 else x * 5 + 8

f = np.vectorize(f)  # or use a different name if you want to keep the original f

result_array = f(A)  # if A is your Numpy array

Il est probablement préférable de spécifier directement un type de sortie lors de la vectorisation:

f = np.vectorize(f, otypes=[np.float])
161
blubberdiblub

Une question similaire est: mappage d'un tableau NumPy à la place . Si vous pouvez trouver un func pour votre f (), utilisez le paramètre out.

5
cyborg

Si vous travaillez avec des nombres et f(A(i,j)) = f(A(j,i)), vous pouvez utiliser scipy.spatial.distance.cdist pour définir f comme distance entre A(i) et A(j).

1
Raphaël Fettaya

Je pense avoir trouvé une meilleure solution. L’idée de changer la fonction en python fonction universelle (voir documentation )), qui permet d’exercer un calcul parallèle sous le capot.

On peut écrire son propre ufunc personnalisé en C, ce qui est sûrement plus efficace, ou en invoquant np.frompyfunc, qui est la méthode d'usine intégrée. Après le test, cela est plus efficace que np.vectorize:

f = lambda x, y: x * y
f_arr = np.frompyfunc(f, 2, 1)
vf = np.vectorize(f)
arr = np.linspace(0, 1, 10000)

%timeit f_arr(arr, arr) # 307ms
%timeit f_arr(arr, arr) # 450ms

J'ai également testé de plus grands échantillons, et l'amélioration est proportionnelle. Pour comparer les performances d'autres méthodes, voir cet article

0
Wunderbar