web-dev-qa-db-fra.com

Appliquer la fonction sur chaque ligne (ligne par ligne) d'un tableau NumPy

Donc, j'ai la fonction -

def function(x):
    x , y = vector
    return exp(((-x**2/200))-0.5*(y+0.05*(x**2) - 100*0.05)**2)

et disons que je voudrais l'évaluer aux points suivants (la première colonne sont les valeurs x et la deuxième colonne sont les valeurs y) -

array([[-1.56113514,  4.51759732],
       [-2.80261623,  5.068371  ],
       [ 0.7792729 ,  6.0169462 ],
       [-1.35672858,  3.52517478],
       [-1.92074891,  5.79966161],
       [-2.79340321,  4.73430001],
       [-2.79655868,  5.05361163],
       [-2.13637747,  5.39255837],
       [ 0.17341809,  3.60918261],
       [-1.22712921,  4.95327158]])

c'est-à-dire que je voudrais transmettre à la fonction la première ligne de valeurs et évaluer, puis la deuxième ligne et évaluer etc., puis le résultat final serait un tableau des valeurs évaluées à ces points (donc, un tableau composé de 10 valeurs) .

Ainsi, par exemple, si la fonction était, disons, une distribution normale bivariée -

def function2(x):

function2 = (mvnorm.pdf(x,[0,0],[[1,0],[0,1]]))

return function2

et j'ai passé les valeurs ci-dessus dans cette fonction, j'obtiendrais -

array([  1.17738907e-05,   1.08383957e-04,   1.69855078e-04,
         5.64757613e-06,   1.37432346e-05,   1.44032800e-04,
         1.33426313e-05,   1.97822328e-06,   6.56121709e-08,
         4.67076770e-05])

Donc, fondamentalement, je cherche un moyen de réécrire la fonction pour qu'elle puisse le faire. De plus, je voudrais garder la fonction en fonction d'une seule variable (c'est-à-dire seulement une fonction de x).

Merci de votre aide!

11
tattybojangler

Vous pouvez utiliser np.apply_along_axis :

np.apply_along_axis(function, 1, array)

Le premier argument est la fonction, le deuxième argument est l'axe le long duquel la fonction doit être appliquée. Dans votre cas, c'est le premier axe. Le dernier argument est le tableau, bien sûr.

Vous devez cependant être averti que apply_along_axis n'est qu'une fonction pratique, pas une solution miracle. Il a une limitation de vitesse sévère, car il cache simplement une boucle. Vous devriez toujours essayer de vectoriser votre calcul, si possible. Voici comment je ferais cela:

v = array[:, 0] ** 2   # computing just once  
return np.exp((-v / 200) - 0.5 * (array[:, 1] + 0.05 * v - 5) ** 2)
17
cs95

Il existe plusieurs façons d'accomplir cela, la seule ligne que vous devez modifier est l'attribution de x et y. x,y = vector ne fonctionne que si la première dimension de vector a une longueur 2. (vector.shape = 2,...). Vous pouvez donc simplement changer votre vecteur avec l'une des commandes suivantes:

x,y = vector.T #transpose the array
x,y = vector.swapaxes(0,1) #swap the axis 0 and 1
x,y = np.rollaxis(vector,1) #roll the axis 1 to the front
x,y = vector[:,0], vector[:,1] #slice asignement

Choisissez simplement celui que vous aimez le plus, il pourrait y avoir d'autres façons (je suis presque sûr, mais je suppose que cela suffira). Le dernier est de loin le plus rapide, les autres sont comparables. Cependant, l'inconvénient du dernier est qu'il n'est pas si facile de l'utiliser dans des dimensions plus élevées.

2
Jürg Merlin Spaak