pandas python: appliquer une fonction avec des arguments à une série

147

Je veux appliquer une fonction avec des arguments à une série en pandas python:

x = my_series.apply(my_function, more_arguments_1)
y = my_series.apply(my_function, more_arguments_2)
...

La documentation décrit la prise en charge d'une méthode apply, mais elle n'accepte aucun argument. Existe-t-il une méthode différente qui accepte les arguments? Sinon, est-ce que je manque une solution de contournement simple?

Mise à jour (octobre 2017): notez que depuis que cette question a été posée à l'origine, les pandas apply()ont été mis à jour pour gérer les arguments de position et de mot-clé et le lien de documentation ci-dessus reflète maintenant cela et montre comment inclure l'un ou l'autre type d'argument.

Abe
la source
3
Pourquoi ne pas simplement utiliser functools.partial, ou starmap?
Joel Cornett
1
Voir les DataFrame.applydocuments et les Series.applydocuments
Martin Thoma

Réponses:

170

Les nouvelles versions de pandas vous permettent de passer des arguments supplémentaires (voir la nouvelle documentation ). Alors maintenant, vous pouvez faire:

my_series.apply(your_function, args=(2,3,4), extra_kw=1)

Les arguments positionnels sont ajoutés après l'élément de la série.


Pour les anciennes versions de pandas:

La documentation l'explique clairement. La méthode apply accepte une fonction python qui doit avoir un seul paramètre. Si vous souhaitez passer plus de paramètres, vous devez utiliser functools.partialcomme suggéré par Joel Cornett dans son commentaire.

Un exemple:

>>> import functools
>>> import operator
>>> add_3 = functools.partial(operator.add,3)
>>> add_3(2)
5
>>> add_3(7)
10

Vous pouvez également transmettre des arguments de mots clés à l'aide de partial.

Une autre façon serait de créer un lambda:

my_series.apply((lambda x: your_func(a,b,c,d,...,x)))

Mais je pense que partialc'est mieux d' utiliser .

Bakuriu
la source
12
Pour une méthode DataFrame, apply accepte l' argsargument, qui est un tuple contenant des arguments positionnels supplémentaires ou ** kwds pour ceux nommés. J'ai créé un problème pour l'avoir également pour Series.apply () github.com/pydata/pandas/issues/1829
Wouter Overmeire
28
La fonctionnalité a été mise en œuvre, sera dans la prochaine version de pandas
Wes McKinney
4
C'est une bonne réponse, mais les 2/3 premiers sont vraiment obsolètes maintenant. IMO, cette réponse pourrait être bien mise à jour en étant simplement un lien vers la nouvelle documentation plus un bref exemple de la façon d'utiliser avec des arguments de position et / ou de mot-clé. Juste FWIW et non une critique de la réponse originale, bénéficierait juste d'une mise à jour de l'OMI, d'autant plus qu'il s'agit d'une réponse fréquemment lue.
JohnE
@watsonic La documentation a depuis été mise à jour et un clic sur les anciens liens conduit à la documentation actuelle qui répond désormais très bien à la question.
JohnE
Remarque: si vous transmettez un seul argument de chaîne, par exemple 'abc', il args=('abc')sera évalué comme trois arguments ('a', 'b', 'c'). Pour éviter cela, vous devez passer un tuple contenant la chaîne, et pour ce faire, inclure une virgule de fin:args=('abc',)
Rocky K
82

Pas:

  1. Créer un dataframe
  2. Créer une fonction
  3. Utilisez les arguments nommés de la fonction dans l'instruction apply.

Exemple

x=pd.DataFrame([1,2,3,4])  

def add(i1, i2):  
    return i1+i2

x.apply(add,i2=9)

Le résultat de cet exemple est que chaque numéro de la trame de données sera ajouté au numéro 9.

    0
0  10
1  11
2  12
3  13

Explication:

La fonction "ajouter" a deux paramètres: i1, i2. Le premier paramètre va être la valeur dans la trame de données et le second est tout ce que nous passons à la fonction «appliquer». Dans ce cas, nous passons "9" à la fonction apply en utilisant le mot-clé argument "i2".

FistOfFury
la source
2
Exactement ce que je cherchais. Notamment, cela ne nécessite pas de créer une fonction personnalisée uniquement pour gérer une série (ou df). Parfait!
Connor
La seule question restante est: comment passer un argument mot-clé au premier argument dans add (i1) et itérer avec i2?
Connor
Je pense que c'est la meilleure réponse
crypdick
43
Series.apply(func, convert_dtype=True, args=(), **kwds)

args : tuple

x = my_series.apply(my_function, args = (arg1,))
dani_g
la source
11
Merci! Pouvez-vous expliquer pourquoi args = (arg1,) a besoin d'une virgule après le premier argument?
DrMisha
21
@MishaTeplitskiy, vous avez besoin de la virgule pour que Python comprenne le contenu des parenthèses comme un tuple de longueur 1.
prooffreader
3
Qu'en est-il de mettre des arguments pour le func. Donc, si je souhaite postuler, pd.Series.mean(axis=1)comment puis-je mettre le axis=1?
Little Bobby Tables
1
En remarque, vous pouvez également ajouter un argument de mot-clé sans utiliser le paramètre <args> (par exemple: x = ma_série.apply (ma_fonction, mot-clé_arg = arg1), où <arg_mot_clé> est parmi les paramètres d'entrée de ma_fonction)
lev
1
cette réponse est trop courte et n'explique rien
FistOfFury
23

Vous pouvez transmettre n'importe quel nombre d'arguments à la fonction qui applyappelle via des arguments sans nom, passés sous forme de tuple au argsparamètre ou via d'autres arguments de mot-clé capturés en interne sous forme de dictionnaire par le kwdsparamètre.

Par exemple, construisons une fonction qui renvoie True pour les valeurs comprises entre 3 et 6, et False sinon.

s = pd.Series(np.random.randint(0,10, 10))
s

0    5
1    3
2    1
3    1
4    6
5    0
6    3
7    4
8    9
9    6
dtype: int64

s.apply(lambda x: x >= 3 and x <= 6)

0     True
1     True
2    False
3    False
4     True
5    False
6     True
7     True
8    False
9     True
dtype: bool

Cette fonction anonyme n'est pas très flexible. Créons une fonction normale avec deux arguments pour contrôler les valeurs min et max que nous voulons dans notre série.

def between(x, low, high):
    return x >= low and x =< high

Nous pouvons répliquer la sortie de la première fonction en passant des arguments sans nom à args:

s.apply(between, args=(3,6))

Ou nous pouvons utiliser les arguments nommés

s.apply(between, low=3, high=6)

Ou même une combinaison des deux

s.apply(between, args=(3,), high=6)
Ted Petrou
la source