Ich habe einige Probleme mit der Pandas-Apply-Funktion, wenn Sie mehrere Spalten mit dem folgenden Datenrahmen verwenden
df = DataFrame ({'a' : np.random.randn(6),
'b' : ['foo', 'bar'] * 3,
'c' : np.random.randn(6)})
und die folgende Funktion
def my_test(a, b):
return a % b
Wenn ich versuche, diese Funktion anzuwenden, mit:
df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1)
Ich erhalte die Fehlermeldung:
NameError: ("global name 'a' is not defined", u'occurred at index 0')
Ich verstehe diese Nachricht nicht, ich habe den Namen richtig definiert.
Ich würde mich sehr über jede Hilfe zu diesem Thema freuen
Aktualisieren
Danke für Ihre Hilfe. Ich habe in der Tat einige Syntaxfehler mit dem Code gemacht, der Index sollte '' gesetzt werden. Ich habe jedoch immer noch das gleiche Problem mit einer komplexeren Funktion wie:
def my_test(a):
cum_diff = 0
for ix in df.index():
cum_diff = cum_diff + (a - df['a'][ix])
return cum_diff
Vielen Dank
Anscheinend haben Sie den ''
Ihrer Zeichenfolge vergessen.
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
Übrigens ist meiner Meinung nach der folgende Weg eleganter:
In [53]: def my_test2(row):
....: return row['a'] % row['c']
....:
In [54]: df['Value'] = df.apply(my_test2, axis=1)
Wenn Sie nur (Spalte a)% (Spalte b) berechnen möchten, benötigen Sie apply
nicht, sondern machen Sie es direkt:
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
Angenommen, wir möchten die Funktion add5 auf die Spalten 'a' und 'b' von DataFrame df anwenden
def add5(x):
return x+5
df[['a', 'b']].apply(add5)
Alle oben genannten Vorschläge funktionieren, aber wenn Sie möchten, dass Ihre Berechnungen effizienter sind, sollten Sie die numpy-Vektoroperationen (wie hier ausgeführt) nutzen.
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)})
Beispiel 1: Schleife mit pandas.apply()
:
%%timeit
def my_test2(row):
return row['a'] % row['c']
df['Value'] = df.apply(my_test2, axis=1)
Der langsamste Lauf dauerte 7,49 mal länger als der schnellste. Das könnte bedeutet, dass ein Zwischenergebnis zwischengespeichert wird. 1000 Loops, das Beste aus 3: 481 us pro Schleife
Beispiel 2: Vektorisieren mit pandas.apply()
:
%%timeit
df['a'] % df['c']
Der langsamste Lauf dauerte 458,85 Mal länger als der schnellste. Das könnte bedeutet, dass ein Zwischenergebnis zwischengespeichert wird. 10000 Loops, das Beste aus 3: 70,9 us pro Schleife
Beispiel 3: Vektorisierung mit Numpy-Arrays:
%%timeit
df['a'].values % df['c'].values
Der langsamste Lauf dauerte 7,98 Mal länger als der schnellste. Das könnte bedeutet, dass ein Zwischenergebnis zwischengespeichert wird. 100000 Schleifen, am besten von 3: 6,39 us pro Schleife
Die Vektorisierung mit numpy-Arrays verbesserte die Geschwindigkeit also um fast zwei Größenordnungen.
Dies ist dieselbe wie bei der vorherigen Lösung, aber ich habe die Funktion in df.apply selbst definiert:
df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)
Ich habe den Vergleich aller drei oben genannten gegeben.
Werte verwenden
% timeit df ['value'] = df ['a']. values% df ['c']. values
139 µs ± 1,91 µs pro Schleife (Mittelwert ± Standardabweichung von 7 Durchläufen, jeweils 10000 Schleifen)
Ohne Werte
% timeit df ['value'] = df ['a']% df ['c']
216 µs ± 1,86 µs pro Schleife (Mittelwert ± Standardabweichung von 7 Durchläufen, jeweils 1000 Schleifen)
Funktion anwenden
% timeit df ['Value'] = df.apply (Lambda-Zeile: Zeile ['a']% Zeile ['c'], Achse = 1)
474 µs ± 5,07 µs pro Loop (Mittelwert ± Standardabweichung von 7 Durchläufen, jeweils 1000 Loops)