Como posso substituir todos os valores de NaN por zeros na coluna de um dataframe do pandas


457

Eu tenho um quadro de dados como abaixo

      itm Date                  Amount 
67    420 2012-09-30 00:00:00   65211
68    421 2012-09-09 00:00:00   29424
69    421 2012-09-16 00:00:00   29877
70    421 2012-09-23 00:00:00   30990
71    421 2012-09-30 00:00:00   61303
72    485 2012-09-09 00:00:00   71781
73    485 2012-09-16 00:00:00     NaN
74    485 2012-09-23 00:00:00   11072
75    485 2012-09-30 00:00:00  113702
76    489 2012-09-09 00:00:00   64731
77    489 2012-09-16 00:00:00     NaN

Quando tento aplicar uma função na coluna Valor, recebo o seguinte erro.

ValueError: cannot convert float NaN to integer

Eu tentei aplicar uma função usando .isnan do módulo de matemática Eu tentei o atributo .replace do pandas Eu tentei o atributo de dados .sparse do pandas 0.9 Eu também tentei se NaN == NaN em uma função. Também observei este artigo. Como substituo valores NA por zeros em um dataframe R? enquanto olha para alguns outros artigos. Todos os métodos que tentei não funcionaram ou não reconhecem o NaN. Quaisquer dicas ou soluções serão apreciadas.


O único problema é df.fill.na () não funciona se o quadro de dados no qual você está aplicando é resampled ou foram cortados através da função loc
Príncipe Agarwal

Respostas:


754

Eu acredito DataFrame.fillna()que fará isso por você.

Link para o Documentos para um quadro de dados e para uma série .

Exemplo:

In [7]: df
Out[7]: 
          0         1
0       NaN       NaN
1 -0.494375  0.570994
2       NaN       NaN
3  1.876360 -0.229738
4       NaN       NaN

In [8]: df.fillna(0)
Out[8]: 
          0         1
0  0.000000  0.000000
1 -0.494375  0.570994
2  0.000000  0.000000
3  1.876360 -0.229738
4  0.000000  0.000000

Para preencher os NaNs em apenas uma coluna, selecione apenas essa coluna. neste caso, estou usando inplace = True para realmente alterar o conteúdo do df.

In [12]: df[1].fillna(0, inplace=True)
Out[12]: 
0    0.000000
1    0.570994
2    0.000000
3   -0.229738
4    0.000000
Name: 1

In [13]: df
Out[13]: 
          0         1
0       NaN  0.000000
1 -0.494375  0.570994
2       NaN  0.000000
3  1.876360 -0.229738
4       NaN  0.000000

EDITAR:

Para evitar a SettingWithCopyWarning, use a funcionalidade específica da coluna integrada:

df.fillna({1:0}, inplace=True)

1
É garantido que df[1]é uma visualização e não uma cópia do DF original? Obviamente, se houver uma situação rara em que seja uma cópia, isso causaria um bug super problemático. Existe uma declaração clara sobre isso na documentação dos pandas?
max

@Max ver isso, pode abordar sua pergunta: stackoverflow.com/questions/23296282/...
Aman

Obrigado. Meu entendimento está correto de que, nessa resposta, um "indexador que define" é a operação de indexação mais externa (executada imediatamente antes da atribuição. Portanto, qualquer atribuição que use apenas um único indexador é garantida e segura, tornando seu código seguro?
max

1
Por que isso não está funcionando para mim? consulte: stackoverflow.com/questions/39452095/how-to-fillna-with-value-0
displayname

1
o último exemplo lança um SettingWithCopyWarning
Sip

124

Não é garantido que a fatia retorne uma visualização ou uma cópia. Você pode fazer

df['column'] = df['column'].fillna(value)

14
Acabei de descobrir o problema "inplace = True". Esta resposta evita o problema e acho que é a solução mais limpa apresentada.
TimCera #

48

Você pode usar replacepara alterar NaNpara 0:

import pandas as pd
import numpy as np

# for column
df['column'] = df['column'].replace(np.nan, 0)

# for whole dataframe
df = df.replace(np.nan, 0)

# inplace
df.replace(np.nan, 0, inplace=True)

Será que vai substituir apenas NaN? ou também substituirá o valor onde NAou NaNcomo df.fillna(0)? Estou procurando uma solução que substitua apenas o valor onde existe NaNe nãoNA
Shyam Bhimani 09/01

1
@ShyamBhimani ele deve substituir apenas NaNvalores ie, onde np.isnané True
Anton Protopopov 10/01

23

Eu só queria fornecer um pouco de atualização / caso especial, pois parece que as pessoas ainda vêm aqui. Se você estiver usando um índice múltiplo ou usando um slicer de índice, a opção inplace = True pode não ser suficiente para atualizar a fatia que você escolheu. Por exemplo, em um multi-índice de nível 2x2, isso não altera nenhum valor (a partir dos pandas 0,15):

idx = pd.IndexSlice
df.loc[idx[:,mask_1],idx[mask_2,:]].fillna(value=0,inplace=True)

O "problema" é que o encadeamento interrompe a capacidade de preenchimento para atualizar o quadro de dados original. Coloquei "problema" entre aspas porque existem boas razões para as decisões de design que levaram a não interpretar essas cadeias em determinadas situações. Além disso, este é um exemplo complexo (embora eu realmente tenha encontrado isso), mas o mesmo pode se aplicar a menos níveis de índices, dependendo de como você fatia.

A solução é DataFrame.update:

df.update(df.loc[idx[:,mask_1],idx[[mask_2],:]].fillna(value=0))

É uma linha, lê razoavelmente bem (mais ou menos) e elimina qualquer confusão desnecessária com variáveis ​​ou loops intermediários, permitindo aplicar fillna a qualquer fatia de vários níveis que você quiser!

Se alguém puder encontrar lugares em que isso não funcione, poste nos comentários. Estou brincando com ele e olhando a fonte e parece resolver pelo menos meus problemas de fatia de vários índices.


21

O código abaixo funcionou para mim.

import pandas

df = pandas.read_csv('somefile.txt')

df = df.fillna(0)

7

Maneira fácil de preencher os valores ausentes: -

preenchimento de colunas de string: quando as colunas de string têm valores ausentes e valores de NaN.

df['string column name'].fillna(df['string column name'].mode().values[0], inplace = True)

preenchimento de colunas numéricas: quando as colunas numéricas têm valores ausentes e NaN.

df['numeric column name'].fillna(df['numeric column name'].mean(), inplace = True)

preenchendo NaN com zero:

df['column name'].fillna(0, inplace = True)

5

Você também pode usar dicionários para preencher os valores de NaN das colunas específicas no DataFrame, em vez de preencher todo o DF com algum valor.

import pandas as pd

df = pd.read_excel('example.xlsx')
df.fillna( {
        'column1': 'Write your values here',
        'column2': 'Write your values here',
        'column3': 'Write your values here',
        'column4': 'Write your values here',
        .
        .
        .
        'column-n': 'Write your values here'} , inplace=True)

Esta é a solução pretendida pelo desenvolvedor para a pergunta do OP.
johnDanger

4

insira a descrição da imagem aqui

Considerando que a coluna específica Amountna tabela acima é do tipo inteiro. O seguinte seria uma solução:

df['Amount'] = df.Amount.fillna(0).astype(int)

Da mesma forma, você pode preenchê-lo com vários tipos de dados float, strcomo etc.

Em particular, eu consideraria o tipo de dados para comparar vários valores da mesma coluna.


2

Para substituir um valor em pandas

df['column_name'].fillna(value_to_be_replaced,inplace=True)

se inplace = False, em vez de atualizar o df (dataframe), ele retornará os valores modificados.


1

Se você quiser convertê-lo em um dataframe do pandas, também poderá fazer isso usando fillna.

import numpy as np
df=np.array([[1,2,3, np.nan]])

import pandas as pd
df=pd.DataFrame(df)
df.fillna(0)

Isso retornará o seguinte:

     0    1    2   3
0  1.0  2.0  3.0 NaN
>>> df.fillna(0)
     0    1    2    3
0  1.0  2.0  3.0  0.0

1

Existem duas opções disponíveis principalmente; em caso de imputação ou preenchimento de valores ausentes NaN / np.nan com apenas substituições numéricas (na (s) coluna (s):

df['Amount'].fillna(value=None, method= ,axis=1,) é suficiente:

A partir da documentação:

value: escalar, dict, Series ou DataFrame Valor a ser usado para preencher furos (por exemplo, 0), alternadamente um dict / Series / DataFrame de valores especificando qual valor usar para cada índice (para uma Série) ou coluna (para um DataFrame) . (os valores fora do dict / Series / DataFrame não serão preenchidos). Este valor não pode ser uma lista.

O que significa que 'strings' ou 'constantes' não são mais permitidas de serem imputadas.

Para imputações mais especializadas, use SimpleImputer () :

from sklearn.impute import SimpleImputer
si = SimpleImputer(strategy='constant', missing_values=np.nan, fill_value='Replacement_Value')
df[['Col-1', 'Col-2']] = si.fit_transform(X=df[['C-1', 'C-2']])

0

Para substituir nan em colunas diferentes por maneiras diferentes:

   replacement= {'column_A': 0, 'column_B': -999, 'column_C': -99999}
   df.fillna(value=replacement)
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.