Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

A menudo, las personas que ingresan al campo de la ciencia de datos tienen expectativas poco realistas de lo que les espera. Mucha gente piensa que ahora escribirán redes neuronales geniales, crearán un asistente de voz de Iron Man o vencerán a todos en los mercados financieros.
pero trabaja Datos Los científicos se basan en datos, y uno de los aspectos más importantes y que consumen más tiempo es procesar los datos antes de introducirlos en una red neuronal o analizarlos de cierta manera.

En este artículo, nuestro equipo describirá cómo puede procesar datos de forma rápida y sencilla con instrucciones y código paso a paso. Intentamos hacer que el código fuera bastante flexible y pudiera usarse para diferentes conjuntos de datos.

Es posible que muchos profesionales no encuentren nada extraordinario en este artículo, pero los principiantes podrán aprender algo nuevo, y cualquiera que haya soñado durante mucho tiempo con hacer un cuaderno separado para el procesamiento de datos rápido y estructurado puede copiar el código y formatearlo usted mismo, o Descargue el cuaderno terminado desde Github.

Recibimos el conjunto de datos. ¿Qué hacer a continuación?

Entonces, la norma: necesitamos entender a qué nos enfrentamos, el panorama general. Para hacer esto, usamos pandas para definir simplemente diferentes tipos de datos.

import pandas as pd #импортируем pandas
import numpy as np  #импортируем numpy
df = pd.read_csv("AB_NYC_2019.csv") #читаем датасет и записываем в переменную df

df.head(3) #смотрим на первые 3 строчки, чтобы понять, как выглядят значения

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

df.info() #Демонстрируем информацию о колонках

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

Veamos los valores de las columnas:

  1. ¿El número de líneas en cada columna corresponde al número total de líneas?
  2. ¿Cuál es la esencia de los datos de cada columna?
  3. ¿A qué columna queremos apuntar para hacer predicciones?

Las respuestas a estas preguntas le permitirán analizar el conjunto de datos y trazar un plan aproximado para sus próximas acciones.

Además, para ver más profundamente los valores de cada columna, podemos usar la función pandas describe(). Sin embargo, la desventaja de esta función es que no proporciona información sobre columnas con valores de cadena. Nos ocuparemos de ellos más tarde.

df.describe()

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

Visualización mágica

Veamos dónde no tenemos ningún valor:

import seaborn as sns
sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

Esta fue una breve mirada desde arriba, ahora pasaremos a cosas más interesantes.

Intentemos encontrar y, si es posible, eliminar columnas que tengan un solo valor en todas las filas (no afectarán el resultado de ninguna manera):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #Перезаписываем датасет, оставляя только те колонки, в которых больше одного уникального значения

Ahora nos protegemos a nosotros mismos y al éxito de nuestro proyecto de líneas duplicadas (líneas que contienen la misma información en el mismo orden que una de las líneas existentes):

df.drop_duplicates(inplace=True) #Делаем это, если считаем нужным.
                                 #В некоторых проектах удалять такие данные с самого начала не стоит.

Dividimos el conjunto de datos en dos: uno con valores cualitativos y otro con valores cuantitativos.

Aquí debemos hacer una pequeña aclaración: si las líneas con datos faltantes en datos cualitativos y cuantitativos no están muy correlacionadas entre sí, entonces tendremos que decidir qué sacrificamos: todas las líneas con datos faltantes, solo una parte de ellas. o determinadas columnas. Si las líneas están correlacionadas, entonces tenemos todo el derecho de dividir el conjunto de datos en dos. De lo contrario, primero deberá ocuparse de las líneas que no correlacionan los datos faltantes en términos cualitativos y cuantitativos, y solo luego dividir el conjunto de datos en dos.

df_numerical = df.select_dtypes(include = [np.number])
df_categorical = df.select_dtypes(exclude = [np.number])

Hacemos esto para que nos resulte más fácil procesar estos dos tipos diferentes de datos; más adelante comprenderemos cuánto más fácil nos hace la vida.

Trabajamos con datos cuantitativos

Lo primero que debemos hacer es determinar si existen “columnas espía” en los datos cuantitativos. Llamamos así a estas columnas porque se presentan como datos cuantitativos, pero actúan como datos cualitativos.

¿Cómo podemos identificarlos? Por supuesto, todo depende de la naturaleza de los datos que esté analizando, pero en general dichas columnas pueden tener pocos datos únicos (en la región de 3 a 10 valores únicos).

print(df_numerical.nunique())

Una vez que hayamos identificado las columnas espía, las pasaremos de datos cuantitativos a datos cualitativos:

spy_columns = df_numerical[['колонка1', 'колока2', 'колонка3']]#выделяем колонки-шпионы и записываем в отдельную dataframe
df_numerical.drop(labels=['колонка1', 'колока2', 'колонка3'], axis=1, inplace = True)#вырезаем эти колонки из количественных данных
df_categorical.insert(1, 'колонка1', spy_columns['колонка1']) #добавляем первую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка2', spy_columns['колонка2']) #добавляем вторую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка3', spy_columns['колонка3']) #добавляем третью колонку-шпион в качественные данные

Finalmente, hemos separado completamente los datos cuantitativos de los cualitativos y ahora podemos trabajar con ellos correctamente. Lo primero es entender dónde tenemos valores vacíos (NaN, y en algunos casos se aceptará 0 como valor vacío).

for i in df_numerical.columns:
    print(i, df[i][df[i]==0].count())

En este punto, es importante comprender en qué columnas los ceros pueden indicar valores faltantes: ¿se debe esto a cómo se recopilaron los datos? ¿O podría estar relacionado con los valores de los datos? Estas preguntas deben responderse caso por caso.

Entonces, si aún decidimos que nos faltan datos donde hay ceros, debemos reemplazar los ceros con NaN para que sea más fácil trabajar con estos datos perdidos más adelante:

df_numerical[["колонка 1", "колонка 2"]] = df_numerical[["колонка 1", "колонка 2"]].replace(0, nan)

Ahora veamos dónde nos faltan datos:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # Можно также воспользоваться df_numerical.info()

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

Aquí se deben marcar en amarillo aquellos valores dentro de las columnas que faltan. Y ahora empieza lo divertido: ¿cómo afrontar estos valores? ¿Debo eliminar filas con estos valores o columnas? ¿O llenar estos valores vacíos con otros?

A continuación se muestra un diagrama aproximado que puede ayudarle a decidir qué se puede hacer, en principio, con valores vacíos:

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

0. Eliminar columnas innecesarias

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. ¿La cantidad de valores vacíos en esta columna es mayor al 50%?

print(df_numerical.isnull().sum() / df_numerical.shape[0] * 100)

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)#Удаляем, если какая-то колонка имеет больше 50 пустых значений

2. Eliminar líneas con valores vacíos.

df_numerical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, если потом останется достаточно данных для обучения

3.1. Insertar un valor aleatorio

import random #импортируем random
df_numerical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True) #вставляем рандомные значения в пустые клетки таблицы

3.2. Insertar un valor constante

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>") #вставляем определенное значение с помощью SimpleImputer
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.3. Insertar el valor promedio o más frecuente

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='mean', missing_values = np.nan) #вместо mean можно также использовать most_frequent
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.4. Insertar el valor calculado por otro modelo.

A veces, los valores se pueden calcular utilizando modelos de regresión utilizando modelos de la biblioteca sklearn u otras bibliotecas similares. Nuestro equipo dedicará un artículo aparte a cómo se puede hacer esto en un futuro próximo.

Entonces, por ahora, la narrativa sobre los datos cuantitativos se interrumpirá, porque hay muchos otros matices sobre cómo preparar mejor y preprocesar los datos para diferentes tareas, y los aspectos básicos de los datos cuantitativos se han tenido en cuenta en este artículo, y Ahora es el momento de volver a los datos cualitativos, que separamos varios pasos atrás de los cuantitativos. ¡Puedes cambiar este cuaderno como quieras, adaptándolo a diferentes tareas, para que el preprocesamiento de datos sea muy rápido!

Datos cualitativos

Básicamente, para datos cualitativos, se utiliza el método de codificación One-hot para formatearlos de una cadena (u objeto) a un número. Antes de pasar a este punto, usemos el diagrama y el código anteriores para tratar con valores vacíos.

df_categorical.nunique()

sns.heatmap(df_categorical.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Hoja de referencia del Bloc de notas para un preprocesamiento rápido de datos

0. Eliminar columnas innecesarias

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. ¿La cantidad de valores vacíos en esta columna es mayor al 50%?

print(df_categorical.isnull().sum() / df_numerical.shape[0] * 100)

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True) #Удаляем, если какая-то колонка 
                                                                          #имеет больше 50% пустых значений

2. Eliminar líneas con valores vacíos.

df_categorical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, 
                                   #если потом останется достаточно данных для обучения

3.1. Insertar un valor aleatorio

import random
df_categorical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True)

3.2. Insertar un valor constante

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>")
df_categorical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_categorical[['колонка1', 'колонка2', 'колонка3']])
df_categorical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True)

Entonces, finalmente tenemos una idea de los valores nulos en los datos cualitativos. Ahora es el momento de realizar una codificación one-hot en los valores que están en su base de datos. Este método se utiliza con mucha frecuencia para garantizar que su algoritmo pueda aprender de datos de alta calidad.

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res)

features_to_encode = ["колонка1","колонка2","колонка3"]
for feature in features_to_encode:
    df_categorical = encode_and_bind(df_categorical, feature))

Finalmente hemos terminado de procesar datos cualitativos y cuantitativos separados: es hora de volver a combinarlos.

new_df = pd.concat([df_numerical,df_categorical], axis=1)

Después de haber combinado los conjuntos de datos en uno, finalmente podemos usar la transformación de datos usando MinMaxScaler de la biblioteca sklearn. Esto hará que nuestros valores estén entre 0 y 1, lo que ayudará a la hora de entrenar el modelo en el futuro.

from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
new_df = min_max_scaler.fit_transform(new_df)

Estos datos ahora están listos para cualquier cosa: redes neuronales, algoritmos de aprendizaje automático estándar, etc.

En este artículo, no tuvimos en cuenta el trabajo con datos de series de tiempo, ya que para dichos datos se deben utilizar técnicas de procesamiento ligeramente diferentes, según su tarea. En el futuro, nuestro equipo dedicará un artículo aparte a este tema y esperamos que pueda aportar algo interesante, nuevo y útil a su vida, como este.

Fuente: habr.com

Añadir un comentario