Como verificar se algum valor é NaN em um DataFrame do Pandas

483

No Python Pandas, qual é a melhor maneira de verificar se um DataFrame possui um (ou mais) valores NaN?

Eu sei sobre a função pd.isnan, mas isso retorna um DataFrame de booleanos para cada elemento. Este post aqui também não responde exatamente à minha pergunta.

hlin117
fonte

Respostas:

578

A resposta de jwilner é imediata . Eu estava explorando para ver se havia uma opção mais rápida, pois, na minha experiência, a soma de matrizes simples é (estranhamente) mais rápida que a contagem. Este código parece mais rápido:

df.isnull().values.any()

Por exemplo:

In [2]: df = pd.DataFrame(np.random.randn(1000,1000))

In [3]: df[df > 0.9] = pd.np.nan

In [4]: %timeit df.isnull().any().any()
100 loops, best of 3: 14.7 ms per loop

In [5]: %timeit df.isnull().values.sum()
100 loops, best of 3: 2.15 ms per loop

In [6]: %timeit df.isnull().sum().sum()
100 loops, best of 3: 18 ms per loop

In [7]: %timeit df.isnull().values.any()
1000 loops, best of 3: 948 µs per loop

df.isnull().sum().sum()é um pouco mais lento, mas é claro, tem informações adicionais - o número de NaNs.

S Anand
fonte
1
Obrigado pelo tempo de referência. É surpreendente que pandasnão tenha uma função integrada para isso. É verdade no post de @ JGreenwell que df.describe()pode fazer isso, mas nenhuma função direta.
hlin117
2
Acabei de cronometrar df.describe()(sem encontrar NaNs). Com uma matriz de 1000 x 1000, uma única chamada leva 1,15 segundos.
hlin117
3
: 1, também, df.isnull().values.sum()é um pouco mais rápido quedf.isnull().values.flatten().sum()
Zero
Ah, boa pegada @JohnGalt - vou mudar minha solução para remover a .flatten()cópia. Obrigado.
S Anand
6
Você não tentou df.isnull().values.any(), para mim é mais rápido que os outros.
CK1
178

Você tem algumas opções.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan

Agora, o quadro de dados se parece com isso:

          0         1         2         3         4         5
0  0.520113  0.884000  1.260966 -0.236597  0.312972 -0.196281
1 -0.837552       NaN  0.143017  0.862355  0.346550  0.842952
2 -0.452595       NaN -0.420790  0.456215  1.203459  0.527425
3  0.317503 -0.917042  1.780938 -1.584102  0.432745  0.389797
4 -0.722852  1.704820 -0.113821 -1.466458  0.083002  0.011722
5 -0.622851 -0.251935 -1.498837       NaN  1.098323  0.273814
6  0.329585  0.075312 -0.690209 -3.807924  0.489317 -0.841368
7 -1.123433 -1.187496  1.868894 -2.046456 -0.949718       NaN
8  1.133880 -0.110447  0.050385 -1.158387  0.188222       NaN
9 -0.513741  1.196259  0.704537  0.982395 -0.585040 -1.693810
  • Opção 1 : df.isnull().any().any()- Isso retorna um valor booleano

Você sabe o isnull()que retornaria um quadro de dados como este:

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

Se você fizer isso df.isnull().any(), poderá encontrar apenas as colunas que possuem NaNvalores:

0    False
1     True
2    False
3     True
4    False
5     True
dtype: bool

Mais um .any()lhe dirá se alguma das opções acima éTrue

> df.isnull().any().any()
True
  • Opção 2 : df.isnull().sum().sum()- Isso retorna um número inteiro do número total de NaNvalores:

Isso funciona da mesma maneira que o .any().any()faz, fornecendo primeiro um somatório do número de NaNvalores em uma coluna e depois o somatório desses valores:

df.isnull().sum()
0    0
1    2
2    0
3    1
4    0
5    2
dtype: int64

Por fim, para obter o número total de valores de NaN no DataFrame:

df.isnull().sum().sum()
5
Andy
fonte
Por que não usar em .any(axis=None)vez de .any().any()?
Georgy
57

Para descobrir quais linhas têm NaNs em uma coluna específica:

nan_rows = df[df['name column'].isnull()]
Ihor Ivasiuk
fonte
17
Para saber quais linhas não têm NaNs em uma coluna específica: non_nan_rows = df[df['name column'].notnull()].
Elmex80s
49

Se você precisar saber quantas linhas existem com "um ou mais NaNs":

df.isnull().T.any().T.sum()

Ou se você precisar extrair essas linhas e examiná-las:

nan_rows = df[df.isnull().T.any().T]
fogão
fonte
4
Acho que não precisamos do 2º T
YOBEN_S
38

df.isnull().any().any() deve fazê-lo.

jwilner
fonte
18

Acrescentando à resposta brilhante do Hobs, sou muito novo no Python e no Pandas, portanto, aponte se estou errado.

Para descobrir quais linhas têm NaNs:

nan_rows = df[df.isnull().any(1)]

executaria a mesma operação sem a necessidade de transposição especificando o eixo de any () como 1 para verificar se 'True' está presente nas linhas.

Ankit
fonte
Isso se livra de duas transposições! Ame sua any(axis=1)simplificação concisa .
hobs
12

Sintaxe super simples: df.isna().any(axis=None)

A partir da v0.23.2 , você pode usar DataFrame.isna+ DataFrame.any(axis=None)onde axis=Noneespecifica a redução lógica em todo o DataFrame.

# Setup
df = pd.DataFrame({'A': [1, 2, np.nan], 'B' : [np.nan, 4, 5]})
df
     A    B
0  1.0  NaN
1  2.0  4.0
2  NaN  5.0

df.isna()

       A      B
0  False   True
1  False  False
2   True  False

df.isna().any(axis=None)
# True

Alternativas úteis

numpy.isnan
Outra opção de desempenho se você estiver executando versões mais antigas de pandas.

np.isnan(df.values)

array([[False,  True],
       [False, False],
       [ True, False]])

np.isnan(df.values).any()
# True

Como alternativa, verifique a soma:

np.isnan(df.values).sum()
# 2

np.isnan(df.values).sum() > 0
# True

Series.hasnans
Você também pode ligar iterativamente Series.hasnans. Por exemplo, para verificar se uma única coluna possui NaNs,

df['A'].hasnans
# True

E para verificar se alguma coluna possui NaNs, você pode usar uma compreensão com any(que é uma operação em curto-circuito).

any(df[c].hasnans for c in df)
# True

Isso é realmente muito rápido.

cs95
fonte
10

Como nenhum deles mencionou, existe apenas outra variável chamada hasnans.

df[i].hasnansserá exibido Truese um ou mais dos valores da série pandas for NaN, Falsese não. Note que não é uma função.

versão pandas '0.19.2' e '0.20.2'

yazhi
fonte
6
Esta resposta está incorreta. A série Pandas tem esse atributo, mas os DataFrames não. Se df = DataFrame([1,None], columns=['foo']), então df.hasnanslançará um AttributeError, mas df.foo.hasnansretornará True.
21417 Nathan Thompson
7

Como ele pandastem que descobrir isso DataFrame.dropna(), dei uma olhada para ver como eles o implementam e descobri que eles utilizavam DataFrame.count(), o que conta todos os valores não nulos no DataFrame. Cf. código fonte do pandas . Não avaliei essa técnica, mas acho que os autores da biblioteca provavelmente fizeram uma escolha sábia de como fazê-lo.

Marshall Farrier
fonte
6

deixe dfser o nome do Pandas trama de dados e qualquer valor que é numpy.nané um valor nulo.

  1. Se você deseja ver quais colunas têm nulos e quais não (apenas Verdadeiro e Falso)
    df.isnull().any()
  2. Se você deseja ver apenas as colunas que possuem nulos
    df.loc[:, df.isnull().any()].columns
  3. Se você deseja ver a contagem de nulos em todas as colunas
    df.isna().sum()
  4. Se você deseja ver a porcentagem de nulos em todas as colunas

    df.isna().sum()/(len(df))*100
  5. Se você deseja ver a porcentagem de nulos nas colunas apenas com nulos: df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

EDIT 1:

Se você deseja ver onde seus dados estão ausentes visualmente:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])
Naveen Kumar
fonte
Se você deseja ver a contagem de nulos em todas as colunas ... Isso parece loucura, por que não fazer df.isna().sum()?
AMC
4

Apenas usando math.isnan (x) , Return True se x for um NaN (não um número) e False caso contrário.

江南 消夏
fonte
4
Eu não acho que math.isnan(x)vai funcionar quando xé um DataFrame. Você recebe um TypeError.
precisa saber é o seguinte
Por que você usaria isso sobre qualquer uma das alternativas?
AMC
4
df.isnull().sum()

Isso fornecerá a contagem de todos os valores de NaN presentes nos respectivos volumes do DataFrame.

Adarsh ​​singh
fonte
Não, isso fornecerá uma série que mapeia os nomes das colunas para o respectivo número de valores de NA.
AMC
Corrigido, minha culpa: p
Adarsh ​​singh
3

Aqui está outra maneira interessante de encontrar nulo e substituir por um valor calculado

    #Creating the DataFrame

    testdf = pd.DataFrame({'Tenure':[1,2,3,4,5],'Monthly':[10,20,30,40,50],'Yearly':[10,40,np.nan,np.nan,250]})
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3     NaN
    3       40       4     NaN
    4       50       5   250.0

    #Identifying the rows with empty columns
    nan_rows = testdf2[testdf2['Yearly'].isnull()]
    >>> nan_rows
       Monthly  Tenure  Yearly
    2       30       3     NaN
    3       40       4     NaN

    #Getting the rows# into a list
    >>> index = list(nan_rows.index)
    >>> index
    [2, 3]

    # Replacing null values with calculated value
    >>> for i in index:
        testdf2['Yearly'][i] = testdf2['Monthly'][i] * testdf2['Tenure'][i]
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3    90.0
    3       40       4   160.0
    4       50       5   250.0
Jagannath Banerjee
fonte
3

Eu tenho usado o seguinte e digite convertê-lo em uma seqüência de caracteres e verificando o valor nan

   (str(df.at[index, 'column']) == 'nan')

Isso me permite verificar o valor específico de uma série e não apenas retornar se isso estiver contido em algum lugar da série.

Peter Thomas
fonte
Existe alguma vantagem em usar isso de novo pandas.isna()?
AMC
2

O melhor seria usar:

df.isna().any().any()

Aqui está o porquê . Então, isna()é usado para definir isnull(), mas ambos são idênticos, é claro.

Isso é ainda mais rápido que a resposta aceita e abrange todas as matrizes 2D de panda.

prosti
fonte
1

Ou você pode usar .info()no DFtais como:

df.info(null_counts=True) que retorna o número de linhas não-nulas em colunas como:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 3276314 entries, 0 to 3276313
Data columns (total 10 columns):
n_matches                          3276314 non-null int64
avg_pic_distance                   3276314 non-null float64
Jan Sila
fonte
1
import missingno as msno
msno.matrix(df)  # just to visualize. no missing value.

insira a descrição da imagem aqui

ikbel benabdessamad
fonte
0
df.apply(axis=0, func=lambda x : any(pd.isnull(x)))

Irá verificar se cada coluna contém Nan ou não.

Alex Dlikman
fonte
Por que usar isso em qualquer uma das soluções integradas?
AMC
0

Podemos ver os valores nulos presentes no conjunto de dados, gerando um mapa de calor usando o mapa de calor do módulo marítimo

import pandas as pd
import seaborn as sns
dataset=pd.read_csv('train.csv')
sns.heatmap(dataset.isnull(),cbar=False)
aditya
fonte
-1

Você não apenas pode verificar se existe algum 'NaN', mas também obter a porcentagem de 'NaNs em cada coluna usando o seguinte,

df = pd.DataFrame({'col1':[1,2,3,4,5],'col2':[6,np.nan,8,9,10]})  
df  

   col1 col2  
0   1   6.0  
1   2   NaN  
2   3   8.0  
3   4   9.0  
4   5   10.0  


df.isnull().sum()/len(df)  
col1    0.0  
col2    0.2  
dtype: float64
Nizam
fonte
-2

Dependendo do tipo de dados com o qual você está lidando, você também pode obter as contagens de valores de cada coluna enquanto executa sua EDA configurando dropna como False.

for col in df:
   print df[col].value_counts(dropna=False)

Funciona bem para variáveis ​​categóricas, não tanto quando você tem muitos valores exclusivos.

andrewwowens
fonte
Eu acho que isso é ineficiente. As funções internas dos pandas são mais organizadas / concisas. Evita a bagunça do notebook ipython.
Koo
Não faz sentido usá-lo nas soluções integradas.
AMC