web-dev-qa-db-fra.com

Utilisez des pandas groupby () + apply () avec des arguments

Je voudrais utiliser df.groupby() en combinaison avec apply() pour appliquer une fonction à chaque ligne par groupe.

J'utilise normalement le code suivant, qui fonctionne habituellement (notez que c'est sans groupby()):

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

Avec la groupby() j'ai essayé ce qui suit:

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

Cependant, j'obtiens l'erreur suivante:

TypeError: myFunction () a reçu un argument de mot clé inattendu, 'args'

Par conséquent, ma question est la suivante: Comment puis-je utiliser groupby() et apply() avec une fonction qui nécessite des arguments?

17
beta

pandas.core.groupby.GroupBy.apply N'A PAS le paramètre namedargs, mais pandas.DataFrame.apply l'a.

Alors essayez ceci:

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

ou comme suggéré par @Zero :

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

Démo:

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

lorsque vous utilisez GroupBy.apply, vous pouvez passer un argument nommé:

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

un tuple d'arguments:

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
13
MaxU

Une certaine confusion ici sur pourquoi l'utilisation d'un paramètre args génère une erreur peut provenir du fait que pandas.DataFrame.apply a un paramètre args (un tuple), alors que pandas.core.groupby.GroupBy.apply n'en a pas.

Ainsi, lorsque vous appelez .apply sur un DataFrame lui-même, vous pouvez utiliser cet argument. lorsque vous appelez .apply sur un objet groupby, vous ne pouvez pas.

Dans la réponse de @ MaxU, l'expression lambda x: myFunction(x, arg1) est transmise à func (le premier paramètre); il n'est pas nécessaire de spécifier un *args/**kwargs supplémentaire, car arg1 est spécifié dans lambda.

Un exemple:

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'
5
Brad Solomon