¿Cómo limpiar datos en Python para aprendizaje automático?

Contenidos

Este post fue hecho público como parte del Blogatón de ciencia de datos

Introducción

Python es un lenguaje de programación fácil de aprender, lo que lo convierte en la opción preferida por los principiantes en ciencia de datos, análisis de datos y aprendizaje automático. Además cuenta con una gran comunidad de estudiantes en línea y excelentes bibliotecas centradas en datos.

Con tantos datos que se generan, es esencial que los datos que usamos para aplicaciones de ciencia de datos como el aprendizaje automático y el modelado predictivo estén limpios. Pero, ¿qué entendemos por datos limpios? ¿Y qué ensucia los datos en primer lugar?

Los datos sucios simplemente significan datos erróneos. La duplicación de registros, los datos incompletos o desactualizados y el análisis incorrecto pueden ensuciar los datos. Estos datos deben limpiarse. La limpieza de datos (o limpieza de datos) se refiere al procedimiento de «limpiar» estos datos sucios, identificando errores en los datos y después rectificándolos.

La limpieza de datos es un paso importante en un proyecto de aprendizaje automático, y cubriremos algunas técnicas básicas de limpieza de datos (en Python) en este post.

Limpieza de datos en Python

Aprenderemos más sobre la limpieza de datos en Python con la ayuda de un conjunto de datos de muestra. Usaremos el Conjunto de datos de vivienda rusa en Kaggle.

Comenzaremos importando las bibliotecas imprescindibles.

# import libraries
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

Descargue los datos y después léalos en un Pandas DataFrame usando la función read_csv () y especificando la ruta del archivo. Posteriormente, use el atributo de forma para verificar el número de filas y columnas en el conjunto de datos. El código para esto es el siguiente:

df = pd.read_csv('housing_data.csv')
df.shape

El conjunto de datos tiene 30 471 filas y 292 columnas.

Ahora separaremos las columnas numéricas de las columnas categóricas.

# select numerical columns
df_numeric = df.select_dtypes(include=[np.number])
numeric_cols = df_numeric.columns.values
# select non-numeric columns
df_non_numeric = df.select_dtypes(exclude=[np.number])
non_numeric_cols = df_non_numeric.columns.values

Ahora hemos terminado con los pasos preliminares. Ahora podemos pasar a la limpieza de datos. Comenzaremos identificando columnas que contienen valores faltantes e intentaremos corregirlos.

Valores faltantes

Comenzaremos calculando el porcentaje de valores que faltan en cada columna y después almacenando esta información en un DataFrame.

# % of values missing in each column
values_list = list()
cols_list = list()
for col in df.columns:
    pct_missing = np.mean(df[col].isnull())*100
    cols_list.append(col)
    values_list.append(pct_missing)
pct_missing_df = pd.DataFrame()
pct_missing_df['col'] = cols_list
pct_missing_df['pct_missing'] = values_list

El DataFrame pct_missing_df ahora contiene el porcentaje de valores perdidos en cada columna junto con los nombres de las columnas.

Además podemos crear una imagen a partir de esta información para una mejor comprensión usando el siguiente código:

pct_missing_df.loc[pct_missing_df.pct_missing > 0].plot(kind='bar', figsize=(12,8))
plt.show()

El resultado después de la ejecución de la línea de código anterior debería verse así:

datos faltantes limpiar datos

Es claro que a algunas columnas les faltan muy pocos valores, mientras que a otras columnas les falta un porcentaje sustancial de valores. Ahora arreglaremos estos valores faltantes.

Hay varias formas en las que podemos corregir estos valores perdidos. Algunos de ellos son»

Observaciones de caída

Una forma podría ser descartar aquellas observaciones que contengan algún valor nulo para cualquiera de las columnas. Esto funcionará cuando el porcentaje de valores perdidos en cada columna sea muy inferior. Eliminaremos las observaciones que contengan nulos en aquellas columnas que tengan menos del 0,5% de nulos. Estas columnas serían metro_min_walk, metro_km_walk, railroad_station_walk_km, railroad_station_walk_min e ID_railroad_station_walk.

less_missing_values_cols_list = list(pct_missing_df.loc[(pct_missing_df.pct_missing < 0.5) & (pct_missing_df.pct_missing > 0), 'col'].values)
df.dropna(subset=less_missing_values_cols_list, inplace=True)

Esto reducirá la cantidad de registros en nuestro conjunto de datos a 30,446 registros.

Borrar columnas (funciones)

Otra manera de abordar los valores perdidos en un conjunto de datos sería borrar aquellas columnas o características que tengan un porcentaje significativo de valores perdidos. Estas columnas no contienen mucha información y se pueden borrar por completo del conjunto de datos. En nuestro caso, eliminemos todas aquellas columnas a las que les faltan más del 40% de valores. Estas columnas serían build_year, state, hospital_beds_raion, cafe_sum_500_min_price_avg, cafe_sum_500_max_price_avg y cafe_avg_price_500.

# dropping columns with more than 40% null values
_40_pct_missing_cols_list = list(pct_missing_df.loc[pct_missing_df.pct_missing > 40, 'col'].values)
df.drop(columns=_40_pct_missing_cols_list, inplace=True)

La cantidad de características en nuestro conjunto de datos ahora es 286.

Imputar valores perdidos

Aún faltan datos en nuestro conjunto de datos. Ahora imputaremos los valores faltantes en cada columna numérica con el valor mediano de esa columna.

df_numeric = df.select_dtypes(include=[np.number])
numeric_cols = df_numeric.columns.values
for col in numeric_cols:
    missing = df[col].isnull()
    num_missing = np.sum(missing)
    if num_missing > 0:  # impute values only for columns that have missing values
        med = df[col].median() #impute with the median
        df[col] = df[col].fillna(med)

Los valores que faltan en las columnas numéricas ahora están corregidos. En el caso de columnas categóricas, reemplazaremos los valores perdidos con los valores de moda de esa columna.

df_non_numeric = df.select_dtypes(exclude=[np.number])
non_numeric_cols = df_non_numeric.columns.values
for col in non_numeric_cols:
    missing = df[col].isnull()
    num_missing = np.sum(missing)
    if num_missing > 0:  # impute values only for columns that have missing values
        mod = df[col].describe()['top'] # impute with the most frequently occuring value
        df[col] = df[col].fillna(mod)

Todos los valores faltantes en nuestro conjunto de datos ya se han tratado. Podemos verificar esto ejecutando el siguiente código:

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

Si la salida es cero, significa que ahora no quedan valores faltantes en nuestro conjunto de datos.

Además podemos reemplazar los valores que faltan con un valor particular (como -9999 o ‘faltante’) que indicará el hecho de que faltaban los datos en este lugar. Esto puede ser un sustituto de la imputación de valor perdido.

Valores atípicos

Un valor atípico es una observación inusual que se aleja de la mayoría de los datos. Los valores atípicos pueden afectar significativamente el rendimiento de un modelo de aprendizaje automático. Por eso, es esencial identificar los valores atípicos y tratarlos.

Tomemos la columna ‘life_sq’ como ejemplo. Primero usaremos el método describe () para mirar las estadísticas descriptivas y ver si podemos recolectar información de él.

df.life_sq.describe()

La salida se verá así:

count    30446.000000
mean        33.482658
std         46.538609
min          0.000000
25%         22.000000
50%         30.000000
75%         38.000000
max       7478.000000
Name: life_sq, dtype: float64

De la salida, es claro que algo no está correcto. El valor máximo parece ser anormalmente grande en comparación con los valores medio y mediano. Hagamos un diagrama de caja de estos datos para tener una mejor idea.

df.life_sq.plot(kind='box', figsize=(12, 8))
plt.show()

La salida se verá así:

datos limpios del diagrama de caja

De la gráfica de caja se desprende claramente que la observación respectivo al valor máximo (7478) es un valor atípico en estos datos. Las estadísticas descriptivas, los diagramas de caja y los diagramas de dispersión nos ayudan a identificar valores atípicos en los datos.

Podemos lidiar con los valores atípicos como lo hicimos con los valores perdidos. Podemos borrar las observaciones que creemos que son valores atípicos, o podemos reemplazar los valores atípicos con valores adecuados, o podemos hacer algún tipo de transformación en los datos (como logaritmo o exponencial). En nuestro caso, eliminemos el registro donde el valor de ‘life_sq’ es 7478.

# removing the outlier value in life_sq column
df = df.loc[df.life_sq < 7478]

Registros duplicados

A veces, los datos pueden contener valores duplicados. Es esencial borrar los registros duplicados de su conjunto de datos antes de continuar con cualquier proyecto de aprendizaje automático. En nuestros datos, dado que la columna de ID es un identificador único, eliminaremos los registros duplicados considerando todos menos la columna de ID.

# dropping duplicates by considering all columns other than ID
cols_other_than_id = list(df.columns)[1:]
df.drop_duplicates(subset=cols_other_than_id, inplace=True)

Esto nos ayudará a borrar los registros duplicados. Al utilizar el método de forma, puede verificar que los registros duplicados verdaderamente se hayan eliminado. El número de observaciones es ahora 30,434.

Arreglando el tipo de datos

A menudo, en el conjunto de datos, los valores no se almacenan en el tipo de datos correcto. Esto puede crear un obstáculo en etapas posteriores y es factible que no obtengamos el resultado deseado o que obtengamos errores durante la ejecución. Un error de tipo de datos común es el de las fechas. Las fechas a menudo se analizan como objetos en Python. Hay un tipo de datos separado para las fechas en Pandas, llamado DateTime.

Primero verificaremos el tipo de datos de la columna de marca de tiempo en nuestros datos.

df.timestamp.dtype

Esto devuelve el tipo de datos ‘objeto’. Ahora sabemos que la marca de tiempo no se almacena correctamente. Para arreglar este problema, convierta la columna de marca de tiempo al formato DateTime.

# converting timestamp to datetime format
df['timestamp'] = pd.to_datetime(df.timestamp, format="%Y-%m-%d")

Ahora tenemos la marca de tiempo en el formato correcto. De manera semejante, puede haber columnas donde los números enteros se almacenan como objetos. Es esencial identificar dichas características y corregir el tipo de datos antes de continuar con el aprendizaje automático. Por suerte para nosotros, no tenemos ningún problema de este tipo en nuestro conjunto de datos.

EndNote

En este post, discutimos algunas formas básicas en las que podemos limpiar datos en Python antes de comenzar con nuestro proyecto de aprendizaje automático. Necesitamos identificar y borrar los valores faltantes, identificar y tratar los valores atípicos, borrar los registros duplicados y corregir el tipo de datos de todas las columnas de nuestro conjunto de datos antes de continuar con nuestra tarea de AA.

El autor de este post es Vishesh Arora. Puedes conectarte conmigo en LinkedIn.

Los medios que se muestran en este post sobre el acreditación del lenguaje de señas no son propiedad de DataPeaker y se usan a discreción del autor.

Suscribite a nuestro Newsletter

No te enviaremos correo SPAM. Lo odiamos tanto como tú.