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
Comenzando con pandas
¿Qué es pandas?
Series e Indexación y selección de datos
De paneles de datos al DataFrame
Indexado y manejo de archivos CSV
Conexión con bases de datos tipo SQL
Ventajas y desventajas de los formatos de importar y guardado
Funcionalidades básicas y esenciales de pandas
Formatos de lectura para cargar y guardar DataFrames
Tipos de Variables que componen un data frame
Estructuras de dataframes en detalle
Borrar filas, columnas y copiar información
Aplicando pandas
Funciones matemáticas
Funciones más complejas y lambdas
Múltiples índices
Cómo trabajar con variables tipo texto en Pandas
Concatenación de DataFrames: concat y append
Merge de DataFrames
¿Cómo lidiar con datos faltantes en tus DataFrames?
Group by
Cómo lidiar con datos duplicados en Pandas
Aggregation y groupby
Group By: extraer valor con variables categóricas
Tablas dinámicas con Pivot Table
Series de Tiempo
Series de Tiempo: variables nulas
Visualización y graficación de datos
Contenido extra
Iniciando una rutina típica de manejo de datos
Preprocesamiento de datos: terminando de preparar y limpiar los datasets
Análisis de datos
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
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
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.