Cómo verificar si algún valor es NaN en un DataFrame de Pandas

569

En Python Pandas, ¿cuál es la mejor manera de verificar si un DataFrame tiene uno (o más) valores NaN?

Conozco la función pd.isnan, pero esto devuelve un DataFrame de valores booleanos para cada elemento. Esta publicación de aquí tampoco responde exactamente a mi pregunta.

1
695

La respuesta de jwilner es acertada . Estaba explorando para ver si hay una opción más rápida, ya que en mi experiencia, sumar matrices planas es (extrañamente) más rápido que contar. Este código parece más rápido:

df.isnull().values.any()

ingrese la descripción de la imagen aquí

import numpy as np
import pandas as pd
import perfplot


def setup(n):
    df = pd.DataFrame(np.random.randn(n))
    df[df > 0.9] = np.nan
    return df


def isnull_any(df):
    return df.isnull().any()


def isnull_values_sum(df):
    return df.isnull().values.sum() > 0


def isnull_sum(df):
    return df.isnull().sum() > 0


def isnull_values_any(df):
    return df.isnull().values.any()


perfplot.save(
    "out.png",
    setup=setup,
    kernels=[isnull_any, isnull_values_sum, isnull_sum, isnull_values_any],
    n_range=[2 ** k for k in range(25)],
)

df.isnull().sum().sum()es un poco más lento, pero, por supuesto, tiene información adicional: el número de NaNs.

9
  • 1
    Gracias por los puntos de referencia de tiempo. Es sorprendente que pandasno tenga una función incorporada para esto. Es cierto desde la publicación de @ JGreenwell que df.describe()puede hacer esto, pero no tiene una función directa. hlin117 9 de abril de 2015 a las 6:37
  • 2
    Solo cronometré df.describe()(sin encontrar NaNs). Con una matriz de 1000 x 1000, una sola llamada tarda 1,15 segundos. hlin117 9 de abril de 2015 a las 6:43
  • 3
    : 1, además, df.isnull().values.sum()es un poco más rápido quedf.isnull().values.flatten().sum()Zero 12/04/15 a las 21:02
  • Ah, buen comentario @JohnGalt: cambiaré mi solución para eliminar la .flatten()publicación. Gracias. S Anand 13/04/2015 a las 1:25
  • 8
    No lo intentaste df.isnull().values.any(), para mí es más rápido que los demás. CK1 15/07/2015 a las 15:28
200

Tienes unas cuantas opciones.

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

Ahora el marco de datos se parece a esto:

          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
  • Opción 1 : df.isnull().any().any()devuelve un valor booleano.

Sabes isnull()cuál devolvería un marco de datos 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

Si lo logra df.isnull().any(), puede encontrar solo las columnas que tienen NaNvalores:

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

Uno más .any()le dirá si alguno de los anteriores esTrue

> df.isnull().any().any()
True
  • Opción 2 : df.isnull().sum().sum()devuelve un número entero del número total de NaNvalores:

Esto funciona de la misma manera que lo .any().any()hace, dando primero una suma del número de NaNvalores en una columna, luego la suma de esos valores:

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

Finalmente, para obtener el número total de valores de NaN en el DataFrame:

df.isnull().sum().sum()
5
1
  • 2
    ¿Por qué no usar en .any(axis=None)lugar de .any().any()? Georgy 13/01/20 a las 18:59
76

Para averiguar qué filas tienen NaN en una columna específica:

nan_rows = df[df['name column'].isnull()]
1
  • 19
    Para averiguar qué filas no tienen NaNs en una columna específica: non_nan_rows = df[df['name column'].notnull()]. Elmex80s 27 nov 2017 a las 10:00
57

Si necesita saber cuántas filas hay con "una o más NaNs":

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

O si necesita sacar estas filas y examinarlas:

nan_rows = df[df.isnull().T.any()]
0
42

df.isnull().any().any() Deberías hacerlo.

0
20

Agregando a la brillante respuesta de Hobs, soy muy nuevo en Python y Pandas, así que señale si estoy equivocado.

Para averiguar qué filas tienen NaN:

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

realizaría la misma operación sin la necesidad de transponer especificando el eje de any () como 1 para verificar si 'Verdadero' está presente en las filas.

1
  • ¡Esto elimina dos transposiciones! Amo tu any(axis=1)simplificación concisa . hobs 9/09/18 a las 22:22
20

Sintaxis súper simple: df.isna().any(axis=None)

A partir de v0.23.2 , puede usar DataFrame.isna+ DataFrame.any(axis=None)donde axis=Noneespecifica la reducción lógica en todo el 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 útiles

numpy.isnan
Otra opción de rendimiento si está ejecutando versiones anteriores de pandas.

np.isnan(df.values)

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

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

Alternativamente, verifique la suma:

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

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

Series.hasnans
También puede llamar iterativamente Series.hasnans. Por ejemplo, para comprobar si una sola columna tiene NaN,

df['A'].hasnans
# True

Y para verificar si alguna columna tiene NaN, puede usar una comprensión con any(que es una operación de cortocircuito).

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

En realidad, esto es muy rápido.

12

dejar que dfsea el nombre de la trama de datos pandas y cualquier valor que es numpy.nanun valor nulo.

  1. Si desea ver qué columnas tienen nulos y cuáles no (solo Verdadero y Falso)

    df.isnull().any()
    
  2. Si desea ver solo las columnas que tienen nulos

    df.loc[:, df.isnull().any()].columns
    
  3. Si desea ver el recuento de nulos en cada columna

    df.isna().sum()
    
  4. Si desea ver el porcentaje de nulos en cada columna

    df.isna().sum()/(len(df))*100
    
  5. Si desea ver el porcentaje de nulos en columnas solo con nulos:

df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

EDITAR 1:

Si desea ver dónde faltan sus datos visualmente:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])
1
  • Si quieres ver el recuento de nulos en cada columna ... Parece una locura, ¿por qué no hacerlo df.isna().sum()? AMC 16 feb.20 a las 4:09
10

Como ninguno lo ha mencionado, solo hay otra variable llamada hasnans.

df[i].hasnanssaldrá a Truesi uno o más de los valores de la serie pandas es NaN, en Falsecaso contrario. Tenga en cuenta que no es una función.

pandas versión '0.19.2' y '0.20.2'

1
  • 6
    Esta respuesta es incorrecta. La serie Pandas tiene este atributo, pero los DataFrames no. Si df = DataFrame([1,None], columns=['foo']), entonces df.hasnanslanzará un AttributeError, pero df.foo.hasnansvolverá True. Nathan Thompson 11/10/2017 a las 22:27
7

Como pandastiene que averiguar esto DataFrame.dropna(), eché un vistazo para ver cómo lo implementan y descubrí que hicieron uso de DataFrame.count(), que cuenta todos los valores no nulos en DataFrame. Cf. código fuente de pandas . No he evaluado esta técnica, pero creo que es probable que los autores de la biblioteca hayan tomado una decisión acertada sobre cómo hacerlo.

6
df.isnull().sum()

Esto le dará el recuento de todos los valores de NaN presentes en las respectivas columnas del DataFrame.

2
  • No, eso le dará una serie que asigna los nombres de las columnas a su número respectivo de valores NA. AMC 16 feb.20 a las 4:11
  • Corregido, culpa mía: pAdarsh singh 21/02/20 a las 5:39
5

He estado usando lo siguiente y el tipo de conversión a una cadena y comprobando el valor nan

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

Esto me permite verificar un valor específico en una serie y no solo regresar si está contenido en algún lugar dentro de la serie.

2
  • 1
    ¿Hay alguna ventaja en usar esto pandas.isna()? AMC 16 feb.20 a las 4:10
  • Esto permite verificar un solo campo. Álvaro 8 de julio a las 16:50
4

Podemos ver los valores nulos presentes en el conjunto de datos generando un mapa de calor usando el mapa de calor del módulo seaborn

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

Simplemente usando math.isnan (x) , devuelve True si x es un NaN (no un número) y False en caso contrario.

2
  • 4
    No creo math.isnan(x)que vaya a funcionar cuando xsea ​​un DataFrame. En su lugar, obtienes un TypeError. hlin117 4/11/2017 a las 19:56
  • ¿Por qué usarías esto en lugar de cualquiera de las alternativas? AMC 16 feb.20 a las 4:05
3

Aquí hay otra forma interesante de encontrar nulos y reemplazarlos con un 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
2

Lo mejor sería utilizar:

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

He aquí por qué . Así isna()se usa para definir isnull(), pero ambos son idénticos, por supuesto.

Esto es incluso más rápido que la respuesta aceptada y cubre todas las matrices panda 2D.

1

O puede usar .info()en DFtales como:

df.info(null_counts=True) que devuelve el número de filas no nulas en columnas 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
1
import missingno as msno
msno.matrix(df)  # just to visualize. no missing value.

ingrese la descripción de la imagen aquí

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

Verificará cada columna si contiene Nan o no.

1
  • ¿Por qué usar esto sobre cualquiera de las soluciones integradas? AMC 16 feb.20 a las 4:12
0

Para hacer esto podemos usar la declaración df.isna().any(). Esto verificará todas nuestras columnas y devolverá Truesi hay valores perdidos o NaNs, o Falsesi no hay valores perdidos.

-1

No solo puede verificar si existe algún 'NaN', sino también obtener el porcentaje de 'NaN en cada columna usando lo siguiente,

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
-2

Dependiendo del tipo de datos con los que esté tratando, también puede obtener los recuentos de valores de cada columna mientras realiza su EDA configurando dropna en False.

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

Funciona bien para variables categóricas, no tanto cuando tiene muchos valores únicos.

1
  • Creo que esto es ineficaz. Las funciones integradas de los pandas son más ordenadas / concisas. Evita el desorden del cuaderno ipython. Koo 10/04/19 a las 17:15