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.