¿Cómo lidiar con datos faltantes en tus DataFrames?

17/28

Lectura

Es muy común que nuestros DataFrames presenten datos faltantes, antes de empezar a procesar nuestros DataFrames veamos un poco en qué consisten los objetos NaN (Not a Number).

Importemos las librerías Pandas y NumPy para esto:

import numpy as np
import pandas as pd

Un número que no está definido usualmente se representa con el siguiente objeto:

np.nan
> nan

¡Este objeto tiene propiedades matemáticas! Al sumar un número, obtenemos como
respuesta el mismo NaN.

np.nan + 0
> nan
np.nan > 0
> False

La versión 1.0 de pandas incluye un nuevo objeto NA, que es mucho más
general pues, además de interactuar con números, también puede hacerlo con
cadenas de texto u otras variables como las de tipo booleano. Si quieres que
esta nueva definición esté incluida entre tus cálculos usa:

 pd.options.mode.use_inf_as_na = False

Al sumar NA a una cadena de texto, obtengo el mismo NA:

pd.NA +'Hola mundo'
> <NA>
pd.NA | False
> <NA>

A continuación, vamos a crear un DataFrame

df = pd.DataFrame(np.arange(0, 15).reshape(5, 3), columns=['a', 'b', 'c'])
df
a b c
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
4 12 13 14

Y vamos a añadir algunas variables no definidas:

df['d'] = np.nan
df['e'] = np.arange(15, 20)
df.loc[5,:] = pd.NA
df.loc[4,'a'] = pd.NA
df.loc[0,'d'] = 1
df.loc[5,'d'] = 10
df
a b c d e
0 0.0 1.0 2.0 1 15.0
1 3.0 4.0 5.0 nan 16.0
2 6.0 7.0 8.0 nan 17.0
3 9.0 10.0 11.0 nan 18.0
4 <NA> 13.0 14.0 nan 19.0
5 <NA> <NA> <NA> 10 <NA>

Para reconocer cuándo un objeto es nulo, simplemente usamos:

df.isnull()
a b c d e
0 0 0 0 0 0
1 0 0 0 1 0
2 0 0 0 1 0
3 0 0 0 1 0
4 1 0 0 1 0
5 1 1 1 0 1

En donde todas nuestras variables no definidas fueron marcadas con TRUE,
df.isna() también cumple esta función.

Conocer el número de variables nulas por columna puede hacerse juntando el comando anterior con la función de suma:

df.isnull().sum()
a 2
b 1
c 1
d 4
e 1

dtype: int64

Si lo que nos interesa es conocer el número de filas con elementos nulos, basta con usar axis=1:

df.isnull().sum(axis=1)
0 5
1 4
2 4
3 4
4 3
5 1

dtype: int64

O todos los elementos nulos de nuestro DataFrame:

df.isnull().sum().sum()

21

Reconocer estos elementos nos puede ayudar a filtrar en nuestro DataFrame, en
este caso, me gustaría filtrar por las variables no nulas de la columna ‘a’:

df[df['a'].notnull()]
a b c d e
0 0 1 2 1 15
1 3 4 5 nan 16
2 6 7 8 nan 17
3 9 10 11 nan 18

dropna es perfecto para eliminar rápidamente las filas con registros faltantes:

df.dropna()
a b c d e
0 0 1 2 1 15
df[['a']].dropna()
a
0 0
1 3
2 6
3 9

Ya que hemos visto cómo funcionan las variables nulas, veamos cómo lidiar con
ellas. Usando la función fillna podremos reemplazarlas por el valor que
queramos, en este caso 0.

df.fillna(0)
a b c d e
0 0 1 2 1 15
1 3 4 5 0 16
2 6 7 8 0 17
3 9 10 11 0 18
4 0 13 14 0 19
5 0 0 0 10 0

Si quisiéramos remplazar con el valor siguiente usamos
method='ffill':

df.fillna(method='ffill')
a b c d e
0 0 1 2 1 15
1 3 4 5 1 16
2 6 7 8 1 17
3 9 10 11 1 18
4 9 13 14 1 19
5 9 13 14 10 19

Si quisiéramos remplazar con el valor previo usamos
method='bfill':

df.fillna(method='bfill')
a b c d e
0 0.0 1.0 2.0 1 15.0
1 3.0 4.0 5.0 10 16.0
2 6.0 7.0 8.0 10 17.0
3 9.0 10.0 11.0 10 18.0
4 <NA> 13.0 14.0 10 19.0
5 <NA> <NA> <NA> 10 <NA>

El mismo ejercicio anterior se puede aplicar con las filas usando axis=1:

df.fillna(method='bfill',axis=1)
a b c d e
0 0 1 2 1 15.0
1 3 4 5 16 16.0
2 6 7 8 17 17.0
3 9 10 11 18 18.0
4 13 13 14 19 19.0
5 10 10 10 10 <NA>

Podemos usar también una serie para reemplazar los valores de una columna en específico, es importante que haya emparejamiento entre los índices:

fill = pd.Series([100, 101, 102])
fill
0 100
1 101
2 102

dtype: int64

df['d'] = df['d'].fillna(fill)
df['d'] 
0 1
1 101
2 102
3 nan
4 nan
5 10

Name: d, dtype: float64

df
a b c d e
0 0.0 1.0 2.0 1 15.0
1 3.0 4.0 5.0 101 16.0
2 6.0 7.0 8.0 102 17.0
3 9.0 10.0 11.0 nan 18.0
4 <NA> 13.0 14.0 nan 19.0
5 <NA> <NA> <NA> 10 <NA>

Una de las formas más usadas para reemplazar datos es usar el promedio de las columnas, esto se hace con la función mean. O si se quiere un mejor estimador, usamos median.

df.fillna(df.median())
a b c d e
0 0 1 2 1 15
1 3 4 5 101 16
2 6 7 8 102 17
3 9 10 11 55.5 18
4 4.5 13 14 55.5 19
5 4.5 7 8 10 17

Por último, Pandas también puede interpolar los valores faltantes calculando el valor que puede haber existido en el medio.

df_d = pd.concat([df[['d']], df[['d']].interpolate()],axis=1)
df_d.columns = ['d_antes','d_interpolado']
df_d
d_antes d_interpolado
0 1 1
1 101 101
2 102 102
3 nan 71.3333
4 nan 40.6667
5 10 10

Aportes 27

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

para que las funciones como .isnull() reconozcan los elementos <NA> se debe escribir:

pd.options.mode.use_inf_as_na = False

En la lectura esta = True

Excelente info. Pero solo una aclaración. Hay una parte del documento indica: " Si lo que nos interesa es conocer el número de filas con elementos nulos, basta con usar axis=1" y el código que indica es

df.notnull().sum(axis=1)

Con esto **NO **conocemos los elementos nulos, conocemos los elementos NO NULOS..

Es importante siempre considerar ambas alternativas, y no únicamente eliminar las columnas nulas, para nuestros modelos en algunas ocasiones es más útil saber que no existe un dado a no brindarle esa información. Es más relevante saber que no existe información en un punto a desconocerlo del todo

No sé por que al usar el nuevo objeto <NA>, al tratar de aplicar todas las funciones mencionadas no los modifica, a pesar de la línea:

pd.options.mode.use_inf_as_na =True

al parecer sigue considerandolos como objetos distintos nan de NA

Si suben, clases de lectura… deberían asegurarse que no haya errores al ejecutar…

En esta parte dice que obtener todos los elementos nulos, pero se estan obteniendo todos los elementos no nulos, debido a que se obtiene el total de elementos y se le restan los nulos

df.size-df.isnull().sum().sum()

Excelente información, todo muy claro y conciso

Hola a todos, tuve un problema con la interpolación, si alguno me pudiera ayudar sería excelente

La notebook está en : https://colab.research.google.com/drive/1ST9pv_PZ3vmwuOupWJbjgJ2pLdxyYyLk?usp=sharing

Entre más trabajo con pandas, más creo que lo difícil es no perderse entre tanto parentesis cuadrado

Explicación un poco mas detallada de los fill. Articulo Fills

Muy interesante la función de pandas que permite interpolar los datos faltantes para hacer un cálculo y poner el valor que pudo haber existido 😯

Quise utilizar df.fillna(method="ffill") para cambiar el valor hasta 2 pero no funciona. De donde sale el “valor siguiente”?

Interesante lectura, es usual encontrarse en datasets con valores no definidos, asi que es importante saber lidiar con ellos

Me parece o hay un error en la lectura?. Por ejemplo al ejecutar el codigo:

df.isnull().sum().sum() #9
df.notnull.sum().sum() #21

En la lectura, el resultado de esta linea, tiene un error
df.isnull().sum(axis=1)
lo que sale cuando la ejecutas es esto

0    0
1    1
2    1
3    1
4    2
5    4

seria el complemento de lo que aparece en la lectura

Una duda, alguien sabe porque para saber la cantidad de elementos no nulos ocupa:

df.size-df.isnull().sum().sum() # 21

Y no ocupa:

df.notnull().sum().sum() # 21

¿Hay alguna diferencia de porque elegir una forma respecto a la otra?
Gracias

✔️¡Excelente! Solo una aclaración.

En la parte que dice “todos los elementos nulos de nuestro DataFrame” y pone la siguiente línea:

df.size-df.isnull().sum().sum()

lo que en realidad está obteniendo son los ELEMENTOS NO NULOS. Si te das cuenta, está restando el tamaño del Data Frame con la cantidad de elementos nulos. Por lo tanto, obtienes los elementos no nulos. 😀

Creo que cuando dice todos los elementos nulos de nuestro DataFrame, trata de decir los elementos NO NULOS de nuestro DataFrame, porque con ese código podemos encontrar cuántos sí tienen algún valor no nulo.

Para obtener los nulos basta con colocar sólo

df.isnull().sum().sum()

He visto la documentación de Pandas y esta muy bien, ademas regalan un libro en PDF con ejemplos de código para descargar, os dejo el link https://pandas.pydata.org/

algo que noté con el metodo interpolate es que sólo funciona con valores nan, no con NA

Entendido, utilizar como NULL en Sql

Excelente hacerlo uno a uno

Esto está genial, es muy común trabajar con datos faltantes

Excelente para aplicarlo en análisis de la calidad de aire para aplicar datos interpolados o datos promedios, cuando se descargan los datos de los equipos de monitoreo y se presentan algunos datos NaN

¿Se podría pensar en la función de interpolación como principio de los sistemas de recomendaciones?.

Excelente y muy preciso con la informacion

interesante