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


Respuestas:


578

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()

Por ejemplo:

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()es un poco más lento, pero por supuesto, tiene información adicional: la cantidad de NaNs.


1
Gracias por los puntos de referencia de tiempo. Es sorprendente que pandasno tenga una función incorporada para esto. Es cierto de la publicación de @ JGreenwell que df.describe()puede hacer esto, pero no tiene una función directa.
hlin117

2
Acabo de cronometrar df.describe()(sin encontrar NaNs). Con una matriz de 1000 x 1000, una sola llamada toma 1.15 segundos.
hlin117

3
: 1, también, df.isnull().values.sum()es un poco más rápido quedf.isnull().values.flatten().sum()
Cero

Ah, buen truco @JohnGalt: cambiaré mi solución para eliminar el .flatten()para publicar. Gracias.
S Anand

66
No lo intentaste df.isnull().values.any(), para mí es más rápido que los demás.
CK1

178

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 ve así:

          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()- Esto devuelve un valor booleano

Usted sabe 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 hace 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 sonTrue

> df.isnull().any().any()
True
  • Opción 2 : df.isnull().sum().sum()- Esto devuelve un 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

¿Por qué no usar en .any(axis=None)lugar de .any().any()?
Georgy

57

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

nan_rows = df[df['name column'].isnull()]

17
Para averiguar qué filas no tienen NaNs en una columna específica: non_nan_rows = df[df['name column'].notnull()].
Elmex80s

49

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

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

O si necesita extraer estas filas y examinarlas:

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

44
Creo que no necesitamos el segundo T
YOBEN_S


18

Agregando a Hobs una respuesta brillante, soy muy nuevo en Python y Pandas, así que por favor 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 transposición especificando el eje de any () como 1 para verificar si 'True' está presente en las filas.


¡Esto elimina dos transposiciones! Me encanta tu any(axis=1)simplificación concisa .
encimeras

12

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 utiles

numpy.isnan
Otra opción eficaz 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 puedes llamar de forma iterativa Series.hasnans. Por ejemplo, para verificar si una sola columna tiene NaNs,

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

Esto es realmente muy rápido.


10

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

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

versión pandas '0.19.2' y '0.20.2'


66
Esta respuesta es incorrecta. Pandas Series tiene este atributo pero DataFrames no. Si df = DataFrame([1,None], columns=['foo']), entonces df.hasnansarrojará un AttributeError, pero df.foo.hasnansregresará True.
Nathan Thompson

7

Como pandastiene que descubrir 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 el DataFrame. Cf. Código fuente de pandas . No he comparado 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

deje que dfsea ​​el nombre del Pandas DataFrame y cualquier valor que numpy.nansea ​​un valor nulo.

  1. Si desea ver qué columnas tienen valores nulos y cuáles no (solo Verdadero y Falso)
    df.isnull().any()
  2. Si desea ver solo las columnas que tienen valores 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 visualmente sus datos:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])

Si desea ver el recuento de nulos en cada columna ... Eso parece una locura, ¿por qué no simplemente hacerlo df.isna().sum()?
AMC

4

Simplemente usando math.isnan (x) , Devuelve True si x es un NaN (no un número) y False de lo contrario.


44
No creo math.isnan(x)que vaya a funcionar cuando se xtrata de un DataFrame. En su lugar, obtienes un TypeError.
hlin117

¿Por qué usarías esto sobre alguna de las alternativas?
AMC

4
df.isnull().sum()

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


No, eso le dará una Serie que asigna nombres de columnas a su respectivo número de valores de NA.
AMC

Corregido, mi culpa: p
Adarsh ​​singh

3

Aquí hay otra forma interesante de encontrar nulo y reemplazarlo 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

3

He estado usando lo siguiente y escribí convertirlo en una cadena y verificar 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.


¿Hay alguna ventaja en usar esto pandas.isna()?
AMC

2

Lo mejor sería usar:

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

Aquí es por qué . Por isna()lo tanto, se utiliza 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 de panda 2D.


1

O puede usar .info()en DF:

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


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

Verificará para cada columna si contiene Nan o no.


¿Por qué usar esto sobre cualquiera de las soluciones integradas?
AMC

0

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

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

-1

No solo puede verificar si existe 'NaN', sino también obtener el porcentaje de 'NaN' en cada columna utilizando 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 podría 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.


Creo que esto es ineficiente. Las funciones integradas de los pandas son más ordenadas / concisas. Evita el desorden del cuaderno de ipython.
Koo

No tiene sentido usar esto sobre las soluciones integradas.
AMC
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.