python pandas: aplica uma função com argumentos a uma série

147

Quero aplicar uma função com argumentos a uma série em pandas python:

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

A documentação descreve o suporte a um método apply, mas não aceita argumentos. Existe um método diferente que aceite argumentos? Como alternativa, estou faltando uma solução alternativa simples?

Atualização (outubro de 2017): observe que desde que essa pergunta foi feita originalmente, o pandas apply()foi atualizado para lidar com argumentos posicionais e de palavras-chave e o link da documentação acima agora reflete isso e mostra como incluir qualquer tipo de argumento.

Abe
fonte
3
Por que não apenas usar functools.partial, ou starmap?
Joel Cornett

Respostas:

170

Versões mais recentes do pandas fazer permitem passar argumentos extras (ver a nova documentação ). Então agora você pode fazer:

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

Os argumentos posicionais são adicionados após o elemento da série.


Para uma versão mais antiga do pandas:

A documentação explica isso claramente. O método apply aceita uma função python que deve ter um único parâmetro. Se você quiser passar mais parâmetros, use functools.partialcomo sugerido por Joel Cornett em seu comentário.

Um exemplo:

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

Você também pode passar argumentos de palavras-chave usando partial.

Outra maneira seria criar um lambda:

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

Mas acho que usar partialé melhor.

Bakuriu
fonte
12
Para um DataFrame, o método apply aceita o argsargumento, que é uma tupla contendo argumentos posicionais adicionais ou ** kwds para os nomeados. Eu criei uma questão de ter isso também para Series.apply () github.com/pydata/pandas/issues/1829
Wouter Overmeire
28
Característica foi implementada, será no próximo lançamento pandas
Wes McKinney
4
Esta é uma boa resposta, mas os primeiros 2/3 dela estão realmente obsoletos agora. Na IMO, essa resposta pode ser bem atualizada apenas por ser um link para a nova documentação, além de um breve exemplo de como usar com argumentos de posição e / ou palavra-chave. Apenas o FWIW e não uma crítica à resposta original, apenas se beneficiariam de uma atualização da IMO, especialmente porque é uma resposta lida com frequência.
Johne
@ watsonic A documentação foi atualizada e, ao clicar nos links antigos, leva à documentação atual, que agora responde muito bem à pergunta.
Johne
Nota: Se você estiver passando um argumento de cadeia única, por exemplo 'abc', args=('abc')será avaliado como três argumentos ('a', 'b', 'c'). Para evitar isso, você deve passar uma tupla contendo a string e, para isso, incluir uma vírgula à direita:args=('abc',)
Rocky K
82

Passos:

  1. Crie um quadro de dados
  2. Crie uma função
  3. Use os argumentos nomeados da função na instrução apply.

Exemplo

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

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

x.apply(add,i2=9)

O resultado deste exemplo é que cada número no quadro de dados será adicionado ao número 9.

    0
0  10
1  11
2  12
3  13

Explicação:

A função "add" possui dois parâmetros: i1, i2. O primeiro parâmetro será o valor no quadro de dados e o segundo é o que passarmos para a função "aplicar". Nesse caso, estamos passando "9" para a função aplicar usando o argumento de palavra-chave "i2".

FistOfFury
fonte
2
Exatamente o que eu estava procurando. Notavelmente, isso não requer a criação de uma função personalizada apenas para lidar com uma série (ou df). Perfeito!
Connor
A única questão restante é: como passar um argumento de palavra-chave para o primeiro argumento em add (i1) e iterar com i2?
Connor
Eu acho que essa é a melhor resposta
crypdick
43
Series.apply(func, convert_dtype=True, args=(), **kwds)

args : tuple

x = my_series.apply(my_function, args = (arg1,))
dani_g
fonte
11
Obrigado! Você pode explicar por que args = (arg1,) precisa de uma vírgula após o primeiro argumento?
DrMisha 5/05
21
@MishaTeplitskiy, você precisa da vírgula para que Python para entender o conteúdo dos parênteses para ser uma tupla de comprimento 1.
prooffreader
3
Que tal colocar args para o func . Então, se eu quiser me inscrever, pd.Series.mean(axis=1)como coloco o axis=1?
Tabelas Pouco Bobby
1
Como uma observação lateral, você também pode adicionar um argumento de palavra-chave sem usar o parâmetro <args> (por exemplo: x = my_series.apply (minha_função, palavra-chave_arg = arg1), onde <arraxa_chave> está entre os parâmetros de entrada de minha_função)
lev
1
esta resposta é muito curta e não explica nada
FistOfFury
23

Você pode passar qualquer número de argumentos para a função que applyestá chamando por argumentos não nomeados, passados ​​como uma tupla para o argsparâmetro ou por outros argumentos de palavras-chave capturados internamente como um dicionário pelo kwdsparâmetro.

Por exemplo, vamos criar uma função que retorne True para valores entre 3 e 6 e False caso contrário.

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

Esta função anônima não é muito flexível. Vamos criar uma função normal com dois argumentos para controlar os valores mínimo e máximo que queremos em nossa série.

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

Podemos replicar a saída da primeira função passando argumentos sem nome para args:

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

Ou podemos usar os argumentos nomeados

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

Ou mesmo uma combinação de ambos

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