Antes de entrenar un algoritmo con el preprocesamiento de datos en machine learning vamos a verificar que nuestros datos de entrenamiento estén en la forma adecuada, evitando la existencia de valores nulos o desconocidos, y además nuestros nuestros algoritmos van a necesitar valores númericos donde para ello debemos codificar los valores categóricos que haya en nuestro conjunto de datos.

Para resolver el problema de los datos que no están en forma adecuada tenemos varias técnicas fundamentales del preprocesamiento de datos:

  • Eliminar e imputar valores ausentes de un conjunto de datos
  • Dar forma a datos categóricos para los algoritmos de aprendizaje automático, las características y las etiquetas
  • Seleccionar características importantes para la construcción del modelo

Eliminar e imputar valores ausentes de un conjunto de datos

Que son los datos ausentes

Los datos ausentes son aquellos que se definen como valores que faltan que serían útiles o significativos para el análisis de los resultados, por ejemplo:

  • Errores de recopilación de datos
  • Medidas que no sean aplicables
  • Campos que se hayan dejado en blanco en una encuesta

Todos estos espacios en blancos los vamos a poner con NAN, por lo que vamos a buscar algunas técnicas para tratar esos valores perdidos eliminando entradas en nuestro conjunto de datos o imputando valores ausentes de otras muestras o característica

Como identificar los datos ausentes

Si tenemos el siguiente conjunto de datos llamado datos.csv donde a algunas filas y columnas le faltan datos:

X1 X2 X3 X4
1.0 2.5 3.4 2.2
4.5 4.3
2.1 3.4

Todos estos espacios en blancos los vamos a poner con NAN, por lo que vamos a buscar algunas técnicas para tratar esos valores perdidos eliminando entradas en nuestro conjunto de datos o imputando valores ausentes de otras muestras o características.

Por ejemplo, en el siguiente código la sentencia datos.isnull().sum() nos va a devolver el número de valores ausentes NaN de cada columna:

import pandas as pd
def lecturaDatos():
    datos = pd.read_csv("datos.csv")
    return datos
datos = lecturaDatos()
print(datos.isnull().sum())                                                     

X1 2
X2 0
X3 1
X4 1

Eliminar muestras o características con datos ausentes

En el siguiente código vamos a eliminar las filas y columnas que falten datos:

import pandas as pd
def lecturaDatos():
    datos = pd.read_csv("datos.csv")
    return datos
datos = lecturaDatos()
filas_del=datos.dropna(axis=0) # Eliminamos las filas que falten datos
columnas_del=datos.dropna(axis=1) # Eliminamos las columnas que falten datos
print("Salida con las filas eliminadas")
print(filas_del)
print("Salida con las columnas eliminadas")
print(columnas_del)

Salida con las filas eliminadas
X1 X2 X3 X4
0 1.0 2.5 3.4 2.2

Salida con las columnas eliminadas
X2
0 2.5
1 4.5
2 2.1

En el siguiente ejemplo:
import pandas as pd
def lecturaDatos():
    datos = pd.read_csv("datos.csv")
    return datos
datos = lecturaDatos()
datos_del1=datos.dropna(how="all") #Descartamos aquellas filas donde todas las columnas sean todas NaN
datos_del2=datos.dropna(thresh=4) #Descartamos aquellas filas que tienen menos de 4 valores numericos
datos_del3=datos.dropna(subset=['X1']) #Se descartan las filas donde NaN este presente en la columna X1
print("Salida con las filas eliminadas cuyas columnas sen todas NAN (how):")
print(datos_del1)
print("Salida con las filas eliminadas que tienen menos de 4 valores numericos (thresh):")
print(datos_del2)
print("Salida con las filas eliminadas donde NaN este presente en la columna X1 (subset):")
print(datos_del3)

Salida con las filas eliminadas cuyas columnas sen todas NAN (how):
X1 X2 X3 X4
0 1.0 2.5 3.4 2.2
1 NaN 4.5 NaN 4.3
2 NaN 2.1 3.4 NaN

Salida con las filas eliminadas que tienen menos de 4 valores numéricos (thresh):
X1 X2 X3 X4
0 1.0 2.5 3.4 2.2

Salida con las filas eliminadas donde NaN esté presente en la columna X1 (subset):
X1 X2 X3 X4
0 1.0 2.5 3.4 2.2

Imputación de valores ausentes

Como técnicas de interpolación vamos a usar la imputación de valores ausentes donde vamos a sustituir el valor faltante de una columna por el valor medio de todos los datos de la columna.

from sklearn.impute import SimpleImputer
import pandas as pd
def lecturaDatos():
    datos = pd.read_csv("datos.csv")
    return datos
datos = lecturaDatos()
imr = SimpleImputer(strategy='mean')
imr.fit(datos.values)
imputed_data=imr.transform(datos.values)
print(imputed_data)
[[1. 2.5 3.4 2.2 ]
[1. 4.5 3.4 4.3 ]
[1. 2.1 3.4 3.25]]

Mapeo de características en el Preprocesamiento de datos en Machine Learning

Mapeo con datos nominales, ordinales y numéricos

En el siguiente ejemplo tenemos un conjunto de alumnos (datos nominales) con sus notas(datos ordinales), sus edades(Datos numéricos) y su asignatura(etiquetas de clase) donde vamos a mapearlos dándoles a cada uno una numeración:

import numpy as np
import pandas as pd
def leerDatos():
    datos = pd.DataFrame([
                          ['Juan','suspenso',12,'Matematicas'],
                          ['Pedro','aprobado',15,'Lenguaje'],
                          ['Maria','notable',13,'Historia'],
                          ['Luis','sobresaliente',9,'Matematicas'],
                         ])
    datos.columns = (['Nombre','Nota','Edad','Asignatura'])                     
    return datos
datos = leerDatos()
#print(datos)
nombre_mapping =
nota_mapping =
datos['Nombre']=datos['Nombre'].map(nombre_mapping)
datos['Nota']=datos['Nota'].map(nota_mapping)
print(datos)

 

Nombre  Nota  Edad   Asignatura
0       1     0    12  Matematicas
1       2     5    15     Lenguaje
2       3     7    13     Historia
3       4    10     9  Matematicas

Inversión de características con datos ordinales, ordinales, y numéricos

En este código vamos a invertir los datos a su codificación original:

import numpy as np
import pandas as pd
def leerDatos():
    datos = pd.DataFrame([
                          ['Juan','suspenso',12,'Matematicas'],
                          ['Pedro','aprobado',15,'Lenguaje'],
                          ['Maria','notable',13,'Historia'],
                          ['Luis','sobresaliente',9,'Matematicas'],
                         ])
    datos.columns = (['Nombre','Nota','Edad','Asignatura'])                     
    return datos
datos = leerDatos()
#print(datos)
nombre_mapping =
nota_mapping =
datos['Nombre']=datos['Nombre'].map(nombre_mapping)
datos['Nota']=datos['Nota'].map(nota_mapping)
print(datos)
#Inversion de datos
inversion_nombre=
datos['Nombre']=datos['Nombre'].map(inversion_nombre)
inversion_nota=
datos['Nota']=datos['Nota'].map(inversion_nota)
print('Datos Invertidos:')
print(datos)

 

Nombre  Nota  Edad   Asignatura
0       1     0    12  Matematicas
1       2     5    15     Lenguaje
2       3     7    13     Historia
3       4    10     9  Matematicas
Datos Invertidos:
  Nombre           Nota  Edad   Asignatura
0   Juan       suspenso    12  Matematicas
1  Pedro       aprobado    15     Lenguaje
2  Maria        notable    13     Historia
3   Luis  sobresaliente     9  Matematicas

Etiquetas de clase en el preprocesamiento de datos en Machine Learning

Mapeo de etiquetas de clase

import numpy as np
import pandas as pd
def leerDatos():
    datos = pd.DataFrame([
                          ['Juan','suspenso',12,'Matematicas'],
                          ['Pedro','aprobado',15,'Lenguaje'],
                          ['Maria','notable',13,'Historia'],
                          ['Luis','sobresaliente',9,'Matematicas'],
                         ])
    datos.columns = (['Nombre','Nota','Edad','Asignatura'])                     
    return datos
datos = leerDatos()
asignatura_mapping =
mapa_clases= #nos devuelve la enumeracion de las clases
print(mapa_clases)
datos['Asignatura'] = datos['Asignatura'].map(mapa_clases)
print(datos)

 

  Nombre           Nota  Edad  Asignatura
0   Juan       suspenso    12           2
1  Pedro       aprobado    15           1
2  Maria        notable    13           0
3   Luis  sobresaliente     9           2

Inversión de etiquetas de clase

import numpy as np
import pandas as pd
def leerDatos():
    datos = pd.DataFrame([
                          ['Juan','suspenso',12,'Matematicas'],
                          ['Pedro','aprobado',15,'Lenguaje'],
                          ['Maria','notable',13,'Historia'],
                          ['Luis','sobresaliente',9,'Matematicas'],
                         ])
    datos.columns = (['Nombre','Nota','Edad','Asignatura'])                     
    return datos
datos = leerDatos()
asignatura_mapping =
mapa_clases= #nos devuelve la enumeracion de las clases
print(mapa_clases)
datos['Asignatura'] = datos['Asignatura'].map(mapa_clases)
print(datos)
#Inversion de datos
inversion_clases=
datos['Clase']=datos['Asignatura'].map(inversion_clases)
print('Datos Invertidos:')
print(datos)

 

  Nombre           Nota  Edad  Asignatura
0   Juan       suspenso    12           2
1  Pedro       aprobado    15           1
2  Maria        notable    13           0
3   Luis  sobresaliente     9           2
Datos Invertidos:
  Nombre           Nota  Edad  Asignatura        Clase
0   Juan       suspenso    12           2  Matematicas
1  Pedro       aprobado    15           1     Lenguaje
2  Maria        notable    13           0     Historia
3   Luis  sobresaliente     9           2  Matematicas

Clase labelEncoder

Sklearn tiene una clase llamada LabelEncoder que codifica las etiquetas de una característica categórica en valores numéricos entre 0 y el número de clases menos 1 y para ello vamos a hacer uso como vemos en el siguiente ejemplo:

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
tipos_animales = ('perro','gato','pajaro','hormiga','leon','tigre','mono')
animales_df = pd.DataFrame(tipos_animales, columns=['Tipos_animales'])
# creating instance of labelencoder
labelencoder = LabelEncoder()
animales_df['Categoria_animales'] = labelencoder.fit_transform(animales_df['Tipos_animales'])
print(animales_df)
0          perro                   5
1           gato                   0
2         pájaro                   4
3        hormiga                   1
4           león                   2
5          tigre                   6
6           mono                   3

Aquí tenemos un problema que hemos clasificado datos de animales en conjuntos numéricos y no existe ninguna relación entre los elementos, pero el modelo va a malinterpretar esos datos en un tipo de orden 0 < 1 < 6 con algún tipo de jerarquía/orden y para evitar esto usamos la codificación en caliente ‘Codificación One-Hot’

En este otro ejemplo va a codificar los colores en los valores 1,2,0

import pandas as pd
from sklearn.preprocessing import LabelEncoder
def leerDatos():
    datos = pd.DataFrame([
                          ['Rojo'],
                          ['Verde'],
                          ['Azul']
                         ])
    datos.columns = (['Color'])                     
    return datos
datos = leerDatos()
label_encoder = LabelEncoder()
colores = datos['Color'].values
y = label_encoder.fit_transform(colores)
print(y)
[1 2 0]

Clase One-HotEncoder

Para solucionar el problema anterior vamos a vamos a crear una columna separada para cada color usando la codificación en caliente, donde se crea una columna binaria para la categoría color y devuelve una matriz dispersa o una matriz densa.

Colores Verde Verde Azul
Rojo 1 0 0
Verde 0 1 0
Azul 0 0 1
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
def lecturaDatos():
    datos = pd.DataFrame([
                          ['Rojo'],
                          ['Verde'],
                          ['Azul']
                         ])
    datos.columns = (['Color'])                     
    return datos
datos = lecturaDatos() 
X = datos[['Color']].values #Carga los datos de la columna color en X
one = OneHotEncoder(categories="auto")                         
s=one.fit_transform(X).toarray()  
print(s)

 

[[0. 1. 0.]
 [0. 0. 1.]
 [1. 0. 0.]]

Clase get_dummies

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
def lecturaDatos():
    datos = pd.DataFrame([
                          ['Rojo'],
                          ['Verde'],
                          ['Azul']
                         ])
    datos.columns = (['Color']) 
    s=pd.get_dummies(datos[['Color']])
    return s
datos = lecturaDatos() 
print(datos)

 

   Color_Azul  Color_Rojo  Color_Verde
0           0           1            0
1           0           0            1
2           1           0            0