2016-04-13 10 views
6

Jeśli mam funkcjiRun funkcja dokładnie jeden raz dla każdego wiersza w dataframe pandy

def do_irreversible_thing(a, b): 
    print a, b 

a dataframe, powiedzmy

df = pd.DataFrame([(0, 1), (2, 3), (4, 5)], columns=['a', 'b']) 

Jaki jest najlepszy sposób, aby uruchomić funkcję dokładnie raz dla każdego wiersza w ramce danych pandy. As wskazał w innym questions, coś jak df.apply pandy wywoła funkcję dwa razy dla pierwszego rzędu. Nawet przy numpy

np.vectorize(do_irreversible_thing)(df.a, df.b) 

powoduje, że funkcja jest wywoływana dwukrotnie w pierwszym rzędzie, będzie df.T.apply() lub df.apply (..., oś = 1).

Czy istnieje szybszy lub czystszy sposób wywoływania funkcji z każdym rzędem niż ta jawna pętla?

for idx, a, b in df.itertuples(): 
     do_irreversible_thing(a, b) 
+3

nie będzie 'df.apply (lambda x: do_irreversible_thing (x [ 'a'] , x ['b']), axis = 1) 'work? poza tym pomysł polega na użyciu wektorowanych metod w twojej funkcji, tak aby działał na wszystkich kolumnach, które Cię interesują. – EdChum

+0

To brzmi jak zadanie dla pętli 'for'. Generalnie nie ma dobrego sposobu na wektoryzację efektów ubocznych. – user2357112

+0

Jeśli efekty uboczne nie zależą od operacji dla każdego wiersza, to powinny być możliwe do zmaskularyzacji – EdChum

Odpowiedz

2

Nie wiadomo, co się funkcja robi ale apply funkcją do każdego wiersza można zrobić przekazując axis=1 do apply czynność row-mądry i przekazać elementy kolumn zainteresowania:

In [155]: 
def foo(a,b): 
    return a*b 
​ 
df = pd.DataFrame([(0, 1), (2, 3), (4, 5)], columns=['a', 'b']) 
df.apply(lambda x: foo(x['a'], x['b']), axis=1) 

Out[155]: 
0  0 
1  6 
2 20 
dtype: int64 

jednak tak długo, jak funkcja nie zależą od df mutacji w każdym wierszu, a następnie można po prostu użyć metody wektoryzowane działać na całej kolumny:

In [156]: 
df['a'] * df['b'] 

Out[156]: 
0  0 
1  6 
2 20 
dtype: int64 

Powodem jest to, że ponieważ funkcje są wektoryzowane to będzie skala lepiej natomiast apply jest cukier tylko syntaktyczny dla iteracji na df więc jest to for pętla zasadniczo

2

Sposób, w jaki to zrobić (bo ja też nie podoba mi się pomysł z df.itertuples pętli) jest:

df.apply(do_irreversible_thing, axis=1) 

a następnie czynność powinna być jak:

def do_irreversible_thing(x): 
    print x.a, x.b 

ten sposób powinny być w stanie uruchomić funkcję na każdym rzędzie.

LUB

jeśli nie można modyfikować swoją funkcję można apply go jak ten

df.apply(lambda x: do_irreversible_thing(x[0],x[1]), axis=1)