web-dev-qa-db-fra.com

Comment utiliser la fonction 'apply' du Pandas sur plusieurs colonnes?

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

196
Andy

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)
321
waitingkuo

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
29
herrfz

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)
15
Mir_Murtaza

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.

8
Blane

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)
1
shaurya airi

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)

0
Gursewak Singh