El pre-procesamiento de los datos es una fase esencial en cualquier proyecto de Machine Learning, e implica fases como la limpieza o la transformación de los datos, entre otras.
Y estas transformaciones buscan obtener una representación numérica adecuada de sets de datos que contienen características (o variables predictoras) de diferentes tipos (como por ejemplo variables numéricas y variables categóricas).
Y en estos casos el uso de «ColumnTransformer», de la librería Scikit-Learn, resulta útil, pues nos permite aplicar diferentes tipos de transformaciones a un set de datos dependiendo de las características de cada variable a transformar.
Así que en este tutorial veremos qué es, para qué sirve y cómo usar «ColumnTransformer» de Scikit-Learn para aplicar de manera simultánea diferentes tipos de transformaciones a un set de datos antes de entrenar un modelo de Machine Learning y al momento de usar el modelo entrenado para generar predicciones.
Recuerda que este tutorial es exclusivo para suscriptores a la Academia Online. Si estás suscrito podrás acceder al enlace de descarga del código fuente y del set de datos al final del tutorial.
¿Qué es la transformación de los datos?
La transformación de datos en Machine Learning es una etapa del preprocesamiento que consiste en modificar los datos originales para hacerlos más adecuados para el modelo.
Con esta fase de transformación lo que se busca es que las variables (es decir, los datos de entrada al modelo) tengan una escala, formato y representación que los algoritmos de entrenamiento puedan interpretar correctamente y que permitan que el modelo genere predicciones adecuadas.
Un ejemplo de transformación es la estandarización, que se aplica a variables numéricas y que consiste en restar de cada variable (o columna del set de datos) su valor promedio y el resultado dividirlo entre la desviación estándar de dicha columna. El resultado es una variable «estandarizada» que tendrá una media igual a cero y una desviación estándar igual a 1.
Otro ejemplo, aplicado al caso de variables categóricas, es la codificación one-hot, donde cada subnivel de la variable categórica es codificado con una secuencia de unos y ceros. Por ejemplo, si la variable categórica «color» tiene como subniveles «rojo», «azul» y «verde», entonces estos sub-niveles se podrían codificar en formato one-hot con las secuencias [1, 0, 0], [0, 1, 0] y [0, 0, 1] respectivamente.
¿Qué problema resuelve ColumnTransformer de Scikit-Learn?
En la práctica, en un proyecto de Machine Learning generalmente nos encontraremos con sets de datos que contienen múltiples variables de diferentes tipos, no sólo variables numéricas.
Por ejemplo, podríamos tener un set de datos de un grupo de personas donde las variables de interés son:
- Edad: variable numérica en el rango de 18 a 72 años
- Nivel de ingresos: variable numérica en el rango de 1.000 a 5.400 USD
- Nivel de estudios: variable categórica con sub-niveles «primaria», «secundaria», «universidad»
Si queremos usar estas variables para entrenar un modelo de Machine Learning, en principio tendremos que transformar de manera individual cada una de estas variables. Por ejemplo:
- Edad: podríamos usar «StandardScaler()» de Scikit-Learn para estandarizar esta variable
- Nivel de ingresos: podríamos usar nuevamente «StandarScaler()» para transformar esta variable
- Nivel de estudios: en este caso podríamos usar «OneHotEncoder()» para codificar numéricamente esta variable
Aunque el enfoque anterior es válido, realmente no es una forma práctica de aplicar las transformaciones. Esto se debe a que para obtener el set de datos transformado se requerirían muchas líneas de código.
Por ejemplo, si volvemos al ejemplo hipotético planteado anteriormente, y asumiendo que «X» es un arreglo que contiene las tres variables (cada una en una columna), una manera de realizar la transformación de los datos sería esta:
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
X12 = X[:,0:2] # Primeras dos columnas (Edad y Nivel de Ingresos)
X3 = X[:,-1].reshape(-1, 1) # Última columna (Nivel de estudios)
# Transformación columnas 1 y 2 (Edad y Nivel de Ingresos)
scaler = StandardScaler()
X12_s = scaler.fit_transform(X12)
# Codificación one-hot de la columna 3
enc = OneHotEncoder()
X3_enc = enc.fit_transform(X3).toarray() # opcional: .toarray() para convertir a NumPy
# Combinar los resultados
X_transformado = np.concatenate([X12_s, X3_enc], axis=1)
donde:
- En las líneas 4 y 5 extraemos las variables numéricas (línea 4) y la variable categórica (línea 5)
- En las líneas 8 y 9 realizamos la transformación de las variables numéricas usando «StandardScaler()»
- En las líneas 12 y 13 hacemos la codificación «one-hot» de la variable categórica
- Y en la línea 16 combinamos las transformaciones anteriores para obtener nuevamente un único arreglo («X_transformado»)
Es decir, ¡en total se requieren 7 líneas de código para estas simples transformaciones!
Sin embargo, el uso de «ColumnTransformer» nos permite aplicar transformaciones individuales a las columnas de nuestro set de datos pero simplifica la sintaxis, reduciendo de esta forma la cantidad de líneas de código necesarias.
Así, si usamos «ColumnTransformer» en el ejemplo anterior simplemente deberíamos escribir estas líneas de código:
Contenido exclusivo para suscriptores
Si eres suscriptor accede en este enlace ó suscríbete a la Academia Online y accede a todo el contenido (lecciones en video, código fuente, sets de datos y descargas) de todos los cursos, proyectos y tutoriales.
Así que teniendo claro el tipo de problema que resuelve «ColumnTransformer», veamos un sencillo ejemplo práctico para entender cómo usarlo en un proyecto de Machine Learning.
El set de datos y el problema a resolver
Usaremos un set de datos que contiene un total de 4.850 registros, donde cada uno de los cuales corresponde a inmueble en una ciudad determinada.
Por cada inmueble tendremos la siguiente información:
- Área (variable numérica): el área en metros cuadrados del inmueble
- Número de habitaciones (variable numérica)
- Vecindario: variable categórica que indica el tipo de vecindario donde está ubicado el inmueble
- Edad (variable numérica): la edad del inmueble
- Precio (variable numérica): el precio en USD del inmueble
Y para justificar el uso de «ColumnTransformer» asumiremos que lo que queremos es entrenar y validar un sencillo modelo de Regresión Lineal Múltiple para predecir el precio del inmueble con base en las otras variables.
Comencemos leyendo el set de datos con ayuda de Pandas:
import pandas as pd
df = pd.read_csv('precios_inmuebles.csv')
df
Tras ejecutar el bloque de código anterior obtenemos un DataFrame similar a este:
area nhabs vecindario edad precio
0 134 3 B 28 506927.0
1 115 3 B 33 392035.3
2 139 3 C 21 439959.2
3 165 3 B 6 598435.8
4 112 4 B 38 399988.1
... ... ... ... ... ...
4845 135 4 B 11 556334.7
4846 54 2 C 9 221939.9
4847 104 5 C 26 407482.5
4848 103 5 A 33 449467.0
4849 134 2 A 35 485755.7
Muy bien, antes de construir el modelo hagamos una simple exploración del set de datos.
Exploración del set de datos
Comencemos usando el método «select_dtypes» de Pandas para extraer las columnas numéricas así como la columna categórica:
num_cols = df.select_dtypes(include="number").columns
cat_cols = df.select_dtypes(exclude="number").columns
Como implementaremos un modelo de Regresión Lineal, podemos hacer gráficos de dispersión por pares de variables numéricas para encontrar posibles relaciones entre la variable a predecir (columna «precio») y las otras variables numéricas predictoras (columnas «area», «nhabs» y «edad»). Para ello podemos usar la función «pairplot» de la librería Seaborn:
import seaborn as sns
import matplotlib.pyplot as plt
sns.pairplot(df[num_cols])
con lo cual obtenemos un gráfico similar a este:

En la diagonal principal de este gráfico podemos ver la distribución de las variables, mientras que podemos analizar la parte superior o inferior de dicha diagonal para comparar pares de variables.
Al analizar la diagonal principal podemos observar que:
- «area» y «precio» tienen prácticamente una distribución Gaussiana pero rangos muy diferentes. Para el área los valores oscilan entre 100 y 200 m^2, mientras que para el precio los valores oscilan entre 200.000 y 800.000 USD
- «nhabs» y «edad» son variables numéricas discretas. En el caso del número de habitaciones tendremos inmuebles con 2, 3, 4 o 5, mientras que la edad de los inmuebles oscila entre aproximadamente los 5 y los 45 años.
La conclusión principal de esta parte del análisis es que las variables numéricas tienen diferentes escalas. Por tanto, para poderlas usar en el modelo de Regresión Lineal tendremos que realizar su escalamiento.
Para analizar la relación entre la variable a predecir («precio») y las variables numéricas predictoras podemos enfocarnos únicamente en la última fila del gráfico anterior. En este caso podemos ver que:
- «precio» y «area» tienen una relación lineal. Es decir que el área será la variable más relevante para nuestro modelo de Regresión Lineal.
- Mientras que no existe una relación lineal entre «precio» y las otras dos variables numéricas («nhabs» y «edad»). A pesar de esto incluiremos estas dos variables en nuestro modelo de Regresión Lineal Múltiple
Veamos ahora la relación que existe entre la variable categórica («vecindario») y la variable a predecir. Para ello podemos simplemente hacer un gráfico de caja para determinar cómo cambia el precio de cada inmueble dependiendo del tipo de vecindario. Así que usaremos la función «boxplot» de Seaborn para generar este gráfico:
sns.boxplot(df, x=cat_cols[0], y='precio', hue=cat_cols[0])
con lo cual obtenemos un conjunto de gráficos de caja como este:

En este caso vemos el precio del inmueble se incrementa ligeramente con el tipo de vecindario, siendo C el vecindario con los precios más bajos y A con los valores más altos.
Así que también incluiremos esta variable categórica en nuestro modelo de Regresión Lineal.
Sets de entrenamiento, validación y prueba
Perfecto, habiendo determinado que todas las variables pueden resultar relevantes para el modelo que construiremos, el siguiente paso es subdividir el set de datos en los subsets de entrenamiento, validación y prueba.
Comencemos tomando el DataFrame original (variable «df») y separando las variables predictoras de la variable a predecir:
X = df.drop("precio", axis=1)
y = df["precio"]
En este caso la variable «X» contendrá las variables predictoras (columnas «area», «nhabs», «vecindario» y «edad») mientras que «y» contendrá la variable a predecir («precio»).
A continuación creamos los sets de entrenamiento, validación y prueba con proporciones del 60%, 20% y 20% del total de los datos respectivamente.
Para ello usaremos la función «train_test_split» de Scikit-Learn. Así que comenzamos haciendo una primera partición 60/40 para crear el set de entrenamiento que contendrá el 60% de los datos:
from sklearn.model_selection import train_test_split
x_tr, x_resto, y_tr, y_resto = train_test_split(X, y, test_size=0.4, random_state=42)
Perfecto, el set de entrenamiento estará en las variables «x_tr» y «y_tr».
A continuación volvemos a usar «train_test_split» pero sobre el set de datos restante («x_resto», «y_resto») y realizaremos una partición 50/50, con lo cual obtendremos los sets de validación y prueba (cada uno con el 20% restante del total de datos):
x_vl, x_ts, y_vl, y_ts = train_test_split(x_resto, y_resto, test_size=0.5, random_state=123)
Muy bien, con esto ya estamos listos para ver cómo usar ColumnTransformer para el escalamiento de los datos.
Pre-procesamiento de los datos con ColumnTransformer
Como lo vimos en la fase de exploración, las variables predictoras que introduciremos al modelo tiene diferentes características.
En particular, las variables numéricas tienen diferentes rangos de valores, mientras que la variable categórica debe ser codificada numéricamente para poderla usar como variable predictora en el modelo de Regresión Lineal.
Así que aplicaremos la siguiente estrategia de transformación:
Contenido exclusivo para suscriptores
Si eres suscriptor accede en este enlace ó suscríbete a la Academia Online y accede a todo el contenido (lecciones en video, código fuente, sets de datos y descargas) de todos los cursos, proyectos y tutoriales.
Y ahora simplemente usamos este set de prueba transformado junto con el método «predict» del modelo entrenado para obtener la predicción correspondiente a los precios de los inmuebles en el set de prueba:
y_pred_ts = modelo.predict(x_ts_transf)
Si imprimimos en pantalla estas predicciones, tendremos los precios de cada inmueble en este subset:
array([524323.82824122, 525423.75122802, 447815.32942416, 472216.15462791,
442910.84977519, 456265.22626787, 496403.74158545, 326329.36278459, ..........])
El set de datos y el código fuente de este tutorial
Contenido exclusivo para suscriptores
Si eres suscriptor accede en este enlace ó suscríbete a la Academia Online y accede a todo el contenido (lecciones en video, código fuente, sets de datos y descargas) de todos los cursos, proyectos y tutoriales.
Conclusión
Muy bien, en este tutorial acabamos de ver qué es y cómo se usa «ColumnTransformer» de Scikit-Learn.
En esencia, «ColumnTransformer» nos provee una interfaz de fácil uso con la cual con muy pocas líneas de código podemos aplicar diferentes transformaciones a las columnas nuestro set de datos.
Simplemente, al momento de crear la instancia de este transformador debemos especificar el tipo de transformación y las columnas correspondientes y una vez creada la instancia podemos usar los métodos «fit_transform()» o «transform()» para aplicar las transformaciones a los datos.
Así que es una herramienta que resulta muy útil cuando tenemos sets de datos cuyas columnas tienen diferentes características y requieren diferentes tipos de transformaciones durante el pre-procesamiento.
Recuerda que si eres suscriptor me puedes contactar a través de la Intranet (sección «Soporte») para aclarar las dudas que tengas de este tutorial.
