2017-04-18 15 views
8

Chciałbym użyć df.groupby() w połączeniu z apply(), aby zastosować funkcję do każdego wiersza na grupę.Użyj Pandy groupby() + apply() z argumentami

normalnie użyć następującego kodu, który zwykle działa (uwaga, że ​​to jest bez groupby()):

df.apply(myFunction, args=(arg1,)) 

Z groupby() Próbowałem następujące:

df.groupby('columnName').apply(myFunction, args=(arg1,)) 

Jednak uzyskać następujący błąd:

TypeError: myFunction() got an unexpected keyword argument 'args'

Stąd moje pytanie to: Jak używać groupby() i apply() z funkcją, która wymaga argumentów?

+2

To będzie pracować z 'df.groupby ('columnName') stosuje się (myFunction, ('arg1'))' – Zero

+0

@Zero to jest świetne rozwiązanie, ponieważ jest bardzo podobny do próbowanego przez OP rozwiązania i nie wymaga lambda. Proponuję opublikować to jako odpowiedź. – DontDivideByZero

+0

@ Zero, Mam takie samo quetsion jak OP, ale to nie działa dla mnie - nadal otrzymuję ten sam błąd co OP. Ponadto, czy mogę zapytać, dlaczego twój komentarz powinien zadziałać i dlaczego podejście PO (które jest takie samo jak moje), nie działa?Nie znalazłem go nigdzie udokumentowanego. –

Odpowiedz

8

pandas.core.groupby.GroupBy.apply NIE ma nazwie parametr args, ale pandas.DataFrame.apply ma.

Więc spróbuj tego:

df.groupby('columnName').apply(lambda x: myFunction(x, arg1)) 

lub sugerowane przez @Zero:

df.groupby('columnName').apply(myFunction, ('arg1')) 

Demo:

In [82]: df = pd.DataFrame(np.random.randint(5,size=(5,3)), columns=list('abc')) 

In [83]: df 
Out[83]: 
    a b c 
0 0 3 1 
1 0 3 4 
2 3 0 4 
3 4 2 3 
4 3 4 1 

In [84]: def f(ser, n): 
    ...:  return ser.max() * n 
    ...: 

In [85]: df.apply(f, args=(10,)) 
Out[85]: 
a 40 
b 40 
c 40 
dtype: int64 

podczas korzystania GroupBy.apply można przekazać albo nazwane argumenty:

In [86]: df.groupby('a').apply(f, n=10) 
Out[86]: 
    a b c 
a 
0 0 30 40 
3 30 40 40 
4 40 20 30 

krotki argumentów:

In [87]: df.groupby('a').apply(f, (10)) 
Out[87]: 
    a b c 
a 
0 0 30 40 
3 30 40 40 
4 40 20 30 
+0

działa jak wdzięk, dziękuję – beta

+1

Jesteś pewny, że nie ma sposobu na przekazanie parametru 'args' tutaj w krotce? Widziałem, że używane na' .apply' gdzie indziej i to eliminuje potrzebę wyrażenia lambda –

+1

@BradSolomon patrz odpowiedź Zero w pytaniu komentarze – DontDivideByZero

2

Pewne zamieszanie tutaj ponad dlaczego przy użyciu parametru args zgłasza błąd może wynikać z faktu, że pandas.DataFrame.apply dokłada mieć parametr args (krotka), natomiast pandas.core.groupby.GroupBy.apply nie .

Tak więc, wywołując .apply na samej DataFrame, można użyć tego argumentu; po wywołaniu .apply na obiekcie groupby nie można. W odpowiedzi @ MaxU wyrażenie lambda x: myFunction(x, arg1) jest przekazywane do func (pierwszy parametr); nie ma potrzeby określania dodatkowej wartości *args/**kwargs, ponieważ arg1 jest określona w lambda.

Przykład:.

import numpy as np 
import pandas as pd 

# Called on DataFrame - `args` is a 1-tuple 
# `0`/`1` are just the axis arguments to np.sum 
df.apply(np.sum, axis=0) # equiv to df.sum(0) 
df.apply(np.sum, axis=1) # equiv to df.sum(1) 


# Called on groupby object of the DataFrame - will throw TypeError 
print(df.groupby('col1').apply(np.sum, args=(0,))) 
# TypeError: sum() got an unexpected keyword argument 'args' 
Powiązane problemy