Pandas: Como posso usar a função apply () para uma única coluna?


258

Eu tenho um quadro de dados de pandas com duas colunas. Preciso alterar os valores da primeira coluna sem afetar a segunda e recuperar todo o quadro de dados com apenas os valores da primeira coluna alterados. Como posso fazer isso usando a aplicação em pandas?


4
Poste alguns dados de amostra de entrada e a saída desejada.
Fabio Lamanna

Você quase nunca deve usar applyem uma situação como esta. Opere diretamente na coluna.
Ted Petrou #

Como Ted Petrou disse, evite usar applyo máximo possível. Se você não tem certeza de que precisa usá-lo, provavelmente não precisa. Eu recomendo dar uma olhada em Quando devo usar pandas apply () no meu código? .
cs95

A questão não está completamente clara: ela aplica uma função a todos os elementos de uma coluna ou aplica uma função à coluna como um todo (por exemplo: reverter a coluna)?
Pierre ALBARÈDE

Respostas:


338

Dado um quadro de dados de amostra dfcomo:

a,b
1,2
2,3
3,4
4,5

o que você quer é:

df['a'] = df['a'].apply(lambda x: x + 1)

que retorna:

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

9
applynunca deve ser usado em uma situação como esta
Ted Petrou

5
@TedPetrou, você está perfeitamente certo, foi apenas um exemplo de como aplicar uma função geral em uma única coluna, conforme solicitado pelo OP.
Fabio Lamanna

14
Quando eu tento fazer isso eu recebo o seguinte aviso: "Um valor está tentando ser definido em uma cópia de uma fatia de uma trama de dados Tente usar .loc [row_indexer, col_indexer] = valor, em vez."
dagrun

24
Por uma questão de curiosidade: por que o aplicativo não deve ser usado nessa situação? Qual é exatamente a situação?
Tio Ben Ben

19
O @UncleBenBen em geral applyusa um loop interno sobre linhas que é muito mais lento que as funções vetorizadas, como por exemplo df.a = df.a / 2(veja a resposta de Mike Muller).
Fabio Lamanna 29/03

66

Para uma única coluna melhor para usar map(), assim:

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

78
Por que é map()melhor do que apply()para uma única coluna?
ChaimG

2
Isso foi muito útil. Usei-o para extrair os nomes de arquivos dos caminhos armazenados em uma colunadf['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
mmann1123

46
map () é para Series (ou seja, colunas únicas) e opera em uma célula por vez, enquanto apply () é para DataFrame e opera em uma linha inteira por vez.
jpcgt

3
@jpcgt Isso significa que o mapa é mais rápido do que o aplicado neste caso?
Viragos 18/08/19

@ChaimG eu vejo esse sistema operacional explica bem: stackoverflow.com/a/19798528/571828
21419

41

Você não precisa de nenhuma função. Você pode trabalhar diretamente em uma coluna inteira.

Dados de exemplo:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

Metade de todos os valores na coluna a:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

E se eu quiser dividir todos os elementos de uma coluna por "/" e pegar a primeira parte?
K47

12

Embora as respostas fornecidas estejam corretas, elas modificam o quadro de dados inicial, o que nem sempre é desejável (e, dado o OP solicitar exemplos "usando apply", pode ser que eles desejem uma versão que retorne um novo quadro de dados, como applyfaz).

Isso é possível usando assign: é válido para assigncolunas existentes, como a documentação declara (a ênfase é minha):

Atribua novas colunas a um DataFrame.

Retorna um novo objeto com todas as colunas originais, além das novas. As colunas existentes que são redesignadas serão substituídas .

Em resumo:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

Observe que a função passará por todo o quadro de dados, não apenas pela coluna que você deseja modificar, portanto, será necessário selecionar a coluna certa em sua lambda.


9

Se você está realmente preocupado com a velocidade de execução da sua função de aplicação e possui um enorme conjunto de dados para trabalhar, pode usar o swifter para acelerar a execução, eis um exemplo para o swifter no pandas dataframe:

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

Isso permitirá que todos os núcleos da CPU calculem o resultado, portanto, será muito mais rápido que as funções de aplicação normais. Tente e me avise se ele se tornar útil para você.


1

Deixe-me tentar um cálculo complexo usando datetime e considerando nulos ou espaços vazios. Estou reduzindo 30 anos em uma coluna datetime e usando o applymétodo e também lambdaconvertendo o formato datetime. A linha if x != '' else xcuidará de todos os espaços vazios ou nulos de acordo.

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.