Supposons que j'aie un dataframe df:
Vx Vy Vmagnitude 0 1.00 1.00 1.41421 1 2.00 3.00 3.60555 2 1.50 1.75 2.30489
Le but est de créer une nouvelle colonne df ['Vmagnitude']
définie comme la magnitude de la somme vectorielle entre Vx et Vy, comme dans cette image :
Vx Vy 0 1.00 1.00 1 2.00 3.00 2 1.50 1.75
Quelle serait la manière la plus rapide et / ou la plus pythonique d'implémenter cela en utilisant numpy / pandas?
4 Réponses :
Vous pouvez utiliser np.linalg.norm < / a>:
Bonne réponse. Je ne savais pas que numpy avait une magnitude intégrée
Vous pouvez définir une nouvelle magnitude de colonne comme étant la somme des racines carrées des vecteurs comme indiqué ci-dessous
Vx Vy Magnitude 0 1.0 1.00 1.414214 1 2.0 3.00 3.605551 2 1.5 1.75 2.304886
Output:
import pandas as pd import numpy as np d = {'Vx':[1,2,1.5], 'Vy':[1,3,1.75]} df = pd.DataFrame(data=d) df['Magnitude'] = np.sqrt(df['Vx'].pow(2) + df['Vy'].pow(2)) print(df)
Un moyen rapide (performances dans les jeux 3D par exemple) serait de ne pas utiliser le sqrt et de stocker uniquement le x² + y² = x * x + y * y
dans une colonne VMagnitudeSquare ou comme vous le souhaitez .
Dans la plupart des cas, pour d'autres calculs, vous pouvez simplement l'utiliser.
Tout cela revient au fait que la fonction sqrt est "lente". Mais cela dépend de votre utilisation.
Lorsque le problème s'aggrave, vous pouvez essayer d'utiliser pandas eval. Assurez-vous d'installer numexpr pour les gains ( pip install numexpr
), voir le lisez-moi numexpr ici pour voir comment cela fonctionne. S'il est installé, Pandas intègre simplement cette fonctionnalité dans la méthode .eval
.
In [24]: %timeit np.linalg.norm( df[["vx", "vy"]], axis=1) 1 loop, best of 3: 266 ms per loop In [25]: %timeit df.eval("sqrt(vx**2 + vy**2)", engine='python') 10 loops, best of 3: 144 ms per loop In [26]: %timeit df.eval("sqrt(vx**2 + vy**2)", engine='numexpr') 10 loops, best of 3: 42 ms per loop
Je pense que c'est votre meilleur pari, numexpr utilise le multi-threading
import pandas df = pandas.DataFrame( random.random((5000000,2)), columns=('vx', 'vy')) df.eval("vmag = sqrt(vx**2 + vy**2)", engine='numexpr', inplace=True)
Voir également ce document pour améliorer les performances.
np.sqrt (df.Vx.pow (2) + df.Vy.pow (2))
ounp.sqrt (df.pow (2) .sum (1)) < / code> s'il s'agit du cadre entier