J'ai quelques problèmes avec la fonction apply Pandas lorsque j'utilise plusieurs colonnes avec la structure de données suivante
df = DataFrame ({'a' : np.random.randn(6),
'b' : ['foo', 'bar'] * 3,
'c' : np.random.randn(6)})
et la fonction suivante
def my_test(a, b):
return a % b
Lorsque j'essaie d'appliquer cette fonction avec:
df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1)
Je reçois le message d'erreur:
NameError: ("global name 'a' is not defined", u'occurred at index 0')
Je ne comprends pas ce message, j'ai bien défini le nom.
J'apprécierais hautement toute aide sur cette question
Mettre à jour
Merci de votre aide. J'ai effectivement fait des erreurs de syntaxe avec le code, l'index devrait être mis ''. Cependant, j'ai toujours le même problème en utilisant une fonction plus complexe telle que:
def my_test(a):
cum_diff = 0
for ix in df.index():
cum_diff = cum_diff + (a - df['a'][ix])
return cum_diff
Je vous remercie
On dirait que vous avez oublié le ''
de votre chaîne.
In [43]: df['Value'] = df.apply(lambda row: my_test(row['a'], row['c']), axis=1)
In [44]: df
Out[44]:
a b c Value
0 -1.674308 foo 0.343801 0.044698
1 -2.163236 bar -2.046438 -0.116798
2 -0.199115 foo -0.458050 -0.199115
3 0.918646 bar -0.007185 -0.001006
4 1.336830 foo 0.534292 0.268245
5 0.976844 bar -0.773630 -0.570417
BTW, à mon avis, la manière suivante est plus élégante:
In [53]: def my_test2(row):
....: return row['a'] % row['c']
....:
In [54]: df['Value'] = df.apply(my_test2, axis=1)
Si vous voulez juste calculer (colonne a)% (colonne b), vous n'avez pas besoin de apply
, faites-le directement:
In [7]: df['a'] % df['c']
Out[7]:
0 -1.132022
1 -0.939493
2 0.201931
3 0.511374
4 -0.694647
5 -0.023486
Name: a
Supposons que nous voulions appliquer une fonction add5 aux colonnes 'a' et 'b' de DataFrame df
def add5(x):
return x+5
df[['a', 'b']].apply(add5)
Toutes les suggestions ci-dessus fonctionnent, mais si vous souhaitez que vos calculs soient plus efficaces, vous devez tirer parti des opérations vectorielles numpy (comme indiqué ici) .
import pandas as pd
import numpy as np
df = pd.DataFrame ({'a' : np.random.randn(6),
'b' : ['foo', 'bar'] * 3,
'c' : np.random.randn(6)})
Exemple 1: boucle avec pandas.apply()
:
%%timeit
def my_test2(row):
return row['a'] % row['c']
df['Value'] = df.apply(my_test2, axis=1)
La course la plus lente a pris 7,49 fois plus longtemps que la plus rapide. Cela pourrait signifie qu'un résultat intermédiaire est mis en cache. 1000 boucles, le meilleur de 3: 481 µs par boucle
Exemple 2: vectoriser en utilisant pandas.apply()
:
%%timeit
df['a'] % df['c']
La course la plus lente prenait 458,85 fois plus longtemps que la plus rapide. Cela pourrait signifie qu'un résultat intermédiaire est mis en cache. 10000 boucles, le meilleur de 3: 70,9 µs par boucle
Exemple 3: vectoriser à l'aide de tableaux numpy:
%%timeit
df['a'].values % df['c'].values
La course la plus lente a pris 7,98 fois plus longtemps que la plus rapide. Cela pourrait signifie qu'un résultat intermédiaire est mis en cache. 100 000 boucles, au mieux de 3: 6,39 µs par boucle
La vectorisation à l'aide de tableaux numpy a donc permis d'améliorer la vitesse de presque deux ordres de grandeur.
Ceci est identique à la solution précédente mais j'ai défini la fonction dans df.apply elle-même:
df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)
J'ai donné la comparaison des trois discutés ci-dessus.
Utilisation de valeurs
% timeit df ['valeur'] = df ['a']. valeurs% df ['c']. valeurs
139 µs ± 1,91 µs par boucle (moyenne ± écart type de 7 passages, 10 000 boucles chacun)
Sans valeurs
% timeit df ['valeur'] = df ['a']% df ['c']
216 µs ± 1,86 µs par boucle (moyenne ± écart type de 7 passages, 1000 boucles chacun)
Appliquer une fonction
% timeit df ['Value'] = df.apply (ligne lambda: ligne ['a']% ligne ['c'], axe = 1)
474 µs ± 5,07 µs par boucle (moyenne ± dév. Normale de 7 cycles, 1000 boucles chacun)