Chapter 3: Data Preprocessing and Feature Engineering
3.3 Codificación y Manejo de Datos Categóricos
En el ámbito de los conjuntos de datos del mundo real, los datos categóricos son una ocurrencia común. Estas características representan categorías o etiquetas distintas, a diferencia de los valores numéricos continuos. El manejo adecuado de los datos categóricos es de suma importancia, ya que la gran mayoría de los algoritmos de aprendizaje automático están diseñados para trabajar con entradas numéricas. Una codificación incorrecta de las variables categóricas puede tener consecuencias graves, potencialmente conduciendo a un rendimiento subóptimo del modelo o incluso a errores durante el proceso de entrenamiento.
Esta sección explora una variedad de técnicas para codificar y gestionar datos categóricos. Exploraremos métodos fundamentales como la codificación one-hot y la codificación por etiquetas, así como enfoques más matizados como la codificación ordinal.
Además, nos adentraremos en técnicas avanzadas, como la codificación por objetivo, que puede ser particularmente útil en ciertos escenarios. También abordaremos los desafíos que plantean las variables categóricas de alta cardinalidad y discutiremos estrategias efectivas para gestionarlas. Al dominar estas técnicas, estarás bien preparado para manejar una amplia gama de escenarios de datos categóricos en tus proyectos de aprendizaje automático.
3.3.1 Entendiendo los Datos Categóricos
Las características categóricas son un concepto fundamental en ciencia de datos y aprendizaje automático, que representan variables que pueden tomar un número limitado de valores o categorías distintas. A diferencia de las variables continuas que pueden tomar cualquier valor numérico dentro de un rango, las variables categóricas son discretas y, a menudo, cualitativas por naturaleza. Comprender estas características es crucial para una preprocesamiento eficaz de los datos y el desarrollo de modelos.
Las características categóricas se pueden clasificar en dos tipos principales:
- Nominales (Sin Orden): Estas categorías no tienen un orden o clasificación inherente. Cada categoría es distinta e independiente de las demás. Por ejemplo:
- Colores: "Rojo", "Verde", "Azul"
- Tipos de sangre: "A", "B", "AB", "O"
- Géneros musicales: "Rock", "Jazz", "Clásico", "Hip-hop"
En estos casos, no hay una manera significativa de decir que una categoría es "mayor" o "menor" que otra.
- Ordinales (Con Orden): Estas categorías tienen un orden o clasificación claro y significativo, aunque los intervalos entre las categorías pueden no ser consistentes o medibles. Algunos ejemplos incluyen:
- Niveles educativos: "Secundaria", "Licenciatura", "Maestría", "Doctorado"
- Satisfacción del cliente: "Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"
- Tallas de camiseta: "XS", "S", "M", "L", "XL"
Aquí, hay una progresión clara de una categoría a otra, incluso si la "distancia" entre categorías no es cuantificable.
La distinción entre categorías nominales y ordinales es crucial porque determina cómo debemos manejar y codificar estas características para los algoritmos de aprendizaje automático. La mayoría de los algoritmos esperan entradas numéricas, por lo que necesitamos convertir los datos categóricos en un formato numérico. Sin embargo, el método de codificación que elijamos puede afectar significativamente el rendimiento y la interpretación del modelo.
Para las categorías nominales, se suelen utilizar técnicas como la codificación one-hot o la codificación por etiquetas. La codificación one-hot crea columnas binarias para cada categoría, mientras que la codificación por etiquetas asigna un entero único a cada categoría. Para las categorías ordinales, podríamos usar la codificación ordinal para preservar la información del orden, o emplear técnicas más avanzadas como la codificación por objetivo.
En las siguientes secciones, profundizaremos en estos métodos de codificación, explorando sus fortalezas, debilidades y casos de uso apropiados. Comprender estas técnicas es esencial para preprocesar eficazmente los datos categóricos y construir modelos de aprendizaje automático robustos.
3.3.2 Codificación One-Hot
La codificación one-hot es un método fundamental y ampliamente utilizado para transformar variables categóricas nominales en un formato numérico que pueda ser utilizado fácilmente por los algoritmos de aprendizaje automático. Esta técnica es particularmente valiosa porque la mayoría de los modelos de aprendizaje automático están diseñados para trabajar con entradas numéricas en lugar de datos categóricos.
Así es como funciona la codificación one-hot:
- Para cada categoría única en la característica original, se crea una nueva columna binaria.
- En estas nuevas columnas, un valor de 1 indica la presencia de la categoría correspondiente para un dato, mientras que un valor de 0 indica su ausencia.
- Este proceso crea un conjunto de características binarias que, en conjunto, representan la variable categórica original.
Por ejemplo, si tenemos una característica "Color" con categorías "Rojo", "Azul" y "Verde", la codificación one-hot crearía tres nuevas columnas: "Color_Rojo", "Color_Azul" y "Color_Verde". Cada fila en el conjunto de datos tendría un 1 en una de estas columnas y 0 en las otras, dependiendo del valor de color original.
La codificación one-hot es particularmente adecuada para variables nominales, que son variables categóricas en las que no existe un orden o clasificación inherente entre las categorías. Ejemplos de tales variables incluyen:
- Nombres de ciudades (p. ej., Nueva York, Londres, Tokio)
- Tipos de productos (p. ej., Electrónica, Ropa, Libros)
- Especies de animales (p. ej., Perro, Gato, Pájaro)
La principal ventaja de la codificación one-hot es que no impone ningún orden artificial a las categorías, lo cual es crucial para las variables nominales. Cada categoría se trata como una característica separada e independiente, lo que permite que los modelos de aprendizaje automático aprendan la importancia de cada categoría por separado.
Sin embargo, es importante tener en cuenta que la codificación one-hot puede generar datos de alta dimensionalidad cuando se trabaja con variables categóricas que tienen muchas categorías únicas. Esto puede resultar en la "maldición de la dimensionalidad" y puede requerir técnicas adicionales de selección de características o reducción de dimensionalidad en algunos casos.
a. Codificación One-Hot con Pandas
Pandas, una biblioteca poderosa para la manipulación de datos en Python, proporciona un método simple y eficiente para aplicar la codificación one-hot utilizando la función get_dummies()
. Esta función es particularmente útil para convertir variables categóricas en un formato adecuado para los algoritmos de aprendizaje automático.
Así es como funciona get_dummies()
:
- Detecta automáticamente las columnas categóricas en tu DataFrame.
- Para cada categoría única en una columna, crea una nueva columna binaria.
- En estas nuevas columnas, asigna un 1 donde la categoría está presente y 0 donde está ausente.
- La columna categórica original se elimina y se reemplaza por estas nuevas columnas binarias.
La función get_dummies()
ofrece varias ventajas:
- Simplicidad: Requiere un código mínimo, lo que facilita su uso incluso para principiantes.
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente.
- Personalización: Ofrece opciones para personalizar el proceso de codificación, como especificar prefijos de columna o manejar categorías desconocidas.
Al utilizar get_dummies()
, puedes transformar rápidamente los datos categóricos en un formato numérico listo para ser utilizado en diversos modelos de aprendizaje automático, agilizando tu flujo de trabajo de preprocesamiento de datos.
Ejemplo: Codificación One-Hot con Pandas
import pandas as pd
import numpy as np
# Create a more comprehensive sample dataset
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', 'New York', 'London', 'Paris'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, 8419000, 8982000, 2141000],
'Continent': ['North America', 'Europe', 'Europe', 'Asia', 'Europe', 'North America', 'Europe', 'Europe']
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Apply one-hot encoding to the 'City' column
city_encoded = pd.get_dummies(df['City'], prefix='City')
# Apply one-hot encoding to the 'Continent' column
continent_encoded = pd.get_dummies(df['Continent'], prefix='Continent')
# Concatenate the encoded columns with the original DataFrame
df_encoded = pd.concat([df, city_encoded, continent_encoded], axis=1)
print("DataFrame after one-hot encoding:")
print(df_encoded)
print("\n")
# Demonstrate handling of high-cardinality columns
df['UniqueID'] = np.arange(len(df))
high_cardinality_encoded = pd.get_dummies(df['UniqueID'], prefix='ID')
df_high_cardinality = pd.concat([df, high_cardinality_encoded], axis=1)
print("DataFrame with high-cardinality column encoded:")
print(df_high_cardinality.head())
print("\n")
# Demonstrate handling of missing values
df_missing = df.copy()
df_missing.loc[1, 'City'] = np.nan
df_missing.loc[3, 'Continent'] = np.nan
print("DataFrame with missing values:")
print(df_missing)
print("\n")
# Handle missing values before encoding
df_missing['City'] = df_missing['City'].fillna('Unknown')
df_missing['Continent'] = df_missing['Continent'].fillna('Unknown')
# Apply one-hot encoding to the DataFrame with handled missing values
df_missing_encoded = pd.get_dummies(df_missing, columns=['City', 'Continent'], prefix=['City', 'Continent'])
print("DataFrame with missing values handled and encoded:")
print(df_missing_encoded)
Este ejemplo de código demuestra un enfoque integral de la codificación one-hot utilizando pandas.
A continuación, se desglosa detalladamente el código y su funcionalidad:
- Preparación de Datos:
- Creamos un conjunto de datos más completo con varias columnas: 'City', 'Population' y 'Continent'.
- Esto nos permite demostrar la codificación para diferentes tipos de variables categóricas.
- Codificación Básica One-Hot:
- Utilizamos
pd.get_dummies()
para codificar las columnas 'City' y 'Continent' por separado. - Se usa el parámetro
prefix
para distinguir las columnas codificadas (por ejemplo, 'City_New York', 'Continent_Europe'). - Luego concatenamos estas columnas codificadas con el DataFrame original.
- Utilizamos
- Manejo de Columnas con Alta Cardinalidad:
- Creamos una columna 'UniqueID' para simular una característica con alta cardinalidad.
- Demostramos cómo la codificación one-hot puede generar un gran número de columnas para características con alta cardinalidad.
- Esto resalta los posibles problemas de uso de memoria y eficiencia computacional en estos casos.
- Manejo de Valores Faltantes:
- Introducimos valores faltantes en las columnas 'City' y 'Continent'.
- Antes de codificar, rellenamos los valores faltantes con 'Unknown' utilizando el método
fillna()
. - Esto asegura que los valores faltantes se traten como una categoría separada durante la codificación.
- Luego aplicamos la codificación one-hot al DataFrame con los valores faltantes gestionados.
- Visualización de Resultados:
- En cada paso, imprimimos el DataFrame para mostrar cómo cambia después de cada operación.
- Esto ayuda a comprender el efecto de cada paso de codificación en la estructura de los datos.
Este ejemplo integral cubre varios aspectos de la codificación one-hot, incluidos el manejo de múltiples columnas categóricas, el tratamiento de características con alta cardinalidad y la gestión de valores faltantes. Proporciona una demostración práctica de cómo utilizar pandas para estas tareas en un escenario del mundo real.
La función get_dummies()
convierte la columna "City" en columnas binarias separadas: City_New York
, City_London
y City_Paris
, que representan cada ciudad. Esto permite que el modelo de aprendizaje automático interprete la característica categórica numéricamente.
b. Codificación One-Hot con Scikit-learn
Scikit-learn ofrece una implementación robusta de la codificación one-hot a través de la clase OneHotEncoder
. Esta clase proporciona un enfoque más flexible y poderoso para codificar variables categóricas, particularmente útil en pipelines complejos de aprendizaje automático o cuando se requiere un control más detallado sobre el proceso de codificación.
La clase OneHotEncoder
destaca por varias razones:
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente, lo que la hace eficiente para conjuntos de datos con numerosas características categóricas.
- Salida en Matriz Dispersa: De forma predeterminada, devuelve una matriz dispersa, lo que es eficiente en términos de memoria para conjuntos de datos con muchas categorías.
- Manejo de Categorías Desconocidas: Ofrece opciones para manejar categorías que no estaban presentes durante el proceso de ajuste, crucial para aplicaciones del mundo real donde pueden aparecer nuevas categorías en los datos de prueba.
- Integración con Pipelines de Scikit-learn: Se integra perfectamente con la clase
Pipeline
de Scikit-learn, lo que permite una fácil combinación con otros pasos de preprocesamiento y modelos.
Cuando se trabaja con pipelines de aprendizaje automático, el OneHotEncoder
puede ser especialmente valioso. Permite definir un esquema de codificación consistente que se puede aplicar de manera uniforme a los conjuntos de datos de entrenamiento y prueba, asegurando que el modelo reciba datos de entrada con un formato consistente.
Para escenarios que requieren más control, el OneHotEncoder
ofrece varios parámetros para personalizar su comportamiento. Por ejemplo, se puede especificar cómo manejar las categorías desconocidas, si usar un formato de salida disperso o denso, e incluso definir una codificación personalizada para características específicas.
Ejemplo: Codificación One-Hot con Scikit-learn
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
import pandas as pd
import numpy as np
# Sample data
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', np.nan],
'Country': ['USA', 'UK', 'France', 'Japan', 'Germany', 'USA'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, np.nan]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Define transformers for categorical and numerical data
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(sparse=False, handle_unknown='ignore'))
])
numerical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean'))
])
# Combine transformers into a ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('cat', categorical_transformer, ['City', 'Country']),
('num', numerical_transformer, ['Population'])
]
)
# Apply the preprocessing pipeline
transformed_data = preprocessor.fit_transform(df)
# Get feature names
onehot_features_city = preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(['City', 'Country'])
numerical_features = ['Population']
feature_names = np.concatenate([onehot_features_city, numerical_features])
# Create a new DataFrame with transformed data
df_encoded = pd.DataFrame(transformed_data, columns=feature_names)
print("Transformed DataFrame:")
print(df_encoded)
Explicación del Desglose del Código:
- Manejo de Valores Faltantes:
- Las columnas categóricas (
City
yCountry
) se rellenan con el valor más frecuente. - La columna numérica (
Population
) se rellena con el valor medio.
- Las columnas categóricas (
- Codificación One-Hot:
- Las columnas categóricas (
City
,Country
) se codifican mediante one-hot, convirtiéndolas en columnas binarias.
- Las columnas categóricas (
- Pipeline con
ColumnTransformer
:- Combina los pasos de preprocesamiento categórico y numérico en un único pipeline.
- Nombres de Características:
- Recupera automáticamente nombres significativos para las características codificadas.
- Resultado Final:
- Se crea un DataFrame limpio y completamente preprocesado (
df_encoded
), listo para análisis o modelado.
- Se crea un DataFrame limpio y completamente preprocesado (
Este ejemplo muestra varias características clave de las capacidades de preprocesamiento de Scikit-learn:
- Manejo de datos faltantes con SimpleImputer
- Codificación one-hot de categorías nominales ('City')
- Codificación de etiquetas de categorías ordinales ('Country')
- Uso de ColumnTransformer para aplicar diferentes transformaciones a diferentes columnas
- Pipeline para encadenar múltiples pasos de preprocesamiento
- Extracción de nombres de características después de la transformación
- Transformación inversa para recuperar las categorías originales de los datos codificados
Este enfoque proporciona un método robusto y escalable para preprocesar tipos de datos mixtos, manejar valores faltantes y preparar datos para modelos de aprendizaje automático.
En este caso, OneHotEncoder
convierte los datos categóricos en una matriz densa de valores binarios, que pueden pasarse directamente a los modelos de aprendizaje automático.
3.3.3 Codificación de Etiquetas (Label Encoding)
La codificación de etiquetas es una técnica que asigna un número entero único a cada categoría en una característica categórica. Este método es particularmente útil para variables categóricas ordinales, donde existe un orden o jerarquía significativa entre las categorías. Al convertir las categorías en valores numéricos, la codificación de etiquetas permite que los algoritmos de aprendizaje automático interpreten y procesen los datos categóricos de manera más efectiva.
La principal ventaja de la codificación de etiquetas radica en su capacidad para preservar la relación ordinal entre las categorías. Por ejemplo, en un conjunto de datos que contiene niveles educativos como "Secundaria", "Licenciatura", "Maestría" y "Doctorado", al codificar estos niveles con números como 0, 1, 2 y 3, respectivamente, mantenemos el orden inherente de los niveles educativos. Esta representación numérica permite a los algoritmos comprender que un Doctorado (3) representa un nivel de educación más alto que una Licenciatura (1).
A continuación, un desglose más detallado de cómo funciona la codificación de etiquetas:
- Identificación: El algoritmo identifica todas las categorías únicas dentro de la característica.
- Ordenación: Para los datos ordinales, las categorías se ordenan normalmente en función de su orden natural. Para los datos nominales sin un orden claro, la ordenación puede ser alfabética o basada en el orden de aparición en el conjunto de datos.
- Asignación: A cada categoría se le asigna un número entero único, generalmente comenzando desde 0 e incrementándose en 1 para cada categoría subsecuente.
- Transformación: Los valores categóricos originales en el conjunto de datos son reemplazados por sus correspondientes codificaciones numéricas.
Es importante destacar que, si bien la codificación de etiquetas es excelente para los datos ordinales, debe usarse con precaución en las variables categóricas nominales (donde no existe un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden o magnitud inexistente, lo que podría inducir a error al modelo de aprendizaje automático.
Además, la codificación de etiquetas puede ser particularmente beneficiosa en ciertos algoritmos, como los árboles de decisión y los bosques aleatorios, que pueden manejar bien las relaciones ordinales. Sin embargo, para los algoritmos sensibles a la magnitud de las características de entrada (como la regresión lineal o las redes neuronales), podrían ser necesarias técnicas adicionales de preprocesamiento, como la normalización, después de la codificación de etiquetas.
Codificación de Etiquetas con Scikit-learn
El LabelEncoder
de Scikit-learn es una herramienta poderosa utilizada para transformar datos categóricos ordinales en números enteros. Este proceso, conocido como codificación de etiquetas, asigna un valor numérico único a cada categoría en una variable categórica. Aquí tienes una explicación más detallada:
- Funcionalidad: El
LabelEncoder
detecta automáticamente todas las categorías únicas en una característica dada y asigna a cada una un número entero único, típicamente comenzando desde 0. - Datos Ordinales: Es particularmente útil para los datos ordinales donde hay un orden claro o jerarquía entre las categorías. Por ejemplo, niveles educativos como 'Secundaria', 'Licenciatura', 'Maestría', 'Doctorado' podrían codificarse como 0, 1, 2, 3 respectivamente.
- Preservación del Orden: El codificador mantiene la relación ordinal entre las categorías, lo cual es crucial para que muchos algoritmos de aprendizaje automático interpreten correctamente los datos.
- Representación Numérica: Al convertir las categorías en enteros, permite que los modelos de aprendizaje automático que requieren entradas numéricas procesen datos categóricos de manera efectiva.
- Reversibilidad: El
LabelEncoder
también proporciona un métodoinverse_transform
, que te permite convertir los números codificados de vuelta a sus etiquetas categóricas originales cuando sea necesario. - Precaución con los Datos Nominales: Aunque es poderoso para datos ordinales, debe usarse con cautela en las variables categóricas nominales (donde no existe un orden inherente), ya que los números asignados podrían implicar un orden o magnitud inexistente.
Comprender estos aspectos del LabelEncoder
es esencial para preprocesar de manera efectiva datos categóricos ordinales en pipelines de aprendizaje automático. Una aplicación adecuada de esta herramienta puede mejorar significativamente la calidad y la interpretabilidad de tus características codificadas.
Ejemplo: Codificación de Etiquetas con Scikit-learn
from sklearn.preprocessing import LabelEncoder
import numpy as np
import pandas as pd
# Sample data
education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Bachelor', 'High School', 'PhD']
# Initialize the LabelEncoder
label_encoder = LabelEncoder()
# Fit and transform the data
education_encoded = label_encoder.fit_transform(education_levels)
# Display the encoded labels
print(f"Original labels: {education_levels}")
print(f"Encoded labels: {education_encoded}")
# Create a dictionary mapping original labels to encoded values
label_mapping = dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_)))
print(f"\nLabel mapping: {label_mapping}")
# Demonstrate inverse transform
decoded_labels = label_encoder.inverse_transform(education_encoded)
print(f"\nDecoded labels: {decoded_labels}")
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': education_levels, 'Encoded': education_encoded})
print("\nDataFrame representation:")
print(df)
# Handling unseen categories
new_education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Associate']
try:
new_encoded = label_encoder.transform(new_education_levels)
except ValueError as e:
print(f"\nError: {e}")
print("Note: LabelEncoder cannot handle unseen categories directly.")
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
LabelEncoder
de scikit-learn, que es la principal herramienta que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de LabelEncoder:
- Creamos una instancia de
LabelEncoder
llamadalabel_encoder
.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero único.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos tanto las etiquetas originales como las etiquetas codificadas para mostrar la transformación.
- Creación de un mapeo de etiquetas:
- Creamos un diccionario que mapea cada categoría original a su valor codificado.
- Esto es útil para entender cómo el codificador ha asignado valores a cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto demuestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
LabelEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo muestra varias características clave y consideraciones al utilizar LabelEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de mapear entre valores originales y codificados en ambas direcciones
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
3.3.4 Codificación Ordinal
Cuando se trabaja con variables categóricas ordinales, que son variables con categorías que tienen un orden o jerarquía natural, se puede utilizar el OrdinalEncoder de scikit-learn. Esta herramienta es ideal para manejar datos ordinales de manera efectiva.
El OrdinalEncoder asigna un número entero único a cada categoría mientras conserva el orden inherente de las mismas. Esto es crucial porque permite a los algoritmos de aprendizaje automático entender y aprovechar las relaciones significativas entre las diferentes categorías.
Por ejemplo, considera una variable que representa niveles de educación: 'Secundaria', 'Licenciatura', 'Maestría' y 'Doctorado'. El OrdinalEncoder podría asignar estos valores como 0, 1, 2 y 3 respectivamente. Esta codificación mantiene la progresión natural de los niveles de educación, lo cual puede ser información valiosa para muchos modelos de aprendizaje automático.
A diferencia de la codificación one-hot, que crea columnas binarias para cada categoría, la codificación ordinal da como resultado una sola columna de enteros. Esto puede ser especialmente útil cuando se trabaja con conjuntos de datos que tienen un gran número de variables ordinales, ya que ayuda a mantener el espacio de características más compacto.
Sin embargo, es importante tener en cuenta que aunque OrdinalEncoder es excelente para datos verdaderamente ordinales, debe usarse con precaución con variables categóricas nominales (donde no hay un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden que no existe, lo cual podría confundir al modelo de aprendizaje automático.
Codificación Ordinal con Scikit-learn
El OrdinalEncoder
de Scikit-learn es una herramienta poderosa diseñada específicamente para codificar variables categóricas ordinales, preservando su orden inherente. Este codificador es particularmente útil cuando se trabaja con variables que tienen una jerarquía o clasificación natural.
El OrdinalEncoder funciona asignando valores enteros a cada categoría en la variable ordinal, asegurando que el orden de estos enteros corresponda al orden natural de las categorías. A diferencia de otros métodos de codificación, el OrdinalEncoder mantiene las relaciones relativas entre las categorías. Por ejemplo, al codificar niveles educativos ('Secundaria', 'Licenciatura', 'Maestría', 'Doctorado'), podría asignar los valores 0, 1, 2 y 3 respectivamente, reflejando la progresión en educación.
Al convertir las categorías en números enteros, el OrdinalEncoder permite que los algoritmos de aprendizaje automático que requieren entrada numérica procesen datos ordinales de manera efectiva, conservando la información ordinal. Además, ofrece flexibilidad al permitir a los usuarios especificar un orden personalizado de las categorías, brindando control sobre cómo se representa la relación ordinal.
El codificador también es escalable, capaz de manejar múltiples características ordinales simultáneamente, lo que lo hace eficiente para conjuntos de datos con varias variables ordinales. Además, como otros codificadores de scikit-learn, el OrdinalEncoder proporciona un método inverse_transform
, que permite convertir los valores codificados de nuevo a sus categorías originales cuando sea necesario.
Ejemplo: Codificación Ordinal con Scikit-learn
from sklearn.preprocessing import OrdinalEncoder
import numpy as np
import pandas as pd
# Sample data with ordinal values
education_levels = [['High School'], ['Bachelor'], ['Master'], ['PhD'], ['High School'], ['Bachelor'], ['Master']]
# Initialize the OrdinalEncoder
ordinal_encoder = OrdinalEncoder(categories=[['High School', 'Bachelor', 'Master', 'PhD']])
# Fit and transform the data
education_encoded = ordinal_encoder.fit_transform(education_levels)
# Print the encoded values
print("Encoded education levels:")
print(education_encoded)
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': [level[0] for level in education_levels], 'Encoded': education_encoded.flatten()})
print("\nDataFrame representation:")
print(df)
# Demonstrate inverse transform
decoded_levels = ordinal_encoder.inverse_transform(education_encoded)
print("\nDecoded education levels:")
print(decoded_levels)
# Get the category order
category_order = ordinal_encoder.categories_[0]
print("\nCategory order:")
print(category_order)
# Handling unseen categories
new_education_levels = [['High School'], ['Bachelor'], ['Associate']]
try:
new_encoded = ordinal_encoder.transform(new_education_levels)
print("\nEncoded new education levels:")
print(new_encoded)
except ValueError as e:
print(f"\nError: {e}")
print("Note: OrdinalEncoder cannot handle unseen categories directly.")
Aquí tienes la traducción al español del texto proporcionado:
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
OrdinalEncoder
de scikit-learn, que es la herramienta principal que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de OrdinalEncoder:
- Creamos una instancia de
OrdinalEncoder
llamadaordinal_encoder
. - Especificamos explícitamente el orden de las categorías usando el parámetro
categories
. Esto asegura que la codificación refleje el orden natural de los niveles de educación.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero basado en el orden especificado.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos los valores codificados para mostrar la transformación.
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto muestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Obteniendo el orden de las categorías:
- Accedemos al atributo
categories_
del codificador para ver el orden de las categorías utilizado para la codificación.
- Accedemos al atributo
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
OrdinalEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo ampliado muestra varias características clave y consideraciones al utilizar OrdinalEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de especificar un orden personalizado para las categorías
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La capacidad de realizar una transformación inversa de los valores codificados a las categorías originales
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
Al utilizar solo OrdinalEncoder
de Scikit-learn, hemos demostrado un enfoque completo para la codificación ordinal, incluyendo el manejo de varios escenarios y posibles problemas.
3.3.5 Manejo de Variables Categóricas con Alta Cardinalidad
Las características de alta cardinalidad son aquellas que tienen un gran número de categorías o valores únicos. Este concepto es particularmente importante en el contexto del aprendizaje automático y la preprocesamiento de datos. Vamos a desglosarlo más:
Definición: Alta cardinalidad se refiere a columnas o características en un conjunto de datos que tienen un número muy alto de valores únicos en relación con el número de filas del conjunto de datos.
Ejemplo: Un ejemplo típico de una característica de alta cardinalidad es la columna "Ciudad" en un conjunto de datos global. Tal característica podría contener cientos o miles de nombres de ciudades únicas, cada una representando una categoría distinta.
Desafíos con la Codificación One-Hot: Al trabajar con características de alta cardinalidad, los métodos tradicionales de codificación como la codificación one-hot pueden generar problemas importantes:
- Matrices dispersas: La codificación one-hot crea una nueva columna para cada categoría única. Para características de alta cardinalidad, esto resulta en una matriz dispersa, es decir, una matriz con muchos valores cero.
- Explosión de la dimensionalidad: El número de columnas en el conjunto de datos aumenta dramáticamente, lo que puede llevar a la "maldición de la dimensionalidad".
- Ineficiencia computacional: Procesar y almacenar matrices dispersas requiere más recursos computacionales, lo que puede ralentizar significativamente el entrenamiento del modelo.
- Riesgo de sobreajuste: Con tantas características, los modelos pueden empezar a ajustar el ruido en los datos en lugar de los patrones verdaderos, aumentando el riesgo de sobreajuste.
Impacto en el rendimiento del modelo: Estos desafíos pueden afectar negativamente el rendimiento del modelo, su interpretabilidad y su capacidad de generalización.
Dado estos problemas, al trabajar con características de alta cardinalidad, a menudo es necesario utilizar técnicas alternativas de codificación o métodos de ingeniería de características para reducir la dimensionalidad al tiempo que se preserva la información importante.
a. Codificación por Frecuencia
La codificación por frecuencia es una técnica poderosa para manejar características categóricas de alta cardinalidad en el aprendizaje automático. Para cada categoría única en una característica, calcula cuántas veces aparece esa categoría en el conjunto de datos y luego reemplaza el nombre de la categoría por este valor de frecuencia. A diferencia de la codificación one-hot, que crea una nueva columna para cada categoría, la codificación por frecuencia mantiene una sola columna, lo que reduce significativamente la dimensionalidad del conjunto de datos, especialmente para características con muchas categorías únicas.
Aunque reduce la dimensionalidad, la codificación por frecuencia aún retiene información importante sobre las categorías. Las categorías más comunes obtienen valores más altos, lo que puede ser informativo para muchos algoritmos de aprendizaje automático. También maneja naturalmente las categorías raras al asignarles valores muy bajos, lo que puede ayudar a prevenir el sobreajuste a categorías raras que podrían no ser representativas de la distribución general de los datos.
Al convertir las categorías en valores numéricos, la codificación por frecuencia permite a los modelos que requieren entradas numéricas (como muchas redes neuronales) trabajar más fácilmente con datos categóricos. Sin embargo, es importante tener en cuenta que este método asume que la frecuencia de una categoría está directamente relacionada con su importancia o impacto en la variable objetivo, lo cual no siempre puede ser el caso. Este posible inconveniente debe considerarse al decidir si usar la codificación por frecuencia para un conjunto de datos o problema en particular.
En general, la codificación por frecuencia es una técnica simple pero efectiva para reducir la dimensionalidad de características categóricas de alta cardinalidad, ofreciendo un buen equilibrio entre la preservación de la información y la reducción de la dimensionalidad.
Ejemplo: Codificación por Frecuencia en Pandas
# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
# Sample data with high-cardinality categorical feature
df = pd.DataFrame({
'City': ['New York', 'London', 'Paris', 'New York', 'Paris', 'London', 'Paris', 'Tokyo', 'Berlin', 'Madrid'],
'Population': [8419000, 8982000, 2141000, 8419000, 2141000, 8982000, 2141000, 13960000, 3645000, 3223000]
})
# Calculate frequency of each category
city_frequency = df['City'].value_counts(normalize=True)
# Map the frequencies to the original data
df['City_Frequency'] = df['City'].map(city_frequency)
# Calculate mean population for each city
city_population = df.groupby('City')['Population'].mean()
# Map the mean population to the original data
df['City_Mean_Population'] = df['City'].map(city_population)
# Print the resulting DataFrame
print("Resulting DataFrame:")
print(df)
# Print frequency distribution
print("\nFrequency Distribution:")
print(city_frequency)
# Visualize frequency distribution
plt.figure(figsize=(10, 6))
city_frequency.plot(kind='bar')
plt.title('Frequency Distribution of Cities')
plt.xlabel('City')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Visualize mean population by city
plt.figure(figsize=(10, 6))
city_population.plot(kind='bar')
plt.title('Mean Population by City')
plt.xlabel('City')
plt.ylabel('Mean Population')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of new categories
new_df = pd.DataFrame({'City': ['New York', 'London', 'Sydney']})
new_df['City_Frequency'] = new_df['City'].map(city_frequency).fillna(0)
print("\nHandling new categories:")
print(new_df)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con una columna 'Ciudad' (una característica de alta cardinalidad) y una columna 'Población' para análisis adicional.
- Codificación por frecuencia:
- Calculamos la frecuencia de cada ciudad usando
value_counts(normalize=True)
. - Luego, mapeamos estas frecuencias de vuelta al DataFrame original usando
map()
.
- Calculamos la frecuencia de cada ciudad usando
- Ingeniería adicional de características:
- Calculamos la población media para cada ciudad usando
groupby()
ymean()
. - Mapeamos estas poblaciones medias de vuelta al DataFrame original.
- Calculamos la población media para cada ciudad usando
- Mostrando resultados:
- Imprimimos el DataFrame resultante para mostrar los datos originales junto con las nuevas características codificadas.
- También imprimimos la distribución de frecuencia de las ciudades.
- Visualización:
- Creamos dos gráficos de barras usando matplotlib:
a. Un gráfico que muestra la distribución de frecuencia de las ciudades.
b. Un gráfico que muestra la población media por ciudad. - Estas visualizaciones ayudan a entender la distribución de los datos categóricos y su relación con otras variables.
- Creamos dos gráficos de barras usando matplotlib:
- Manejo de nuevas categorías:
- Demostramos cómo manejar nuevas categorías que no estaban en el conjunto de datos original.
- Creamos un nuevo DataFrame con una ciudad ('Sídney') que no estaba en los datos originales.
- Usamos
map()
confillna(0)
para asignar frecuencias, dando un valor de 0 a la nueva categoría.
Este ejemplo muestra varios aspectos importantes del trabajo con datos categóricos de alta cardinalidad utilizando pandas:
- Codificación por frecuencia
- Ingeniería adicional de características (población media por categoría)
- Visualización de datos categóricos
- Manejo de nuevas categorías
Estas técnicas proporcionan un enfoque integral para manejar características de alta cardinalidad, ofreciendo tanto una reducción de la dimensionalidad como la creación de características significativas.
b. Codificación basada en el objetivo
La codificación basada en el objetivo es una técnica sofisticada utilizada en la ingeniería de características para variables categóricas. Implica reemplazar cada categoría con un valor numérico derivado de la media de la variable objetivo para esa categoría específica. Este método es especialmente valioso en tareas de aprendizaje supervisado por varias razones:
- Captura de relaciones: Captura eficazmente la relación entre la característica categórica y la variable objetivo, proporcionando al modelo una entrada más informativa.
- Reducción de la dimensionalidad: A diferencia de la codificación one-hot, la codificación basada en el objetivo no aumenta el número de características, lo que la hace adecuada para variables categóricas de alta cardinalidad.
- Poder predictivo: Los valores codificados reflejan directamente cómo se relaciona cada categoría con la variable objetivo, lo que potencialmente mejora las capacidades predictivas del modelo.
- Manejo de categorías raras: Puede manejar eficazmente categorías raras asignándoles valores basados en la variable objetivo, en lugar de crear características dispersas.
- Salida continua: La característica codificada resultante es continua, lo cual puede ser beneficioso para ciertos algoritmos que funcionan mejor con entradas numéricas.
Sin embargo, es importante tener en cuenta que la codificación basada en el objetivo debe usarse con precaución:
- Potencial de sobreajuste: Puede conducir al sobreajuste si no se valida adecuadamente, ya que utiliza información del objetivo en el paso de preprocesamiento.
- Fugas de datos: Se debe tener cuidado para evitar fugas de datos asegurando que la codificación se realice dentro de los pliegues de la validación cruzada.
- Interpretabilidad: Los valores codificados pueden ser menos interpretables que las categorías originales, lo que podría ser una desventaja en algunas aplicaciones donde la explicabilidad del modelo es crucial.
En general, la codificación basada en el objetivo es una herramienta poderosa que, cuando se usa adecuadamente, puede mejorar significativamente el rendimiento de los modelos de aprendizaje automático en datos categóricos.
Ejemplo: Codificación basada en el objetivo con Category Encoders
import category_encoders as ce
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# Create a larger sample dataset
np.random.seed(42)
cities = ['New York', 'London', 'Paris', 'Tokyo', 'Berlin']
n_samples = 1000
df = pd.DataFrame({
'City': np.random.choice(cities, n_samples),
'Target': np.random.randint(0, 2, n_samples)
})
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(df['City'], df['Target'], test_size=0.2, random_state=42)
# Initialize the TargetEncoder
target_encoder = ce.TargetEncoder()
# Fit and transform the training data
X_train_encoded = target_encoder.fit_transform(X_train, y_train)
# Transform the test data
X_test_encoded = target_encoder.transform(X_test)
# Train a logistic regression model
model = LogisticRegression(random_state=42)
model.fit(X_train_encoded, y_train)
# Make predictions on the test set
y_pred = model.predict(X_test_encoded)
# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Model Accuracy: {accuracy:.2f}")
# Display the encoding for each city
encoding_map = target_encoder.mapping[0]['mapping']
print("\nTarget Encoding Map:")
for city, encoded_value in encoding_map.items():
print(f"{city}: {encoded_value:.4f}")
# Visualize the target encoding
plt.figure(figsize=(10, 6))
plt.bar(encoding_map.keys(), encoding_map.values())
plt.title('Target Encoding of Cities')
plt.xlabel('City')
plt.ylabel('Encoded Value')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of unseen categories
new_cities = pd.Series(['New York', 'London', 'San Francisco'])
encoded_new_cities = target_encoder.transform(new_cities)
print("\nEncoding of New Cities (including unseen):")
print(encoded_new_cities)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos bibliotecas adicionales, incluyendo numpy para la generación de números aleatorios, sklearn para el entrenamiento y evaluación del modelo, y matplotlib para la visualización.
- Creación de un conjunto de datos más grande:
- Generamos un conjunto de datos de muestra más grande con 1000 entradas y 5 ciudades diferentes para demostrar mejor el proceso de codificación basada en el objetivo.
- La variable 'Objetivo' es generada aleatoriamente como 0 o 1 para simular un problema de clasificación binaria.
- División de los datos:
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
train_test_split
para evaluar correctamente nuestra codificación y el modelo.
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
- Codificación basada en el objetivo:
- Usamos
TargetEncoder
de la bibliotecacategory_encoders
para realizar la codificación basada en el objetivo. - El codificador se ajusta a los datos de entrenamiento y luego se usa para transformar tanto los datos de entrenamiento como los de prueba.
- Usamos
- Entrenamiento y evaluación del modelo:
- Entrenamos un modelo de regresión logística con los datos codificados.
- El modelo se usa luego para hacer predicciones en el conjunto de prueba, y calculamos su precisión.
- Visualización de la codificación:
- Extraemos el mapa de codificación del
TargetEncoder
para ver cómo se codificó cada ciudad. - Se crea un gráfico de barras para visualizar los valores codificados de cada ciudad.
- Extraemos el mapa de codificación del
- Manejo de categorías no vistas:
- Demostramos cómo
TargetEncoder
maneja nuevas categorías que no estaban presentes en los datos de entrenamiento.
- Demostramos cómo
Este ejemplo ofrece una visión más completa de la codificación basada en el objetivo, incluyendo:
- Trabajar con un conjunto de datos más grande y realista
- División adecuada en entrenamiento y prueba para evitar fugas de datos
- Entrenamiento y evaluación reales de un modelo utilizando las características codificadas
- Visualización de los resultados de la codificación
- Manejo de categorías no vistas
Este enfoque proporciona una imagen más completa de cómo se puede aplicar la codificación basada en el objetivo en una canalización de aprendizaje automático y sus efectos en el rendimiento del modelo.
3.3.6 Manejo de Datos Categóricos Faltantes
Los valores faltantes en los datos categóricos suponen un desafío importante en la fase de preprocesamiento de proyectos de aprendizaje automático. Estas lagunas en el conjunto de datos pueden afectar significativamente la precisión y fiabilidad del modelo si no se abordan adecuadamente. La presencia de valores faltantes puede llevar a resultados sesgados, reducción de la potencia estadística y conclusiones incorrectas. Por lo tanto, es crucial manejarlos con cuidado y consideración.
Existen varias estrategias para tratar los datos categóricos faltantes, cada una con sus ventajas y posibles inconvenientes:
- Eliminación: Implica eliminar filas o columnas con valores faltantes. Aunque es simple, puede llevar a la pérdida de información valiosa.
- Imputación: Este método implica llenar los valores faltantes con estimaciones. Algunas técnicas comunes incluyen imputación por moda, imputación mediante un modelo de predicción, o el uso de una categoría dedicada como "Faltante".
- Métodos avanzados: Incluyen el uso de algoritmos que pueden manejar directamente los valores faltantes o técnicas de imputación múltiple que tienen en cuenta la incertidumbre en los datos faltantes.
La elección de la estrategia depende de factores como la cantidad de datos faltantes, el mecanismo de la falta de datos (si es completamente al azar, al azar, o no al azar), y los requisitos específicos de tu tarea de aprendizaje automático. A menudo es beneficioso experimentar con múltiples enfoques y evaluar su impacto en el rendimiento de tu modelo.
a. Imputación de valores faltantes con la moda
Para datos categóricos nominales, un enfoque común es reemplazar los valores faltantes con la categoría más frecuente (moda).
Ejemplo: Imputación de valores categóricos faltantes
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
# Sample data with missing values
df = pd.DataFrame({
'City': ['New York', 'London', None, 'Paris', 'Paris', 'London', None, 'Tokyo', 'Berlin', None],
'Population': [8400000, 8900000, None, 2100000, 2100000, 8900000, None, 13900000, 3700000, None],
'IsCapital': [False, True, None, True, True, True, None, True, True, None]
})
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Method 1: Fill missing values with the mode (most frequent value)
df['City_Mode'] = df['City'].fillna(df['City'].mode()[0])
# Method 2: Fill missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# Method 3: Use SimpleImputer for numerical data (Population)
imputer = SimpleImputer(strategy='mean')
df['Population_Imputed'] = imputer.fit_transform(df[['Population']])
# Method 4: Forward fill for IsCapital (assuming temporal order)
df['IsCapital_Ffill'] = df['IsCapital'].ffill()
print("\nDataFrame after handling missing values:")
print(df)
# Visualize missing data
plt.figure(figsize=(10, 6))
plt.imshow(df.isnull(), cmap='viridis', aspect='auto')
plt.title('Missing Value Heatmap')
plt.xlabel('Columns')
plt.ylabel('Rows')
plt.colorbar(label='Missing (Yellow)')
plt.tight_layout()
plt.show()
# Compare original and imputed data distributions
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['Population'].hist(ax=ax1, bins=10)
ax1.set_title('Original Population Distribution')
ax1.set_xlabel('Population')
ax1.set_ylabel('Frequency')
df['Population_Imputed'].hist(ax=ax2, bins=10)
ax2.set_title('Imputed Population Distribution')
ax2.set_xlabel('Population')
ax2.set_ylabel('Frequency')
plt.tight_layout()
plt.show()
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
SimpleImputer
de sklearn para la imputación de valores numéricos.
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
None
).
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
- Mostrando los datos originales:
- Imprimimos el DataFrame original y la cantidad de valores faltantes en cada columna.
- Manejo de valores faltantes:
- Método 1 (Imputación por moda): Rellenamos los valores faltantes en la columna 'Ciudad' con la ciudad más frecuente.
- Método 2 (Nueva categoría): Creamos una nueva columna donde las ciudades faltantes se reemplazan por 'Desconocido'.
- Método 3 (Imputación por media): Utilizamos
SimpleImputer
para rellenar los valores faltantes en la columna 'Población' con la media de la población. - Método 4 (Relleno hacia adelante): Utilizamos el método de relleno hacia adelante para la columna 'EsCapital', asumiendo un orden temporal en los datos.
- Visualización de datos faltantes:
- Creamos un mapa de calor para visualizar el patrón de valores faltantes en todo el DataFrame.
- Comparación de distribuciones:
- Creamos histogramas para comparar la distribución de los datos originales de 'Población' con los datos imputados.
Este ejemplo demuestra múltiples técnicas para manejar datos faltantes tanto categóricos como numéricos, incluyendo:
- Imputación por moda para datos categóricos
- Creación de una nueva categoría para valores faltantes
- Imputación por media para datos numéricos usando
SimpleImputer
- Relleno hacia adelante para datos potencialmente ordenados
- Visualización de patrones de datos faltantes
- Comparación de las distribuciones de los datos originales e imputados
Estas técnicas proporcionan un enfoque integral para tratar los datos faltantes, mostrando tanto los métodos de manejo como formas de analizar el impacto de estos métodos en tu conjunto de datos.
b. Usando una categoría separada para datos faltantes
Otra estrategia para manejar valores faltantes en datos categóricos es crear una categoría separada, comúnmente etiquetada como "Desconocido" o "Faltante". Este método implica introducir una nueva categoría específicamente para representar los puntos de datos faltantes. Al hacerlo, se reconoce explícitamente la ausencia de información y se trata como una categoría distinta en sí misma.
Este enfoque ofrece varias ventajas:
- Preservación de información: Retiene el hecho de que los datos estaban faltantes, lo cual podría ser significativo en ciertos análisis.
- Interpretabilidad del modelo: Permite que los modelos aprendan patrones asociados con los datos faltantes.
- Simplicidad: Es fácil de implementar y comprender.
- Consistencia: Proporciona una manera uniforme de manejar valores faltantes en diferentes variables categóricas.
Sin embargo, es importante considerar posibles desventajas:
- Aumento de la dimensionalidad: Para datos codificados con one-hot encoding, agrega una dimensión adicional.
- Posible sesgo: Si los datos faltantes no son aleatorios, este método podría introducir sesgo.
- Pérdida de potencia estadística: En algunos análisis, tratar los datos faltantes como una categoría separada podría reducir la potencia estadística.
Al decidir si usar este enfoque, considera la naturaleza de tus datos, la razón de la falta de datos y los requisitos específicos de tu análisis o tarea de aprendizaje automático.
Ejemplo: Reemplazo de valores faltantes con una nueva categoría
import pandas as pd
import matplotlib.pyplot as plt
# Create a sample dataset with missing values
data = {
'City': ['New York', 'London', None, 'Paris', 'Tokyo', None, 'Berlin', 'Madrid', None, 'Rome'],
'Population': [8.4, 9.0, None, 2.2, 13.9, None, 3.7, 3.2, None, 4.3],
'IsCapital': [False, True, None, True, True, None, True, True, None, True]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Replace missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# For numerical data, we can use mean imputation
df['Population_Imputed'] = df['Population'].fillna(df['Population'].mean())
# For boolean data, we can use mode imputation
df['IsCapital_Imputed'] = df['IsCapital'].fillna(df['IsCapital'].mode()[0])
print("\nDataFrame after handling missing values:")
print(df)
# Visualize the distribution of cities before and after imputation
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['City'].value_counts().plot(kind='bar', ax=ax1, title='City Distribution (Before)')
ax1.set_ylabel('Count')
df['City_Unknown'].value_counts().plot(kind='bar', ax=ax2, title='City Distribution (After)')
ax2.set_ylabel('Count')
plt.tight_layout()
plt.show()
# Analyze the impact of imputation on Population
print("\nPopulation statistics before imputation:")
print(df['Population'].describe())
print("\nPopulation statistics after imputation:")
print(df['Population_Imputed'].describe())
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana).
- El conjunto de datos incluye valores faltantes (None) para demostrar diferentes técnicas de imputación.
- Mostrando los datos originales:
- Imprimimos el DataFrame original y contamos los valores faltantes en cada columna.
- Manejo de valores faltantes:
- Para la columna 'Ciudad', creamos una nueva columna 'Ciudad_Desconocida', donde los valores faltantes se reemplazan por 'Desconocido'.
- Para la columna 'Población', usamos imputación por media para rellenar los valores faltantes.
- Para la columna 'EsCapital', utilizamos imputación por moda para completar los valores faltantes.
- Visualización de los datos:
- Creamos gráficos de barras para comparar la distribución de las ciudades antes y después de la imputación.
- Esto ayuda a visualizar el impacto de agregar la categoría 'Desconocido'.
- Análisis del impacto de la imputación:
- Imprimimos estadísticas descriptivas de la columna 'Población' antes y después de la imputación.
- Esto nos permite ver cómo la imputación por media afecta la distribución general de los datos.
Este ejemplo ampliado demuestra un enfoque más integral para manejar datos faltantes, incluyendo:
- Uso de una nueva categoría ('Desconocido') para datos faltantes categóricos
- Aplicación de imputación por media para datos numéricos
- Uso de imputación por moda para datos booleanos
- Visualización del impacto de la imputación en los datos categóricos
- Análisis del impacto estadístico de la imputación en los datos numéricos
Este enfoque proporciona una visión completa de cómo aplicar diferentes técnicas de imputación y sus efectos en el conjunto de datos, lo cual es crucial para comprender los impactos potenciales en los análisis o modelos de aprendizaje automático posteriores.
Este enfoque marca explícitamente los datos faltantes, lo que a veces puede ayudar a los modelos a aprender que la falta de datos es significativa.
3.3 Codificación y Manejo de Datos Categóricos
En el ámbito de los conjuntos de datos del mundo real, los datos categóricos son una ocurrencia común. Estas características representan categorías o etiquetas distintas, a diferencia de los valores numéricos continuos. El manejo adecuado de los datos categóricos es de suma importancia, ya que la gran mayoría de los algoritmos de aprendizaje automático están diseñados para trabajar con entradas numéricas. Una codificación incorrecta de las variables categóricas puede tener consecuencias graves, potencialmente conduciendo a un rendimiento subóptimo del modelo o incluso a errores durante el proceso de entrenamiento.
Esta sección explora una variedad de técnicas para codificar y gestionar datos categóricos. Exploraremos métodos fundamentales como la codificación one-hot y la codificación por etiquetas, así como enfoques más matizados como la codificación ordinal.
Además, nos adentraremos en técnicas avanzadas, como la codificación por objetivo, que puede ser particularmente útil en ciertos escenarios. También abordaremos los desafíos que plantean las variables categóricas de alta cardinalidad y discutiremos estrategias efectivas para gestionarlas. Al dominar estas técnicas, estarás bien preparado para manejar una amplia gama de escenarios de datos categóricos en tus proyectos de aprendizaje automático.
3.3.1 Entendiendo los Datos Categóricos
Las características categóricas son un concepto fundamental en ciencia de datos y aprendizaje automático, que representan variables que pueden tomar un número limitado de valores o categorías distintas. A diferencia de las variables continuas que pueden tomar cualquier valor numérico dentro de un rango, las variables categóricas son discretas y, a menudo, cualitativas por naturaleza. Comprender estas características es crucial para una preprocesamiento eficaz de los datos y el desarrollo de modelos.
Las características categóricas se pueden clasificar en dos tipos principales:
- Nominales (Sin Orden): Estas categorías no tienen un orden o clasificación inherente. Cada categoría es distinta e independiente de las demás. Por ejemplo:
- Colores: "Rojo", "Verde", "Azul"
- Tipos de sangre: "A", "B", "AB", "O"
- Géneros musicales: "Rock", "Jazz", "Clásico", "Hip-hop"
En estos casos, no hay una manera significativa de decir que una categoría es "mayor" o "menor" que otra.
- Ordinales (Con Orden): Estas categorías tienen un orden o clasificación claro y significativo, aunque los intervalos entre las categorías pueden no ser consistentes o medibles. Algunos ejemplos incluyen:
- Niveles educativos: "Secundaria", "Licenciatura", "Maestría", "Doctorado"
- Satisfacción del cliente: "Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"
- Tallas de camiseta: "XS", "S", "M", "L", "XL"
Aquí, hay una progresión clara de una categoría a otra, incluso si la "distancia" entre categorías no es cuantificable.
La distinción entre categorías nominales y ordinales es crucial porque determina cómo debemos manejar y codificar estas características para los algoritmos de aprendizaje automático. La mayoría de los algoritmos esperan entradas numéricas, por lo que necesitamos convertir los datos categóricos en un formato numérico. Sin embargo, el método de codificación que elijamos puede afectar significativamente el rendimiento y la interpretación del modelo.
Para las categorías nominales, se suelen utilizar técnicas como la codificación one-hot o la codificación por etiquetas. La codificación one-hot crea columnas binarias para cada categoría, mientras que la codificación por etiquetas asigna un entero único a cada categoría. Para las categorías ordinales, podríamos usar la codificación ordinal para preservar la información del orden, o emplear técnicas más avanzadas como la codificación por objetivo.
En las siguientes secciones, profundizaremos en estos métodos de codificación, explorando sus fortalezas, debilidades y casos de uso apropiados. Comprender estas técnicas es esencial para preprocesar eficazmente los datos categóricos y construir modelos de aprendizaje automático robustos.
3.3.2 Codificación One-Hot
La codificación one-hot es un método fundamental y ampliamente utilizado para transformar variables categóricas nominales en un formato numérico que pueda ser utilizado fácilmente por los algoritmos de aprendizaje automático. Esta técnica es particularmente valiosa porque la mayoría de los modelos de aprendizaje automático están diseñados para trabajar con entradas numéricas en lugar de datos categóricos.
Así es como funciona la codificación one-hot:
- Para cada categoría única en la característica original, se crea una nueva columna binaria.
- En estas nuevas columnas, un valor de 1 indica la presencia de la categoría correspondiente para un dato, mientras que un valor de 0 indica su ausencia.
- Este proceso crea un conjunto de características binarias que, en conjunto, representan la variable categórica original.
Por ejemplo, si tenemos una característica "Color" con categorías "Rojo", "Azul" y "Verde", la codificación one-hot crearía tres nuevas columnas: "Color_Rojo", "Color_Azul" y "Color_Verde". Cada fila en el conjunto de datos tendría un 1 en una de estas columnas y 0 en las otras, dependiendo del valor de color original.
La codificación one-hot es particularmente adecuada para variables nominales, que son variables categóricas en las que no existe un orden o clasificación inherente entre las categorías. Ejemplos de tales variables incluyen:
- Nombres de ciudades (p. ej., Nueva York, Londres, Tokio)
- Tipos de productos (p. ej., Electrónica, Ropa, Libros)
- Especies de animales (p. ej., Perro, Gato, Pájaro)
La principal ventaja de la codificación one-hot es que no impone ningún orden artificial a las categorías, lo cual es crucial para las variables nominales. Cada categoría se trata como una característica separada e independiente, lo que permite que los modelos de aprendizaje automático aprendan la importancia de cada categoría por separado.
Sin embargo, es importante tener en cuenta que la codificación one-hot puede generar datos de alta dimensionalidad cuando se trabaja con variables categóricas que tienen muchas categorías únicas. Esto puede resultar en la "maldición de la dimensionalidad" y puede requerir técnicas adicionales de selección de características o reducción de dimensionalidad en algunos casos.
a. Codificación One-Hot con Pandas
Pandas, una biblioteca poderosa para la manipulación de datos en Python, proporciona un método simple y eficiente para aplicar la codificación one-hot utilizando la función get_dummies()
. Esta función es particularmente útil para convertir variables categóricas en un formato adecuado para los algoritmos de aprendizaje automático.
Así es como funciona get_dummies()
:
- Detecta automáticamente las columnas categóricas en tu DataFrame.
- Para cada categoría única en una columna, crea una nueva columna binaria.
- En estas nuevas columnas, asigna un 1 donde la categoría está presente y 0 donde está ausente.
- La columna categórica original se elimina y se reemplaza por estas nuevas columnas binarias.
La función get_dummies()
ofrece varias ventajas:
- Simplicidad: Requiere un código mínimo, lo que facilita su uso incluso para principiantes.
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente.
- Personalización: Ofrece opciones para personalizar el proceso de codificación, como especificar prefijos de columna o manejar categorías desconocidas.
Al utilizar get_dummies()
, puedes transformar rápidamente los datos categóricos en un formato numérico listo para ser utilizado en diversos modelos de aprendizaje automático, agilizando tu flujo de trabajo de preprocesamiento de datos.
Ejemplo: Codificación One-Hot con Pandas
import pandas as pd
import numpy as np
# Create a more comprehensive sample dataset
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', 'New York', 'London', 'Paris'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, 8419000, 8982000, 2141000],
'Continent': ['North America', 'Europe', 'Europe', 'Asia', 'Europe', 'North America', 'Europe', 'Europe']
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Apply one-hot encoding to the 'City' column
city_encoded = pd.get_dummies(df['City'], prefix='City')
# Apply one-hot encoding to the 'Continent' column
continent_encoded = pd.get_dummies(df['Continent'], prefix='Continent')
# Concatenate the encoded columns with the original DataFrame
df_encoded = pd.concat([df, city_encoded, continent_encoded], axis=1)
print("DataFrame after one-hot encoding:")
print(df_encoded)
print("\n")
# Demonstrate handling of high-cardinality columns
df['UniqueID'] = np.arange(len(df))
high_cardinality_encoded = pd.get_dummies(df['UniqueID'], prefix='ID')
df_high_cardinality = pd.concat([df, high_cardinality_encoded], axis=1)
print("DataFrame with high-cardinality column encoded:")
print(df_high_cardinality.head())
print("\n")
# Demonstrate handling of missing values
df_missing = df.copy()
df_missing.loc[1, 'City'] = np.nan
df_missing.loc[3, 'Continent'] = np.nan
print("DataFrame with missing values:")
print(df_missing)
print("\n")
# Handle missing values before encoding
df_missing['City'] = df_missing['City'].fillna('Unknown')
df_missing['Continent'] = df_missing['Continent'].fillna('Unknown')
# Apply one-hot encoding to the DataFrame with handled missing values
df_missing_encoded = pd.get_dummies(df_missing, columns=['City', 'Continent'], prefix=['City', 'Continent'])
print("DataFrame with missing values handled and encoded:")
print(df_missing_encoded)
Este ejemplo de código demuestra un enfoque integral de la codificación one-hot utilizando pandas.
A continuación, se desglosa detalladamente el código y su funcionalidad:
- Preparación de Datos:
- Creamos un conjunto de datos más completo con varias columnas: 'City', 'Population' y 'Continent'.
- Esto nos permite demostrar la codificación para diferentes tipos de variables categóricas.
- Codificación Básica One-Hot:
- Utilizamos
pd.get_dummies()
para codificar las columnas 'City' y 'Continent' por separado. - Se usa el parámetro
prefix
para distinguir las columnas codificadas (por ejemplo, 'City_New York', 'Continent_Europe'). - Luego concatenamos estas columnas codificadas con el DataFrame original.
- Utilizamos
- Manejo de Columnas con Alta Cardinalidad:
- Creamos una columna 'UniqueID' para simular una característica con alta cardinalidad.
- Demostramos cómo la codificación one-hot puede generar un gran número de columnas para características con alta cardinalidad.
- Esto resalta los posibles problemas de uso de memoria y eficiencia computacional en estos casos.
- Manejo de Valores Faltantes:
- Introducimos valores faltantes en las columnas 'City' y 'Continent'.
- Antes de codificar, rellenamos los valores faltantes con 'Unknown' utilizando el método
fillna()
. - Esto asegura que los valores faltantes se traten como una categoría separada durante la codificación.
- Luego aplicamos la codificación one-hot al DataFrame con los valores faltantes gestionados.
- Visualización de Resultados:
- En cada paso, imprimimos el DataFrame para mostrar cómo cambia después de cada operación.
- Esto ayuda a comprender el efecto de cada paso de codificación en la estructura de los datos.
Este ejemplo integral cubre varios aspectos de la codificación one-hot, incluidos el manejo de múltiples columnas categóricas, el tratamiento de características con alta cardinalidad y la gestión de valores faltantes. Proporciona una demostración práctica de cómo utilizar pandas para estas tareas en un escenario del mundo real.
La función get_dummies()
convierte la columna "City" en columnas binarias separadas: City_New York
, City_London
y City_Paris
, que representan cada ciudad. Esto permite que el modelo de aprendizaje automático interprete la característica categórica numéricamente.
b. Codificación One-Hot con Scikit-learn
Scikit-learn ofrece una implementación robusta de la codificación one-hot a través de la clase OneHotEncoder
. Esta clase proporciona un enfoque más flexible y poderoso para codificar variables categóricas, particularmente útil en pipelines complejos de aprendizaje automático o cuando se requiere un control más detallado sobre el proceso de codificación.
La clase OneHotEncoder
destaca por varias razones:
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente, lo que la hace eficiente para conjuntos de datos con numerosas características categóricas.
- Salida en Matriz Dispersa: De forma predeterminada, devuelve una matriz dispersa, lo que es eficiente en términos de memoria para conjuntos de datos con muchas categorías.
- Manejo de Categorías Desconocidas: Ofrece opciones para manejar categorías que no estaban presentes durante el proceso de ajuste, crucial para aplicaciones del mundo real donde pueden aparecer nuevas categorías en los datos de prueba.
- Integración con Pipelines de Scikit-learn: Se integra perfectamente con la clase
Pipeline
de Scikit-learn, lo que permite una fácil combinación con otros pasos de preprocesamiento y modelos.
Cuando se trabaja con pipelines de aprendizaje automático, el OneHotEncoder
puede ser especialmente valioso. Permite definir un esquema de codificación consistente que se puede aplicar de manera uniforme a los conjuntos de datos de entrenamiento y prueba, asegurando que el modelo reciba datos de entrada con un formato consistente.
Para escenarios que requieren más control, el OneHotEncoder
ofrece varios parámetros para personalizar su comportamiento. Por ejemplo, se puede especificar cómo manejar las categorías desconocidas, si usar un formato de salida disperso o denso, e incluso definir una codificación personalizada para características específicas.
Ejemplo: Codificación One-Hot con Scikit-learn
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
import pandas as pd
import numpy as np
# Sample data
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', np.nan],
'Country': ['USA', 'UK', 'France', 'Japan', 'Germany', 'USA'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, np.nan]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Define transformers for categorical and numerical data
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(sparse=False, handle_unknown='ignore'))
])
numerical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean'))
])
# Combine transformers into a ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('cat', categorical_transformer, ['City', 'Country']),
('num', numerical_transformer, ['Population'])
]
)
# Apply the preprocessing pipeline
transformed_data = preprocessor.fit_transform(df)
# Get feature names
onehot_features_city = preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(['City', 'Country'])
numerical_features = ['Population']
feature_names = np.concatenate([onehot_features_city, numerical_features])
# Create a new DataFrame with transformed data
df_encoded = pd.DataFrame(transformed_data, columns=feature_names)
print("Transformed DataFrame:")
print(df_encoded)
Explicación del Desglose del Código:
- Manejo de Valores Faltantes:
- Las columnas categóricas (
City
yCountry
) se rellenan con el valor más frecuente. - La columna numérica (
Population
) se rellena con el valor medio.
- Las columnas categóricas (
- Codificación One-Hot:
- Las columnas categóricas (
City
,Country
) se codifican mediante one-hot, convirtiéndolas en columnas binarias.
- Las columnas categóricas (
- Pipeline con
ColumnTransformer
:- Combina los pasos de preprocesamiento categórico y numérico en un único pipeline.
- Nombres de Características:
- Recupera automáticamente nombres significativos para las características codificadas.
- Resultado Final:
- Se crea un DataFrame limpio y completamente preprocesado (
df_encoded
), listo para análisis o modelado.
- Se crea un DataFrame limpio y completamente preprocesado (
Este ejemplo muestra varias características clave de las capacidades de preprocesamiento de Scikit-learn:
- Manejo de datos faltantes con SimpleImputer
- Codificación one-hot de categorías nominales ('City')
- Codificación de etiquetas de categorías ordinales ('Country')
- Uso de ColumnTransformer para aplicar diferentes transformaciones a diferentes columnas
- Pipeline para encadenar múltiples pasos de preprocesamiento
- Extracción de nombres de características después de la transformación
- Transformación inversa para recuperar las categorías originales de los datos codificados
Este enfoque proporciona un método robusto y escalable para preprocesar tipos de datos mixtos, manejar valores faltantes y preparar datos para modelos de aprendizaje automático.
En este caso, OneHotEncoder
convierte los datos categóricos en una matriz densa de valores binarios, que pueden pasarse directamente a los modelos de aprendizaje automático.
3.3.3 Codificación de Etiquetas (Label Encoding)
La codificación de etiquetas es una técnica que asigna un número entero único a cada categoría en una característica categórica. Este método es particularmente útil para variables categóricas ordinales, donde existe un orden o jerarquía significativa entre las categorías. Al convertir las categorías en valores numéricos, la codificación de etiquetas permite que los algoritmos de aprendizaje automático interpreten y procesen los datos categóricos de manera más efectiva.
La principal ventaja de la codificación de etiquetas radica en su capacidad para preservar la relación ordinal entre las categorías. Por ejemplo, en un conjunto de datos que contiene niveles educativos como "Secundaria", "Licenciatura", "Maestría" y "Doctorado", al codificar estos niveles con números como 0, 1, 2 y 3, respectivamente, mantenemos el orden inherente de los niveles educativos. Esta representación numérica permite a los algoritmos comprender que un Doctorado (3) representa un nivel de educación más alto que una Licenciatura (1).
A continuación, un desglose más detallado de cómo funciona la codificación de etiquetas:
- Identificación: El algoritmo identifica todas las categorías únicas dentro de la característica.
- Ordenación: Para los datos ordinales, las categorías se ordenan normalmente en función de su orden natural. Para los datos nominales sin un orden claro, la ordenación puede ser alfabética o basada en el orden de aparición en el conjunto de datos.
- Asignación: A cada categoría se le asigna un número entero único, generalmente comenzando desde 0 e incrementándose en 1 para cada categoría subsecuente.
- Transformación: Los valores categóricos originales en el conjunto de datos son reemplazados por sus correspondientes codificaciones numéricas.
Es importante destacar que, si bien la codificación de etiquetas es excelente para los datos ordinales, debe usarse con precaución en las variables categóricas nominales (donde no existe un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden o magnitud inexistente, lo que podría inducir a error al modelo de aprendizaje automático.
Además, la codificación de etiquetas puede ser particularmente beneficiosa en ciertos algoritmos, como los árboles de decisión y los bosques aleatorios, que pueden manejar bien las relaciones ordinales. Sin embargo, para los algoritmos sensibles a la magnitud de las características de entrada (como la regresión lineal o las redes neuronales), podrían ser necesarias técnicas adicionales de preprocesamiento, como la normalización, después de la codificación de etiquetas.
Codificación de Etiquetas con Scikit-learn
El LabelEncoder
de Scikit-learn es una herramienta poderosa utilizada para transformar datos categóricos ordinales en números enteros. Este proceso, conocido como codificación de etiquetas, asigna un valor numérico único a cada categoría en una variable categórica. Aquí tienes una explicación más detallada:
- Funcionalidad: El
LabelEncoder
detecta automáticamente todas las categorías únicas en una característica dada y asigna a cada una un número entero único, típicamente comenzando desde 0. - Datos Ordinales: Es particularmente útil para los datos ordinales donde hay un orden claro o jerarquía entre las categorías. Por ejemplo, niveles educativos como 'Secundaria', 'Licenciatura', 'Maestría', 'Doctorado' podrían codificarse como 0, 1, 2, 3 respectivamente.
- Preservación del Orden: El codificador mantiene la relación ordinal entre las categorías, lo cual es crucial para que muchos algoritmos de aprendizaje automático interpreten correctamente los datos.
- Representación Numérica: Al convertir las categorías en enteros, permite que los modelos de aprendizaje automático que requieren entradas numéricas procesen datos categóricos de manera efectiva.
- Reversibilidad: El
LabelEncoder
también proporciona un métodoinverse_transform
, que te permite convertir los números codificados de vuelta a sus etiquetas categóricas originales cuando sea necesario. - Precaución con los Datos Nominales: Aunque es poderoso para datos ordinales, debe usarse con cautela en las variables categóricas nominales (donde no existe un orden inherente), ya que los números asignados podrían implicar un orden o magnitud inexistente.
Comprender estos aspectos del LabelEncoder
es esencial para preprocesar de manera efectiva datos categóricos ordinales en pipelines de aprendizaje automático. Una aplicación adecuada de esta herramienta puede mejorar significativamente la calidad y la interpretabilidad de tus características codificadas.
Ejemplo: Codificación de Etiquetas con Scikit-learn
from sklearn.preprocessing import LabelEncoder
import numpy as np
import pandas as pd
# Sample data
education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Bachelor', 'High School', 'PhD']
# Initialize the LabelEncoder
label_encoder = LabelEncoder()
# Fit and transform the data
education_encoded = label_encoder.fit_transform(education_levels)
# Display the encoded labels
print(f"Original labels: {education_levels}")
print(f"Encoded labels: {education_encoded}")
# Create a dictionary mapping original labels to encoded values
label_mapping = dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_)))
print(f"\nLabel mapping: {label_mapping}")
# Demonstrate inverse transform
decoded_labels = label_encoder.inverse_transform(education_encoded)
print(f"\nDecoded labels: {decoded_labels}")
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': education_levels, 'Encoded': education_encoded})
print("\nDataFrame representation:")
print(df)
# Handling unseen categories
new_education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Associate']
try:
new_encoded = label_encoder.transform(new_education_levels)
except ValueError as e:
print(f"\nError: {e}")
print("Note: LabelEncoder cannot handle unseen categories directly.")
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
LabelEncoder
de scikit-learn, que es la principal herramienta que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de LabelEncoder:
- Creamos una instancia de
LabelEncoder
llamadalabel_encoder
.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero único.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos tanto las etiquetas originales como las etiquetas codificadas para mostrar la transformación.
- Creación de un mapeo de etiquetas:
- Creamos un diccionario que mapea cada categoría original a su valor codificado.
- Esto es útil para entender cómo el codificador ha asignado valores a cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto demuestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
LabelEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo muestra varias características clave y consideraciones al utilizar LabelEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de mapear entre valores originales y codificados en ambas direcciones
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
3.3.4 Codificación Ordinal
Cuando se trabaja con variables categóricas ordinales, que son variables con categorías que tienen un orden o jerarquía natural, se puede utilizar el OrdinalEncoder de scikit-learn. Esta herramienta es ideal para manejar datos ordinales de manera efectiva.
El OrdinalEncoder asigna un número entero único a cada categoría mientras conserva el orden inherente de las mismas. Esto es crucial porque permite a los algoritmos de aprendizaje automático entender y aprovechar las relaciones significativas entre las diferentes categorías.
Por ejemplo, considera una variable que representa niveles de educación: 'Secundaria', 'Licenciatura', 'Maestría' y 'Doctorado'. El OrdinalEncoder podría asignar estos valores como 0, 1, 2 y 3 respectivamente. Esta codificación mantiene la progresión natural de los niveles de educación, lo cual puede ser información valiosa para muchos modelos de aprendizaje automático.
A diferencia de la codificación one-hot, que crea columnas binarias para cada categoría, la codificación ordinal da como resultado una sola columna de enteros. Esto puede ser especialmente útil cuando se trabaja con conjuntos de datos que tienen un gran número de variables ordinales, ya que ayuda a mantener el espacio de características más compacto.
Sin embargo, es importante tener en cuenta que aunque OrdinalEncoder es excelente para datos verdaderamente ordinales, debe usarse con precaución con variables categóricas nominales (donde no hay un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden que no existe, lo cual podría confundir al modelo de aprendizaje automático.
Codificación Ordinal con Scikit-learn
El OrdinalEncoder
de Scikit-learn es una herramienta poderosa diseñada específicamente para codificar variables categóricas ordinales, preservando su orden inherente. Este codificador es particularmente útil cuando se trabaja con variables que tienen una jerarquía o clasificación natural.
El OrdinalEncoder funciona asignando valores enteros a cada categoría en la variable ordinal, asegurando que el orden de estos enteros corresponda al orden natural de las categorías. A diferencia de otros métodos de codificación, el OrdinalEncoder mantiene las relaciones relativas entre las categorías. Por ejemplo, al codificar niveles educativos ('Secundaria', 'Licenciatura', 'Maestría', 'Doctorado'), podría asignar los valores 0, 1, 2 y 3 respectivamente, reflejando la progresión en educación.
Al convertir las categorías en números enteros, el OrdinalEncoder permite que los algoritmos de aprendizaje automático que requieren entrada numérica procesen datos ordinales de manera efectiva, conservando la información ordinal. Además, ofrece flexibilidad al permitir a los usuarios especificar un orden personalizado de las categorías, brindando control sobre cómo se representa la relación ordinal.
El codificador también es escalable, capaz de manejar múltiples características ordinales simultáneamente, lo que lo hace eficiente para conjuntos de datos con varias variables ordinales. Además, como otros codificadores de scikit-learn, el OrdinalEncoder proporciona un método inverse_transform
, que permite convertir los valores codificados de nuevo a sus categorías originales cuando sea necesario.
Ejemplo: Codificación Ordinal con Scikit-learn
from sklearn.preprocessing import OrdinalEncoder
import numpy as np
import pandas as pd
# Sample data with ordinal values
education_levels = [['High School'], ['Bachelor'], ['Master'], ['PhD'], ['High School'], ['Bachelor'], ['Master']]
# Initialize the OrdinalEncoder
ordinal_encoder = OrdinalEncoder(categories=[['High School', 'Bachelor', 'Master', 'PhD']])
# Fit and transform the data
education_encoded = ordinal_encoder.fit_transform(education_levels)
# Print the encoded values
print("Encoded education levels:")
print(education_encoded)
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': [level[0] for level in education_levels], 'Encoded': education_encoded.flatten()})
print("\nDataFrame representation:")
print(df)
# Demonstrate inverse transform
decoded_levels = ordinal_encoder.inverse_transform(education_encoded)
print("\nDecoded education levels:")
print(decoded_levels)
# Get the category order
category_order = ordinal_encoder.categories_[0]
print("\nCategory order:")
print(category_order)
# Handling unseen categories
new_education_levels = [['High School'], ['Bachelor'], ['Associate']]
try:
new_encoded = ordinal_encoder.transform(new_education_levels)
print("\nEncoded new education levels:")
print(new_encoded)
except ValueError as e:
print(f"\nError: {e}")
print("Note: OrdinalEncoder cannot handle unseen categories directly.")
Aquí tienes la traducción al español del texto proporcionado:
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
OrdinalEncoder
de scikit-learn, que es la herramienta principal que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de OrdinalEncoder:
- Creamos una instancia de
OrdinalEncoder
llamadaordinal_encoder
. - Especificamos explícitamente el orden de las categorías usando el parámetro
categories
. Esto asegura que la codificación refleje el orden natural de los niveles de educación.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero basado en el orden especificado.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos los valores codificados para mostrar la transformación.
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto muestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Obteniendo el orden de las categorías:
- Accedemos al atributo
categories_
del codificador para ver el orden de las categorías utilizado para la codificación.
- Accedemos al atributo
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
OrdinalEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo ampliado muestra varias características clave y consideraciones al utilizar OrdinalEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de especificar un orden personalizado para las categorías
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La capacidad de realizar una transformación inversa de los valores codificados a las categorías originales
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
Al utilizar solo OrdinalEncoder
de Scikit-learn, hemos demostrado un enfoque completo para la codificación ordinal, incluyendo el manejo de varios escenarios y posibles problemas.
3.3.5 Manejo de Variables Categóricas con Alta Cardinalidad
Las características de alta cardinalidad son aquellas que tienen un gran número de categorías o valores únicos. Este concepto es particularmente importante en el contexto del aprendizaje automático y la preprocesamiento de datos. Vamos a desglosarlo más:
Definición: Alta cardinalidad se refiere a columnas o características en un conjunto de datos que tienen un número muy alto de valores únicos en relación con el número de filas del conjunto de datos.
Ejemplo: Un ejemplo típico de una característica de alta cardinalidad es la columna "Ciudad" en un conjunto de datos global. Tal característica podría contener cientos o miles de nombres de ciudades únicas, cada una representando una categoría distinta.
Desafíos con la Codificación One-Hot: Al trabajar con características de alta cardinalidad, los métodos tradicionales de codificación como la codificación one-hot pueden generar problemas importantes:
- Matrices dispersas: La codificación one-hot crea una nueva columna para cada categoría única. Para características de alta cardinalidad, esto resulta en una matriz dispersa, es decir, una matriz con muchos valores cero.
- Explosión de la dimensionalidad: El número de columnas en el conjunto de datos aumenta dramáticamente, lo que puede llevar a la "maldición de la dimensionalidad".
- Ineficiencia computacional: Procesar y almacenar matrices dispersas requiere más recursos computacionales, lo que puede ralentizar significativamente el entrenamiento del modelo.
- Riesgo de sobreajuste: Con tantas características, los modelos pueden empezar a ajustar el ruido en los datos en lugar de los patrones verdaderos, aumentando el riesgo de sobreajuste.
Impacto en el rendimiento del modelo: Estos desafíos pueden afectar negativamente el rendimiento del modelo, su interpretabilidad y su capacidad de generalización.
Dado estos problemas, al trabajar con características de alta cardinalidad, a menudo es necesario utilizar técnicas alternativas de codificación o métodos de ingeniería de características para reducir la dimensionalidad al tiempo que se preserva la información importante.
a. Codificación por Frecuencia
La codificación por frecuencia es una técnica poderosa para manejar características categóricas de alta cardinalidad en el aprendizaje automático. Para cada categoría única en una característica, calcula cuántas veces aparece esa categoría en el conjunto de datos y luego reemplaza el nombre de la categoría por este valor de frecuencia. A diferencia de la codificación one-hot, que crea una nueva columna para cada categoría, la codificación por frecuencia mantiene una sola columna, lo que reduce significativamente la dimensionalidad del conjunto de datos, especialmente para características con muchas categorías únicas.
Aunque reduce la dimensionalidad, la codificación por frecuencia aún retiene información importante sobre las categorías. Las categorías más comunes obtienen valores más altos, lo que puede ser informativo para muchos algoritmos de aprendizaje automático. También maneja naturalmente las categorías raras al asignarles valores muy bajos, lo que puede ayudar a prevenir el sobreajuste a categorías raras que podrían no ser representativas de la distribución general de los datos.
Al convertir las categorías en valores numéricos, la codificación por frecuencia permite a los modelos que requieren entradas numéricas (como muchas redes neuronales) trabajar más fácilmente con datos categóricos. Sin embargo, es importante tener en cuenta que este método asume que la frecuencia de una categoría está directamente relacionada con su importancia o impacto en la variable objetivo, lo cual no siempre puede ser el caso. Este posible inconveniente debe considerarse al decidir si usar la codificación por frecuencia para un conjunto de datos o problema en particular.
En general, la codificación por frecuencia es una técnica simple pero efectiva para reducir la dimensionalidad de características categóricas de alta cardinalidad, ofreciendo un buen equilibrio entre la preservación de la información y la reducción de la dimensionalidad.
Ejemplo: Codificación por Frecuencia en Pandas
# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
# Sample data with high-cardinality categorical feature
df = pd.DataFrame({
'City': ['New York', 'London', 'Paris', 'New York', 'Paris', 'London', 'Paris', 'Tokyo', 'Berlin', 'Madrid'],
'Population': [8419000, 8982000, 2141000, 8419000, 2141000, 8982000, 2141000, 13960000, 3645000, 3223000]
})
# Calculate frequency of each category
city_frequency = df['City'].value_counts(normalize=True)
# Map the frequencies to the original data
df['City_Frequency'] = df['City'].map(city_frequency)
# Calculate mean population for each city
city_population = df.groupby('City')['Population'].mean()
# Map the mean population to the original data
df['City_Mean_Population'] = df['City'].map(city_population)
# Print the resulting DataFrame
print("Resulting DataFrame:")
print(df)
# Print frequency distribution
print("\nFrequency Distribution:")
print(city_frequency)
# Visualize frequency distribution
plt.figure(figsize=(10, 6))
city_frequency.plot(kind='bar')
plt.title('Frequency Distribution of Cities')
plt.xlabel('City')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Visualize mean population by city
plt.figure(figsize=(10, 6))
city_population.plot(kind='bar')
plt.title('Mean Population by City')
plt.xlabel('City')
plt.ylabel('Mean Population')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of new categories
new_df = pd.DataFrame({'City': ['New York', 'London', 'Sydney']})
new_df['City_Frequency'] = new_df['City'].map(city_frequency).fillna(0)
print("\nHandling new categories:")
print(new_df)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con una columna 'Ciudad' (una característica de alta cardinalidad) y una columna 'Población' para análisis adicional.
- Codificación por frecuencia:
- Calculamos la frecuencia de cada ciudad usando
value_counts(normalize=True)
. - Luego, mapeamos estas frecuencias de vuelta al DataFrame original usando
map()
.
- Calculamos la frecuencia de cada ciudad usando
- Ingeniería adicional de características:
- Calculamos la población media para cada ciudad usando
groupby()
ymean()
. - Mapeamos estas poblaciones medias de vuelta al DataFrame original.
- Calculamos la población media para cada ciudad usando
- Mostrando resultados:
- Imprimimos el DataFrame resultante para mostrar los datos originales junto con las nuevas características codificadas.
- También imprimimos la distribución de frecuencia de las ciudades.
- Visualización:
- Creamos dos gráficos de barras usando matplotlib:
a. Un gráfico que muestra la distribución de frecuencia de las ciudades.
b. Un gráfico que muestra la población media por ciudad. - Estas visualizaciones ayudan a entender la distribución de los datos categóricos y su relación con otras variables.
- Creamos dos gráficos de barras usando matplotlib:
- Manejo de nuevas categorías:
- Demostramos cómo manejar nuevas categorías que no estaban en el conjunto de datos original.
- Creamos un nuevo DataFrame con una ciudad ('Sídney') que no estaba en los datos originales.
- Usamos
map()
confillna(0)
para asignar frecuencias, dando un valor de 0 a la nueva categoría.
Este ejemplo muestra varios aspectos importantes del trabajo con datos categóricos de alta cardinalidad utilizando pandas:
- Codificación por frecuencia
- Ingeniería adicional de características (población media por categoría)
- Visualización de datos categóricos
- Manejo de nuevas categorías
Estas técnicas proporcionan un enfoque integral para manejar características de alta cardinalidad, ofreciendo tanto una reducción de la dimensionalidad como la creación de características significativas.
b. Codificación basada en el objetivo
La codificación basada en el objetivo es una técnica sofisticada utilizada en la ingeniería de características para variables categóricas. Implica reemplazar cada categoría con un valor numérico derivado de la media de la variable objetivo para esa categoría específica. Este método es especialmente valioso en tareas de aprendizaje supervisado por varias razones:
- Captura de relaciones: Captura eficazmente la relación entre la característica categórica y la variable objetivo, proporcionando al modelo una entrada más informativa.
- Reducción de la dimensionalidad: A diferencia de la codificación one-hot, la codificación basada en el objetivo no aumenta el número de características, lo que la hace adecuada para variables categóricas de alta cardinalidad.
- Poder predictivo: Los valores codificados reflejan directamente cómo se relaciona cada categoría con la variable objetivo, lo que potencialmente mejora las capacidades predictivas del modelo.
- Manejo de categorías raras: Puede manejar eficazmente categorías raras asignándoles valores basados en la variable objetivo, en lugar de crear características dispersas.
- Salida continua: La característica codificada resultante es continua, lo cual puede ser beneficioso para ciertos algoritmos que funcionan mejor con entradas numéricas.
Sin embargo, es importante tener en cuenta que la codificación basada en el objetivo debe usarse con precaución:
- Potencial de sobreajuste: Puede conducir al sobreajuste si no se valida adecuadamente, ya que utiliza información del objetivo en el paso de preprocesamiento.
- Fugas de datos: Se debe tener cuidado para evitar fugas de datos asegurando que la codificación se realice dentro de los pliegues de la validación cruzada.
- Interpretabilidad: Los valores codificados pueden ser menos interpretables que las categorías originales, lo que podría ser una desventaja en algunas aplicaciones donde la explicabilidad del modelo es crucial.
En general, la codificación basada en el objetivo es una herramienta poderosa que, cuando se usa adecuadamente, puede mejorar significativamente el rendimiento de los modelos de aprendizaje automático en datos categóricos.
Ejemplo: Codificación basada en el objetivo con Category Encoders
import category_encoders as ce
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# Create a larger sample dataset
np.random.seed(42)
cities = ['New York', 'London', 'Paris', 'Tokyo', 'Berlin']
n_samples = 1000
df = pd.DataFrame({
'City': np.random.choice(cities, n_samples),
'Target': np.random.randint(0, 2, n_samples)
})
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(df['City'], df['Target'], test_size=0.2, random_state=42)
# Initialize the TargetEncoder
target_encoder = ce.TargetEncoder()
# Fit and transform the training data
X_train_encoded = target_encoder.fit_transform(X_train, y_train)
# Transform the test data
X_test_encoded = target_encoder.transform(X_test)
# Train a logistic regression model
model = LogisticRegression(random_state=42)
model.fit(X_train_encoded, y_train)
# Make predictions on the test set
y_pred = model.predict(X_test_encoded)
# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Model Accuracy: {accuracy:.2f}")
# Display the encoding for each city
encoding_map = target_encoder.mapping[0]['mapping']
print("\nTarget Encoding Map:")
for city, encoded_value in encoding_map.items():
print(f"{city}: {encoded_value:.4f}")
# Visualize the target encoding
plt.figure(figsize=(10, 6))
plt.bar(encoding_map.keys(), encoding_map.values())
plt.title('Target Encoding of Cities')
plt.xlabel('City')
plt.ylabel('Encoded Value')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of unseen categories
new_cities = pd.Series(['New York', 'London', 'San Francisco'])
encoded_new_cities = target_encoder.transform(new_cities)
print("\nEncoding of New Cities (including unseen):")
print(encoded_new_cities)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos bibliotecas adicionales, incluyendo numpy para la generación de números aleatorios, sklearn para el entrenamiento y evaluación del modelo, y matplotlib para la visualización.
- Creación de un conjunto de datos más grande:
- Generamos un conjunto de datos de muestra más grande con 1000 entradas y 5 ciudades diferentes para demostrar mejor el proceso de codificación basada en el objetivo.
- La variable 'Objetivo' es generada aleatoriamente como 0 o 1 para simular un problema de clasificación binaria.
- División de los datos:
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
train_test_split
para evaluar correctamente nuestra codificación y el modelo.
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
- Codificación basada en el objetivo:
- Usamos
TargetEncoder
de la bibliotecacategory_encoders
para realizar la codificación basada en el objetivo. - El codificador se ajusta a los datos de entrenamiento y luego se usa para transformar tanto los datos de entrenamiento como los de prueba.
- Usamos
- Entrenamiento y evaluación del modelo:
- Entrenamos un modelo de regresión logística con los datos codificados.
- El modelo se usa luego para hacer predicciones en el conjunto de prueba, y calculamos su precisión.
- Visualización de la codificación:
- Extraemos el mapa de codificación del
TargetEncoder
para ver cómo se codificó cada ciudad. - Se crea un gráfico de barras para visualizar los valores codificados de cada ciudad.
- Extraemos el mapa de codificación del
- Manejo de categorías no vistas:
- Demostramos cómo
TargetEncoder
maneja nuevas categorías que no estaban presentes en los datos de entrenamiento.
- Demostramos cómo
Este ejemplo ofrece una visión más completa de la codificación basada en el objetivo, incluyendo:
- Trabajar con un conjunto de datos más grande y realista
- División adecuada en entrenamiento y prueba para evitar fugas de datos
- Entrenamiento y evaluación reales de un modelo utilizando las características codificadas
- Visualización de los resultados de la codificación
- Manejo de categorías no vistas
Este enfoque proporciona una imagen más completa de cómo se puede aplicar la codificación basada en el objetivo en una canalización de aprendizaje automático y sus efectos en el rendimiento del modelo.
3.3.6 Manejo de Datos Categóricos Faltantes
Los valores faltantes en los datos categóricos suponen un desafío importante en la fase de preprocesamiento de proyectos de aprendizaje automático. Estas lagunas en el conjunto de datos pueden afectar significativamente la precisión y fiabilidad del modelo si no se abordan adecuadamente. La presencia de valores faltantes puede llevar a resultados sesgados, reducción de la potencia estadística y conclusiones incorrectas. Por lo tanto, es crucial manejarlos con cuidado y consideración.
Existen varias estrategias para tratar los datos categóricos faltantes, cada una con sus ventajas y posibles inconvenientes:
- Eliminación: Implica eliminar filas o columnas con valores faltantes. Aunque es simple, puede llevar a la pérdida de información valiosa.
- Imputación: Este método implica llenar los valores faltantes con estimaciones. Algunas técnicas comunes incluyen imputación por moda, imputación mediante un modelo de predicción, o el uso de una categoría dedicada como "Faltante".
- Métodos avanzados: Incluyen el uso de algoritmos que pueden manejar directamente los valores faltantes o técnicas de imputación múltiple que tienen en cuenta la incertidumbre en los datos faltantes.
La elección de la estrategia depende de factores como la cantidad de datos faltantes, el mecanismo de la falta de datos (si es completamente al azar, al azar, o no al azar), y los requisitos específicos de tu tarea de aprendizaje automático. A menudo es beneficioso experimentar con múltiples enfoques y evaluar su impacto en el rendimiento de tu modelo.
a. Imputación de valores faltantes con la moda
Para datos categóricos nominales, un enfoque común es reemplazar los valores faltantes con la categoría más frecuente (moda).
Ejemplo: Imputación de valores categóricos faltantes
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
# Sample data with missing values
df = pd.DataFrame({
'City': ['New York', 'London', None, 'Paris', 'Paris', 'London', None, 'Tokyo', 'Berlin', None],
'Population': [8400000, 8900000, None, 2100000, 2100000, 8900000, None, 13900000, 3700000, None],
'IsCapital': [False, True, None, True, True, True, None, True, True, None]
})
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Method 1: Fill missing values with the mode (most frequent value)
df['City_Mode'] = df['City'].fillna(df['City'].mode()[0])
# Method 2: Fill missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# Method 3: Use SimpleImputer for numerical data (Population)
imputer = SimpleImputer(strategy='mean')
df['Population_Imputed'] = imputer.fit_transform(df[['Population']])
# Method 4: Forward fill for IsCapital (assuming temporal order)
df['IsCapital_Ffill'] = df['IsCapital'].ffill()
print("\nDataFrame after handling missing values:")
print(df)
# Visualize missing data
plt.figure(figsize=(10, 6))
plt.imshow(df.isnull(), cmap='viridis', aspect='auto')
plt.title('Missing Value Heatmap')
plt.xlabel('Columns')
plt.ylabel('Rows')
plt.colorbar(label='Missing (Yellow)')
plt.tight_layout()
plt.show()
# Compare original and imputed data distributions
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['Population'].hist(ax=ax1, bins=10)
ax1.set_title('Original Population Distribution')
ax1.set_xlabel('Population')
ax1.set_ylabel('Frequency')
df['Population_Imputed'].hist(ax=ax2, bins=10)
ax2.set_title('Imputed Population Distribution')
ax2.set_xlabel('Population')
ax2.set_ylabel('Frequency')
plt.tight_layout()
plt.show()
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
SimpleImputer
de sklearn para la imputación de valores numéricos.
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
None
).
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
- Mostrando los datos originales:
- Imprimimos el DataFrame original y la cantidad de valores faltantes en cada columna.
- Manejo de valores faltantes:
- Método 1 (Imputación por moda): Rellenamos los valores faltantes en la columna 'Ciudad' con la ciudad más frecuente.
- Método 2 (Nueva categoría): Creamos una nueva columna donde las ciudades faltantes se reemplazan por 'Desconocido'.
- Método 3 (Imputación por media): Utilizamos
SimpleImputer
para rellenar los valores faltantes en la columna 'Población' con la media de la población. - Método 4 (Relleno hacia adelante): Utilizamos el método de relleno hacia adelante para la columna 'EsCapital', asumiendo un orden temporal en los datos.
- Visualización de datos faltantes:
- Creamos un mapa de calor para visualizar el patrón de valores faltantes en todo el DataFrame.
- Comparación de distribuciones:
- Creamos histogramas para comparar la distribución de los datos originales de 'Población' con los datos imputados.
Este ejemplo demuestra múltiples técnicas para manejar datos faltantes tanto categóricos como numéricos, incluyendo:
- Imputación por moda para datos categóricos
- Creación de una nueva categoría para valores faltantes
- Imputación por media para datos numéricos usando
SimpleImputer
- Relleno hacia adelante para datos potencialmente ordenados
- Visualización de patrones de datos faltantes
- Comparación de las distribuciones de los datos originales e imputados
Estas técnicas proporcionan un enfoque integral para tratar los datos faltantes, mostrando tanto los métodos de manejo como formas de analizar el impacto de estos métodos en tu conjunto de datos.
b. Usando una categoría separada para datos faltantes
Otra estrategia para manejar valores faltantes en datos categóricos es crear una categoría separada, comúnmente etiquetada como "Desconocido" o "Faltante". Este método implica introducir una nueva categoría específicamente para representar los puntos de datos faltantes. Al hacerlo, se reconoce explícitamente la ausencia de información y se trata como una categoría distinta en sí misma.
Este enfoque ofrece varias ventajas:
- Preservación de información: Retiene el hecho de que los datos estaban faltantes, lo cual podría ser significativo en ciertos análisis.
- Interpretabilidad del modelo: Permite que los modelos aprendan patrones asociados con los datos faltantes.
- Simplicidad: Es fácil de implementar y comprender.
- Consistencia: Proporciona una manera uniforme de manejar valores faltantes en diferentes variables categóricas.
Sin embargo, es importante considerar posibles desventajas:
- Aumento de la dimensionalidad: Para datos codificados con one-hot encoding, agrega una dimensión adicional.
- Posible sesgo: Si los datos faltantes no son aleatorios, este método podría introducir sesgo.
- Pérdida de potencia estadística: En algunos análisis, tratar los datos faltantes como una categoría separada podría reducir la potencia estadística.
Al decidir si usar este enfoque, considera la naturaleza de tus datos, la razón de la falta de datos y los requisitos específicos de tu análisis o tarea de aprendizaje automático.
Ejemplo: Reemplazo de valores faltantes con una nueva categoría
import pandas as pd
import matplotlib.pyplot as plt
# Create a sample dataset with missing values
data = {
'City': ['New York', 'London', None, 'Paris', 'Tokyo', None, 'Berlin', 'Madrid', None, 'Rome'],
'Population': [8.4, 9.0, None, 2.2, 13.9, None, 3.7, 3.2, None, 4.3],
'IsCapital': [False, True, None, True, True, None, True, True, None, True]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Replace missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# For numerical data, we can use mean imputation
df['Population_Imputed'] = df['Population'].fillna(df['Population'].mean())
# For boolean data, we can use mode imputation
df['IsCapital_Imputed'] = df['IsCapital'].fillna(df['IsCapital'].mode()[0])
print("\nDataFrame after handling missing values:")
print(df)
# Visualize the distribution of cities before and after imputation
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['City'].value_counts().plot(kind='bar', ax=ax1, title='City Distribution (Before)')
ax1.set_ylabel('Count')
df['City_Unknown'].value_counts().plot(kind='bar', ax=ax2, title='City Distribution (After)')
ax2.set_ylabel('Count')
plt.tight_layout()
plt.show()
# Analyze the impact of imputation on Population
print("\nPopulation statistics before imputation:")
print(df['Population'].describe())
print("\nPopulation statistics after imputation:")
print(df['Population_Imputed'].describe())
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana).
- El conjunto de datos incluye valores faltantes (None) para demostrar diferentes técnicas de imputación.
- Mostrando los datos originales:
- Imprimimos el DataFrame original y contamos los valores faltantes en cada columna.
- Manejo de valores faltantes:
- Para la columna 'Ciudad', creamos una nueva columna 'Ciudad_Desconocida', donde los valores faltantes se reemplazan por 'Desconocido'.
- Para la columna 'Población', usamos imputación por media para rellenar los valores faltantes.
- Para la columna 'EsCapital', utilizamos imputación por moda para completar los valores faltantes.
- Visualización de los datos:
- Creamos gráficos de barras para comparar la distribución de las ciudades antes y después de la imputación.
- Esto ayuda a visualizar el impacto de agregar la categoría 'Desconocido'.
- Análisis del impacto de la imputación:
- Imprimimos estadísticas descriptivas de la columna 'Población' antes y después de la imputación.
- Esto nos permite ver cómo la imputación por media afecta la distribución general de los datos.
Este ejemplo ampliado demuestra un enfoque más integral para manejar datos faltantes, incluyendo:
- Uso de una nueva categoría ('Desconocido') para datos faltantes categóricos
- Aplicación de imputación por media para datos numéricos
- Uso de imputación por moda para datos booleanos
- Visualización del impacto de la imputación en los datos categóricos
- Análisis del impacto estadístico de la imputación en los datos numéricos
Este enfoque proporciona una visión completa de cómo aplicar diferentes técnicas de imputación y sus efectos en el conjunto de datos, lo cual es crucial para comprender los impactos potenciales en los análisis o modelos de aprendizaje automático posteriores.
Este enfoque marca explícitamente los datos faltantes, lo que a veces puede ayudar a los modelos a aprender que la falta de datos es significativa.
3.3 Codificación y Manejo de Datos Categóricos
En el ámbito de los conjuntos de datos del mundo real, los datos categóricos son una ocurrencia común. Estas características representan categorías o etiquetas distintas, a diferencia de los valores numéricos continuos. El manejo adecuado de los datos categóricos es de suma importancia, ya que la gran mayoría de los algoritmos de aprendizaje automático están diseñados para trabajar con entradas numéricas. Una codificación incorrecta de las variables categóricas puede tener consecuencias graves, potencialmente conduciendo a un rendimiento subóptimo del modelo o incluso a errores durante el proceso de entrenamiento.
Esta sección explora una variedad de técnicas para codificar y gestionar datos categóricos. Exploraremos métodos fundamentales como la codificación one-hot y la codificación por etiquetas, así como enfoques más matizados como la codificación ordinal.
Además, nos adentraremos en técnicas avanzadas, como la codificación por objetivo, que puede ser particularmente útil en ciertos escenarios. También abordaremos los desafíos que plantean las variables categóricas de alta cardinalidad y discutiremos estrategias efectivas para gestionarlas. Al dominar estas técnicas, estarás bien preparado para manejar una amplia gama de escenarios de datos categóricos en tus proyectos de aprendizaje automático.
3.3.1 Entendiendo los Datos Categóricos
Las características categóricas son un concepto fundamental en ciencia de datos y aprendizaje automático, que representan variables que pueden tomar un número limitado de valores o categorías distintas. A diferencia de las variables continuas que pueden tomar cualquier valor numérico dentro de un rango, las variables categóricas son discretas y, a menudo, cualitativas por naturaleza. Comprender estas características es crucial para una preprocesamiento eficaz de los datos y el desarrollo de modelos.
Las características categóricas se pueden clasificar en dos tipos principales:
- Nominales (Sin Orden): Estas categorías no tienen un orden o clasificación inherente. Cada categoría es distinta e independiente de las demás. Por ejemplo:
- Colores: "Rojo", "Verde", "Azul"
- Tipos de sangre: "A", "B", "AB", "O"
- Géneros musicales: "Rock", "Jazz", "Clásico", "Hip-hop"
En estos casos, no hay una manera significativa de decir que una categoría es "mayor" o "menor" que otra.
- Ordinales (Con Orden): Estas categorías tienen un orden o clasificación claro y significativo, aunque los intervalos entre las categorías pueden no ser consistentes o medibles. Algunos ejemplos incluyen:
- Niveles educativos: "Secundaria", "Licenciatura", "Maestría", "Doctorado"
- Satisfacción del cliente: "Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"
- Tallas de camiseta: "XS", "S", "M", "L", "XL"
Aquí, hay una progresión clara de una categoría a otra, incluso si la "distancia" entre categorías no es cuantificable.
La distinción entre categorías nominales y ordinales es crucial porque determina cómo debemos manejar y codificar estas características para los algoritmos de aprendizaje automático. La mayoría de los algoritmos esperan entradas numéricas, por lo que necesitamos convertir los datos categóricos en un formato numérico. Sin embargo, el método de codificación que elijamos puede afectar significativamente el rendimiento y la interpretación del modelo.
Para las categorías nominales, se suelen utilizar técnicas como la codificación one-hot o la codificación por etiquetas. La codificación one-hot crea columnas binarias para cada categoría, mientras que la codificación por etiquetas asigna un entero único a cada categoría. Para las categorías ordinales, podríamos usar la codificación ordinal para preservar la información del orden, o emplear técnicas más avanzadas como la codificación por objetivo.
En las siguientes secciones, profundizaremos en estos métodos de codificación, explorando sus fortalezas, debilidades y casos de uso apropiados. Comprender estas técnicas es esencial para preprocesar eficazmente los datos categóricos y construir modelos de aprendizaje automático robustos.
3.3.2 Codificación One-Hot
La codificación one-hot es un método fundamental y ampliamente utilizado para transformar variables categóricas nominales en un formato numérico que pueda ser utilizado fácilmente por los algoritmos de aprendizaje automático. Esta técnica es particularmente valiosa porque la mayoría de los modelos de aprendizaje automático están diseñados para trabajar con entradas numéricas en lugar de datos categóricos.
Así es como funciona la codificación one-hot:
- Para cada categoría única en la característica original, se crea una nueva columna binaria.
- En estas nuevas columnas, un valor de 1 indica la presencia de la categoría correspondiente para un dato, mientras que un valor de 0 indica su ausencia.
- Este proceso crea un conjunto de características binarias que, en conjunto, representan la variable categórica original.
Por ejemplo, si tenemos una característica "Color" con categorías "Rojo", "Azul" y "Verde", la codificación one-hot crearía tres nuevas columnas: "Color_Rojo", "Color_Azul" y "Color_Verde". Cada fila en el conjunto de datos tendría un 1 en una de estas columnas y 0 en las otras, dependiendo del valor de color original.
La codificación one-hot es particularmente adecuada para variables nominales, que son variables categóricas en las que no existe un orden o clasificación inherente entre las categorías. Ejemplos de tales variables incluyen:
- Nombres de ciudades (p. ej., Nueva York, Londres, Tokio)
- Tipos de productos (p. ej., Electrónica, Ropa, Libros)
- Especies de animales (p. ej., Perro, Gato, Pájaro)
La principal ventaja de la codificación one-hot es que no impone ningún orden artificial a las categorías, lo cual es crucial para las variables nominales. Cada categoría se trata como una característica separada e independiente, lo que permite que los modelos de aprendizaje automático aprendan la importancia de cada categoría por separado.
Sin embargo, es importante tener en cuenta que la codificación one-hot puede generar datos de alta dimensionalidad cuando se trabaja con variables categóricas que tienen muchas categorías únicas. Esto puede resultar en la "maldición de la dimensionalidad" y puede requerir técnicas adicionales de selección de características o reducción de dimensionalidad en algunos casos.
a. Codificación One-Hot con Pandas
Pandas, una biblioteca poderosa para la manipulación de datos en Python, proporciona un método simple y eficiente para aplicar la codificación one-hot utilizando la función get_dummies()
. Esta función es particularmente útil para convertir variables categóricas en un formato adecuado para los algoritmos de aprendizaje automático.
Así es como funciona get_dummies()
:
- Detecta automáticamente las columnas categóricas en tu DataFrame.
- Para cada categoría única en una columna, crea una nueva columna binaria.
- En estas nuevas columnas, asigna un 1 donde la categoría está presente y 0 donde está ausente.
- La columna categórica original se elimina y se reemplaza por estas nuevas columnas binarias.
La función get_dummies()
ofrece varias ventajas:
- Simplicidad: Requiere un código mínimo, lo que facilita su uso incluso para principiantes.
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente.
- Personalización: Ofrece opciones para personalizar el proceso de codificación, como especificar prefijos de columna o manejar categorías desconocidas.
Al utilizar get_dummies()
, puedes transformar rápidamente los datos categóricos en un formato numérico listo para ser utilizado en diversos modelos de aprendizaje automático, agilizando tu flujo de trabajo de preprocesamiento de datos.
Ejemplo: Codificación One-Hot con Pandas
import pandas as pd
import numpy as np
# Create a more comprehensive sample dataset
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', 'New York', 'London', 'Paris'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, 8419000, 8982000, 2141000],
'Continent': ['North America', 'Europe', 'Europe', 'Asia', 'Europe', 'North America', 'Europe', 'Europe']
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Apply one-hot encoding to the 'City' column
city_encoded = pd.get_dummies(df['City'], prefix='City')
# Apply one-hot encoding to the 'Continent' column
continent_encoded = pd.get_dummies(df['Continent'], prefix='Continent')
# Concatenate the encoded columns with the original DataFrame
df_encoded = pd.concat([df, city_encoded, continent_encoded], axis=1)
print("DataFrame after one-hot encoding:")
print(df_encoded)
print("\n")
# Demonstrate handling of high-cardinality columns
df['UniqueID'] = np.arange(len(df))
high_cardinality_encoded = pd.get_dummies(df['UniqueID'], prefix='ID')
df_high_cardinality = pd.concat([df, high_cardinality_encoded], axis=1)
print("DataFrame with high-cardinality column encoded:")
print(df_high_cardinality.head())
print("\n")
# Demonstrate handling of missing values
df_missing = df.copy()
df_missing.loc[1, 'City'] = np.nan
df_missing.loc[3, 'Continent'] = np.nan
print("DataFrame with missing values:")
print(df_missing)
print("\n")
# Handle missing values before encoding
df_missing['City'] = df_missing['City'].fillna('Unknown')
df_missing['Continent'] = df_missing['Continent'].fillna('Unknown')
# Apply one-hot encoding to the DataFrame with handled missing values
df_missing_encoded = pd.get_dummies(df_missing, columns=['City', 'Continent'], prefix=['City', 'Continent'])
print("DataFrame with missing values handled and encoded:")
print(df_missing_encoded)
Este ejemplo de código demuestra un enfoque integral de la codificación one-hot utilizando pandas.
A continuación, se desglosa detalladamente el código y su funcionalidad:
- Preparación de Datos:
- Creamos un conjunto de datos más completo con varias columnas: 'City', 'Population' y 'Continent'.
- Esto nos permite demostrar la codificación para diferentes tipos de variables categóricas.
- Codificación Básica One-Hot:
- Utilizamos
pd.get_dummies()
para codificar las columnas 'City' y 'Continent' por separado. - Se usa el parámetro
prefix
para distinguir las columnas codificadas (por ejemplo, 'City_New York', 'Continent_Europe'). - Luego concatenamos estas columnas codificadas con el DataFrame original.
- Utilizamos
- Manejo de Columnas con Alta Cardinalidad:
- Creamos una columna 'UniqueID' para simular una característica con alta cardinalidad.
- Demostramos cómo la codificación one-hot puede generar un gran número de columnas para características con alta cardinalidad.
- Esto resalta los posibles problemas de uso de memoria y eficiencia computacional en estos casos.
- Manejo de Valores Faltantes:
- Introducimos valores faltantes en las columnas 'City' y 'Continent'.
- Antes de codificar, rellenamos los valores faltantes con 'Unknown' utilizando el método
fillna()
. - Esto asegura que los valores faltantes se traten como una categoría separada durante la codificación.
- Luego aplicamos la codificación one-hot al DataFrame con los valores faltantes gestionados.
- Visualización de Resultados:
- En cada paso, imprimimos el DataFrame para mostrar cómo cambia después de cada operación.
- Esto ayuda a comprender el efecto de cada paso de codificación en la estructura de los datos.
Este ejemplo integral cubre varios aspectos de la codificación one-hot, incluidos el manejo de múltiples columnas categóricas, el tratamiento de características con alta cardinalidad y la gestión de valores faltantes. Proporciona una demostración práctica de cómo utilizar pandas para estas tareas en un escenario del mundo real.
La función get_dummies()
convierte la columna "City" en columnas binarias separadas: City_New York
, City_London
y City_Paris
, que representan cada ciudad. Esto permite que el modelo de aprendizaje automático interprete la característica categórica numéricamente.
b. Codificación One-Hot con Scikit-learn
Scikit-learn ofrece una implementación robusta de la codificación one-hot a través de la clase OneHotEncoder
. Esta clase proporciona un enfoque más flexible y poderoso para codificar variables categóricas, particularmente útil en pipelines complejos de aprendizaje automático o cuando se requiere un control más detallado sobre el proceso de codificación.
La clase OneHotEncoder
destaca por varias razones:
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente, lo que la hace eficiente para conjuntos de datos con numerosas características categóricas.
- Salida en Matriz Dispersa: De forma predeterminada, devuelve una matriz dispersa, lo que es eficiente en términos de memoria para conjuntos de datos con muchas categorías.
- Manejo de Categorías Desconocidas: Ofrece opciones para manejar categorías que no estaban presentes durante el proceso de ajuste, crucial para aplicaciones del mundo real donde pueden aparecer nuevas categorías en los datos de prueba.
- Integración con Pipelines de Scikit-learn: Se integra perfectamente con la clase
Pipeline
de Scikit-learn, lo que permite una fácil combinación con otros pasos de preprocesamiento y modelos.
Cuando se trabaja con pipelines de aprendizaje automático, el OneHotEncoder
puede ser especialmente valioso. Permite definir un esquema de codificación consistente que se puede aplicar de manera uniforme a los conjuntos de datos de entrenamiento y prueba, asegurando que el modelo reciba datos de entrada con un formato consistente.
Para escenarios que requieren más control, el OneHotEncoder
ofrece varios parámetros para personalizar su comportamiento. Por ejemplo, se puede especificar cómo manejar las categorías desconocidas, si usar un formato de salida disperso o denso, e incluso definir una codificación personalizada para características específicas.
Ejemplo: Codificación One-Hot con Scikit-learn
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
import pandas as pd
import numpy as np
# Sample data
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', np.nan],
'Country': ['USA', 'UK', 'France', 'Japan', 'Germany', 'USA'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, np.nan]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Define transformers for categorical and numerical data
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(sparse=False, handle_unknown='ignore'))
])
numerical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean'))
])
# Combine transformers into a ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('cat', categorical_transformer, ['City', 'Country']),
('num', numerical_transformer, ['Population'])
]
)
# Apply the preprocessing pipeline
transformed_data = preprocessor.fit_transform(df)
# Get feature names
onehot_features_city = preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(['City', 'Country'])
numerical_features = ['Population']
feature_names = np.concatenate([onehot_features_city, numerical_features])
# Create a new DataFrame with transformed data
df_encoded = pd.DataFrame(transformed_data, columns=feature_names)
print("Transformed DataFrame:")
print(df_encoded)
Explicación del Desglose del Código:
- Manejo de Valores Faltantes:
- Las columnas categóricas (
City
yCountry
) se rellenan con el valor más frecuente. - La columna numérica (
Population
) se rellena con el valor medio.
- Las columnas categóricas (
- Codificación One-Hot:
- Las columnas categóricas (
City
,Country
) se codifican mediante one-hot, convirtiéndolas en columnas binarias.
- Las columnas categóricas (
- Pipeline con
ColumnTransformer
:- Combina los pasos de preprocesamiento categórico y numérico en un único pipeline.
- Nombres de Características:
- Recupera automáticamente nombres significativos para las características codificadas.
- Resultado Final:
- Se crea un DataFrame limpio y completamente preprocesado (
df_encoded
), listo para análisis o modelado.
- Se crea un DataFrame limpio y completamente preprocesado (
Este ejemplo muestra varias características clave de las capacidades de preprocesamiento de Scikit-learn:
- Manejo de datos faltantes con SimpleImputer
- Codificación one-hot de categorías nominales ('City')
- Codificación de etiquetas de categorías ordinales ('Country')
- Uso de ColumnTransformer para aplicar diferentes transformaciones a diferentes columnas
- Pipeline para encadenar múltiples pasos de preprocesamiento
- Extracción de nombres de características después de la transformación
- Transformación inversa para recuperar las categorías originales de los datos codificados
Este enfoque proporciona un método robusto y escalable para preprocesar tipos de datos mixtos, manejar valores faltantes y preparar datos para modelos de aprendizaje automático.
En este caso, OneHotEncoder
convierte los datos categóricos en una matriz densa de valores binarios, que pueden pasarse directamente a los modelos de aprendizaje automático.
3.3.3 Codificación de Etiquetas (Label Encoding)
La codificación de etiquetas es una técnica que asigna un número entero único a cada categoría en una característica categórica. Este método es particularmente útil para variables categóricas ordinales, donde existe un orden o jerarquía significativa entre las categorías. Al convertir las categorías en valores numéricos, la codificación de etiquetas permite que los algoritmos de aprendizaje automático interpreten y procesen los datos categóricos de manera más efectiva.
La principal ventaja de la codificación de etiquetas radica en su capacidad para preservar la relación ordinal entre las categorías. Por ejemplo, en un conjunto de datos que contiene niveles educativos como "Secundaria", "Licenciatura", "Maestría" y "Doctorado", al codificar estos niveles con números como 0, 1, 2 y 3, respectivamente, mantenemos el orden inherente de los niveles educativos. Esta representación numérica permite a los algoritmos comprender que un Doctorado (3) representa un nivel de educación más alto que una Licenciatura (1).
A continuación, un desglose más detallado de cómo funciona la codificación de etiquetas:
- Identificación: El algoritmo identifica todas las categorías únicas dentro de la característica.
- Ordenación: Para los datos ordinales, las categorías se ordenan normalmente en función de su orden natural. Para los datos nominales sin un orden claro, la ordenación puede ser alfabética o basada en el orden de aparición en el conjunto de datos.
- Asignación: A cada categoría se le asigna un número entero único, generalmente comenzando desde 0 e incrementándose en 1 para cada categoría subsecuente.
- Transformación: Los valores categóricos originales en el conjunto de datos son reemplazados por sus correspondientes codificaciones numéricas.
Es importante destacar que, si bien la codificación de etiquetas es excelente para los datos ordinales, debe usarse con precaución en las variables categóricas nominales (donde no existe un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden o magnitud inexistente, lo que podría inducir a error al modelo de aprendizaje automático.
Además, la codificación de etiquetas puede ser particularmente beneficiosa en ciertos algoritmos, como los árboles de decisión y los bosques aleatorios, que pueden manejar bien las relaciones ordinales. Sin embargo, para los algoritmos sensibles a la magnitud de las características de entrada (como la regresión lineal o las redes neuronales), podrían ser necesarias técnicas adicionales de preprocesamiento, como la normalización, después de la codificación de etiquetas.
Codificación de Etiquetas con Scikit-learn
El LabelEncoder
de Scikit-learn es una herramienta poderosa utilizada para transformar datos categóricos ordinales en números enteros. Este proceso, conocido como codificación de etiquetas, asigna un valor numérico único a cada categoría en una variable categórica. Aquí tienes una explicación más detallada:
- Funcionalidad: El
LabelEncoder
detecta automáticamente todas las categorías únicas en una característica dada y asigna a cada una un número entero único, típicamente comenzando desde 0. - Datos Ordinales: Es particularmente útil para los datos ordinales donde hay un orden claro o jerarquía entre las categorías. Por ejemplo, niveles educativos como 'Secundaria', 'Licenciatura', 'Maestría', 'Doctorado' podrían codificarse como 0, 1, 2, 3 respectivamente.
- Preservación del Orden: El codificador mantiene la relación ordinal entre las categorías, lo cual es crucial para que muchos algoritmos de aprendizaje automático interpreten correctamente los datos.
- Representación Numérica: Al convertir las categorías en enteros, permite que los modelos de aprendizaje automático que requieren entradas numéricas procesen datos categóricos de manera efectiva.
- Reversibilidad: El
LabelEncoder
también proporciona un métodoinverse_transform
, que te permite convertir los números codificados de vuelta a sus etiquetas categóricas originales cuando sea necesario. - Precaución con los Datos Nominales: Aunque es poderoso para datos ordinales, debe usarse con cautela en las variables categóricas nominales (donde no existe un orden inherente), ya que los números asignados podrían implicar un orden o magnitud inexistente.
Comprender estos aspectos del LabelEncoder
es esencial para preprocesar de manera efectiva datos categóricos ordinales en pipelines de aprendizaje automático. Una aplicación adecuada de esta herramienta puede mejorar significativamente la calidad y la interpretabilidad de tus características codificadas.
Ejemplo: Codificación de Etiquetas con Scikit-learn
from sklearn.preprocessing import LabelEncoder
import numpy as np
import pandas as pd
# Sample data
education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Bachelor', 'High School', 'PhD']
# Initialize the LabelEncoder
label_encoder = LabelEncoder()
# Fit and transform the data
education_encoded = label_encoder.fit_transform(education_levels)
# Display the encoded labels
print(f"Original labels: {education_levels}")
print(f"Encoded labels: {education_encoded}")
# Create a dictionary mapping original labels to encoded values
label_mapping = dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_)))
print(f"\nLabel mapping: {label_mapping}")
# Demonstrate inverse transform
decoded_labels = label_encoder.inverse_transform(education_encoded)
print(f"\nDecoded labels: {decoded_labels}")
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': education_levels, 'Encoded': education_encoded})
print("\nDataFrame representation:")
print(df)
# Handling unseen categories
new_education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Associate']
try:
new_encoded = label_encoder.transform(new_education_levels)
except ValueError as e:
print(f"\nError: {e}")
print("Note: LabelEncoder cannot handle unseen categories directly.")
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
LabelEncoder
de scikit-learn, que es la principal herramienta que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de LabelEncoder:
- Creamos una instancia de
LabelEncoder
llamadalabel_encoder
.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero único.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos tanto las etiquetas originales como las etiquetas codificadas para mostrar la transformación.
- Creación de un mapeo de etiquetas:
- Creamos un diccionario que mapea cada categoría original a su valor codificado.
- Esto es útil para entender cómo el codificador ha asignado valores a cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto demuestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
LabelEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo muestra varias características clave y consideraciones al utilizar LabelEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de mapear entre valores originales y codificados en ambas direcciones
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
3.3.4 Codificación Ordinal
Cuando se trabaja con variables categóricas ordinales, que son variables con categorías que tienen un orden o jerarquía natural, se puede utilizar el OrdinalEncoder de scikit-learn. Esta herramienta es ideal para manejar datos ordinales de manera efectiva.
El OrdinalEncoder asigna un número entero único a cada categoría mientras conserva el orden inherente de las mismas. Esto es crucial porque permite a los algoritmos de aprendizaje automático entender y aprovechar las relaciones significativas entre las diferentes categorías.
Por ejemplo, considera una variable que representa niveles de educación: 'Secundaria', 'Licenciatura', 'Maestría' y 'Doctorado'. El OrdinalEncoder podría asignar estos valores como 0, 1, 2 y 3 respectivamente. Esta codificación mantiene la progresión natural de los niveles de educación, lo cual puede ser información valiosa para muchos modelos de aprendizaje automático.
A diferencia de la codificación one-hot, que crea columnas binarias para cada categoría, la codificación ordinal da como resultado una sola columna de enteros. Esto puede ser especialmente útil cuando se trabaja con conjuntos de datos que tienen un gran número de variables ordinales, ya que ayuda a mantener el espacio de características más compacto.
Sin embargo, es importante tener en cuenta que aunque OrdinalEncoder es excelente para datos verdaderamente ordinales, debe usarse con precaución con variables categóricas nominales (donde no hay un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden que no existe, lo cual podría confundir al modelo de aprendizaje automático.
Codificación Ordinal con Scikit-learn
El OrdinalEncoder
de Scikit-learn es una herramienta poderosa diseñada específicamente para codificar variables categóricas ordinales, preservando su orden inherente. Este codificador es particularmente útil cuando se trabaja con variables que tienen una jerarquía o clasificación natural.
El OrdinalEncoder funciona asignando valores enteros a cada categoría en la variable ordinal, asegurando que el orden de estos enteros corresponda al orden natural de las categorías. A diferencia de otros métodos de codificación, el OrdinalEncoder mantiene las relaciones relativas entre las categorías. Por ejemplo, al codificar niveles educativos ('Secundaria', 'Licenciatura', 'Maestría', 'Doctorado'), podría asignar los valores 0, 1, 2 y 3 respectivamente, reflejando la progresión en educación.
Al convertir las categorías en números enteros, el OrdinalEncoder permite que los algoritmos de aprendizaje automático que requieren entrada numérica procesen datos ordinales de manera efectiva, conservando la información ordinal. Además, ofrece flexibilidad al permitir a los usuarios especificar un orden personalizado de las categorías, brindando control sobre cómo se representa la relación ordinal.
El codificador también es escalable, capaz de manejar múltiples características ordinales simultáneamente, lo que lo hace eficiente para conjuntos de datos con varias variables ordinales. Además, como otros codificadores de scikit-learn, el OrdinalEncoder proporciona un método inverse_transform
, que permite convertir los valores codificados de nuevo a sus categorías originales cuando sea necesario.
Ejemplo: Codificación Ordinal con Scikit-learn
from sklearn.preprocessing import OrdinalEncoder
import numpy as np
import pandas as pd
# Sample data with ordinal values
education_levels = [['High School'], ['Bachelor'], ['Master'], ['PhD'], ['High School'], ['Bachelor'], ['Master']]
# Initialize the OrdinalEncoder
ordinal_encoder = OrdinalEncoder(categories=[['High School', 'Bachelor', 'Master', 'PhD']])
# Fit and transform the data
education_encoded = ordinal_encoder.fit_transform(education_levels)
# Print the encoded values
print("Encoded education levels:")
print(education_encoded)
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': [level[0] for level in education_levels], 'Encoded': education_encoded.flatten()})
print("\nDataFrame representation:")
print(df)
# Demonstrate inverse transform
decoded_levels = ordinal_encoder.inverse_transform(education_encoded)
print("\nDecoded education levels:")
print(decoded_levels)
# Get the category order
category_order = ordinal_encoder.categories_[0]
print("\nCategory order:")
print(category_order)
# Handling unseen categories
new_education_levels = [['High School'], ['Bachelor'], ['Associate']]
try:
new_encoded = ordinal_encoder.transform(new_education_levels)
print("\nEncoded new education levels:")
print(new_encoded)
except ValueError as e:
print(f"\nError: {e}")
print("Note: OrdinalEncoder cannot handle unseen categories directly.")
Aquí tienes la traducción al español del texto proporcionado:
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
OrdinalEncoder
de scikit-learn, que es la herramienta principal que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de OrdinalEncoder:
- Creamos una instancia de
OrdinalEncoder
llamadaordinal_encoder
. - Especificamos explícitamente el orden de las categorías usando el parámetro
categories
. Esto asegura que la codificación refleje el orden natural de los niveles de educación.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero basado en el orden especificado.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos los valores codificados para mostrar la transformación.
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto muestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Obteniendo el orden de las categorías:
- Accedemos al atributo
categories_
del codificador para ver el orden de las categorías utilizado para la codificación.
- Accedemos al atributo
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
OrdinalEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo ampliado muestra varias características clave y consideraciones al utilizar OrdinalEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de especificar un orden personalizado para las categorías
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La capacidad de realizar una transformación inversa de los valores codificados a las categorías originales
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
Al utilizar solo OrdinalEncoder
de Scikit-learn, hemos demostrado un enfoque completo para la codificación ordinal, incluyendo el manejo de varios escenarios y posibles problemas.
3.3.5 Manejo de Variables Categóricas con Alta Cardinalidad
Las características de alta cardinalidad son aquellas que tienen un gran número de categorías o valores únicos. Este concepto es particularmente importante en el contexto del aprendizaje automático y la preprocesamiento de datos. Vamos a desglosarlo más:
Definición: Alta cardinalidad se refiere a columnas o características en un conjunto de datos que tienen un número muy alto de valores únicos en relación con el número de filas del conjunto de datos.
Ejemplo: Un ejemplo típico de una característica de alta cardinalidad es la columna "Ciudad" en un conjunto de datos global. Tal característica podría contener cientos o miles de nombres de ciudades únicas, cada una representando una categoría distinta.
Desafíos con la Codificación One-Hot: Al trabajar con características de alta cardinalidad, los métodos tradicionales de codificación como la codificación one-hot pueden generar problemas importantes:
- Matrices dispersas: La codificación one-hot crea una nueva columna para cada categoría única. Para características de alta cardinalidad, esto resulta en una matriz dispersa, es decir, una matriz con muchos valores cero.
- Explosión de la dimensionalidad: El número de columnas en el conjunto de datos aumenta dramáticamente, lo que puede llevar a la "maldición de la dimensionalidad".
- Ineficiencia computacional: Procesar y almacenar matrices dispersas requiere más recursos computacionales, lo que puede ralentizar significativamente el entrenamiento del modelo.
- Riesgo de sobreajuste: Con tantas características, los modelos pueden empezar a ajustar el ruido en los datos en lugar de los patrones verdaderos, aumentando el riesgo de sobreajuste.
Impacto en el rendimiento del modelo: Estos desafíos pueden afectar negativamente el rendimiento del modelo, su interpretabilidad y su capacidad de generalización.
Dado estos problemas, al trabajar con características de alta cardinalidad, a menudo es necesario utilizar técnicas alternativas de codificación o métodos de ingeniería de características para reducir la dimensionalidad al tiempo que se preserva la información importante.
a. Codificación por Frecuencia
La codificación por frecuencia es una técnica poderosa para manejar características categóricas de alta cardinalidad en el aprendizaje automático. Para cada categoría única en una característica, calcula cuántas veces aparece esa categoría en el conjunto de datos y luego reemplaza el nombre de la categoría por este valor de frecuencia. A diferencia de la codificación one-hot, que crea una nueva columna para cada categoría, la codificación por frecuencia mantiene una sola columna, lo que reduce significativamente la dimensionalidad del conjunto de datos, especialmente para características con muchas categorías únicas.
Aunque reduce la dimensionalidad, la codificación por frecuencia aún retiene información importante sobre las categorías. Las categorías más comunes obtienen valores más altos, lo que puede ser informativo para muchos algoritmos de aprendizaje automático. También maneja naturalmente las categorías raras al asignarles valores muy bajos, lo que puede ayudar a prevenir el sobreajuste a categorías raras que podrían no ser representativas de la distribución general de los datos.
Al convertir las categorías en valores numéricos, la codificación por frecuencia permite a los modelos que requieren entradas numéricas (como muchas redes neuronales) trabajar más fácilmente con datos categóricos. Sin embargo, es importante tener en cuenta que este método asume que la frecuencia de una categoría está directamente relacionada con su importancia o impacto en la variable objetivo, lo cual no siempre puede ser el caso. Este posible inconveniente debe considerarse al decidir si usar la codificación por frecuencia para un conjunto de datos o problema en particular.
En general, la codificación por frecuencia es una técnica simple pero efectiva para reducir la dimensionalidad de características categóricas de alta cardinalidad, ofreciendo un buen equilibrio entre la preservación de la información y la reducción de la dimensionalidad.
Ejemplo: Codificación por Frecuencia en Pandas
# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
# Sample data with high-cardinality categorical feature
df = pd.DataFrame({
'City': ['New York', 'London', 'Paris', 'New York', 'Paris', 'London', 'Paris', 'Tokyo', 'Berlin', 'Madrid'],
'Population': [8419000, 8982000, 2141000, 8419000, 2141000, 8982000, 2141000, 13960000, 3645000, 3223000]
})
# Calculate frequency of each category
city_frequency = df['City'].value_counts(normalize=True)
# Map the frequencies to the original data
df['City_Frequency'] = df['City'].map(city_frequency)
# Calculate mean population for each city
city_population = df.groupby('City')['Population'].mean()
# Map the mean population to the original data
df['City_Mean_Population'] = df['City'].map(city_population)
# Print the resulting DataFrame
print("Resulting DataFrame:")
print(df)
# Print frequency distribution
print("\nFrequency Distribution:")
print(city_frequency)
# Visualize frequency distribution
plt.figure(figsize=(10, 6))
city_frequency.plot(kind='bar')
plt.title('Frequency Distribution of Cities')
plt.xlabel('City')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Visualize mean population by city
plt.figure(figsize=(10, 6))
city_population.plot(kind='bar')
plt.title('Mean Population by City')
plt.xlabel('City')
plt.ylabel('Mean Population')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of new categories
new_df = pd.DataFrame({'City': ['New York', 'London', 'Sydney']})
new_df['City_Frequency'] = new_df['City'].map(city_frequency).fillna(0)
print("\nHandling new categories:")
print(new_df)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con una columna 'Ciudad' (una característica de alta cardinalidad) y una columna 'Población' para análisis adicional.
- Codificación por frecuencia:
- Calculamos la frecuencia de cada ciudad usando
value_counts(normalize=True)
. - Luego, mapeamos estas frecuencias de vuelta al DataFrame original usando
map()
.
- Calculamos la frecuencia de cada ciudad usando
- Ingeniería adicional de características:
- Calculamos la población media para cada ciudad usando
groupby()
ymean()
. - Mapeamos estas poblaciones medias de vuelta al DataFrame original.
- Calculamos la población media para cada ciudad usando
- Mostrando resultados:
- Imprimimos el DataFrame resultante para mostrar los datos originales junto con las nuevas características codificadas.
- También imprimimos la distribución de frecuencia de las ciudades.
- Visualización:
- Creamos dos gráficos de barras usando matplotlib:
a. Un gráfico que muestra la distribución de frecuencia de las ciudades.
b. Un gráfico que muestra la población media por ciudad. - Estas visualizaciones ayudan a entender la distribución de los datos categóricos y su relación con otras variables.
- Creamos dos gráficos de barras usando matplotlib:
- Manejo de nuevas categorías:
- Demostramos cómo manejar nuevas categorías que no estaban en el conjunto de datos original.
- Creamos un nuevo DataFrame con una ciudad ('Sídney') que no estaba en los datos originales.
- Usamos
map()
confillna(0)
para asignar frecuencias, dando un valor de 0 a la nueva categoría.
Este ejemplo muestra varios aspectos importantes del trabajo con datos categóricos de alta cardinalidad utilizando pandas:
- Codificación por frecuencia
- Ingeniería adicional de características (población media por categoría)
- Visualización de datos categóricos
- Manejo de nuevas categorías
Estas técnicas proporcionan un enfoque integral para manejar características de alta cardinalidad, ofreciendo tanto una reducción de la dimensionalidad como la creación de características significativas.
b. Codificación basada en el objetivo
La codificación basada en el objetivo es una técnica sofisticada utilizada en la ingeniería de características para variables categóricas. Implica reemplazar cada categoría con un valor numérico derivado de la media de la variable objetivo para esa categoría específica. Este método es especialmente valioso en tareas de aprendizaje supervisado por varias razones:
- Captura de relaciones: Captura eficazmente la relación entre la característica categórica y la variable objetivo, proporcionando al modelo una entrada más informativa.
- Reducción de la dimensionalidad: A diferencia de la codificación one-hot, la codificación basada en el objetivo no aumenta el número de características, lo que la hace adecuada para variables categóricas de alta cardinalidad.
- Poder predictivo: Los valores codificados reflejan directamente cómo se relaciona cada categoría con la variable objetivo, lo que potencialmente mejora las capacidades predictivas del modelo.
- Manejo de categorías raras: Puede manejar eficazmente categorías raras asignándoles valores basados en la variable objetivo, en lugar de crear características dispersas.
- Salida continua: La característica codificada resultante es continua, lo cual puede ser beneficioso para ciertos algoritmos que funcionan mejor con entradas numéricas.
Sin embargo, es importante tener en cuenta que la codificación basada en el objetivo debe usarse con precaución:
- Potencial de sobreajuste: Puede conducir al sobreajuste si no se valida adecuadamente, ya que utiliza información del objetivo en el paso de preprocesamiento.
- Fugas de datos: Se debe tener cuidado para evitar fugas de datos asegurando que la codificación se realice dentro de los pliegues de la validación cruzada.
- Interpretabilidad: Los valores codificados pueden ser menos interpretables que las categorías originales, lo que podría ser una desventaja en algunas aplicaciones donde la explicabilidad del modelo es crucial.
En general, la codificación basada en el objetivo es una herramienta poderosa que, cuando se usa adecuadamente, puede mejorar significativamente el rendimiento de los modelos de aprendizaje automático en datos categóricos.
Ejemplo: Codificación basada en el objetivo con Category Encoders
import category_encoders as ce
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# Create a larger sample dataset
np.random.seed(42)
cities = ['New York', 'London', 'Paris', 'Tokyo', 'Berlin']
n_samples = 1000
df = pd.DataFrame({
'City': np.random.choice(cities, n_samples),
'Target': np.random.randint(0, 2, n_samples)
})
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(df['City'], df['Target'], test_size=0.2, random_state=42)
# Initialize the TargetEncoder
target_encoder = ce.TargetEncoder()
# Fit and transform the training data
X_train_encoded = target_encoder.fit_transform(X_train, y_train)
# Transform the test data
X_test_encoded = target_encoder.transform(X_test)
# Train a logistic regression model
model = LogisticRegression(random_state=42)
model.fit(X_train_encoded, y_train)
# Make predictions on the test set
y_pred = model.predict(X_test_encoded)
# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Model Accuracy: {accuracy:.2f}")
# Display the encoding for each city
encoding_map = target_encoder.mapping[0]['mapping']
print("\nTarget Encoding Map:")
for city, encoded_value in encoding_map.items():
print(f"{city}: {encoded_value:.4f}")
# Visualize the target encoding
plt.figure(figsize=(10, 6))
plt.bar(encoding_map.keys(), encoding_map.values())
plt.title('Target Encoding of Cities')
plt.xlabel('City')
plt.ylabel('Encoded Value')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of unseen categories
new_cities = pd.Series(['New York', 'London', 'San Francisco'])
encoded_new_cities = target_encoder.transform(new_cities)
print("\nEncoding of New Cities (including unseen):")
print(encoded_new_cities)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos bibliotecas adicionales, incluyendo numpy para la generación de números aleatorios, sklearn para el entrenamiento y evaluación del modelo, y matplotlib para la visualización.
- Creación de un conjunto de datos más grande:
- Generamos un conjunto de datos de muestra más grande con 1000 entradas y 5 ciudades diferentes para demostrar mejor el proceso de codificación basada en el objetivo.
- La variable 'Objetivo' es generada aleatoriamente como 0 o 1 para simular un problema de clasificación binaria.
- División de los datos:
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
train_test_split
para evaluar correctamente nuestra codificación y el modelo.
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
- Codificación basada en el objetivo:
- Usamos
TargetEncoder
de la bibliotecacategory_encoders
para realizar la codificación basada en el objetivo. - El codificador se ajusta a los datos de entrenamiento y luego se usa para transformar tanto los datos de entrenamiento como los de prueba.
- Usamos
- Entrenamiento y evaluación del modelo:
- Entrenamos un modelo de regresión logística con los datos codificados.
- El modelo se usa luego para hacer predicciones en el conjunto de prueba, y calculamos su precisión.
- Visualización de la codificación:
- Extraemos el mapa de codificación del
TargetEncoder
para ver cómo se codificó cada ciudad. - Se crea un gráfico de barras para visualizar los valores codificados de cada ciudad.
- Extraemos el mapa de codificación del
- Manejo de categorías no vistas:
- Demostramos cómo
TargetEncoder
maneja nuevas categorías que no estaban presentes en los datos de entrenamiento.
- Demostramos cómo
Este ejemplo ofrece una visión más completa de la codificación basada en el objetivo, incluyendo:
- Trabajar con un conjunto de datos más grande y realista
- División adecuada en entrenamiento y prueba para evitar fugas de datos
- Entrenamiento y evaluación reales de un modelo utilizando las características codificadas
- Visualización de los resultados de la codificación
- Manejo de categorías no vistas
Este enfoque proporciona una imagen más completa de cómo se puede aplicar la codificación basada en el objetivo en una canalización de aprendizaje automático y sus efectos en el rendimiento del modelo.
3.3.6 Manejo de Datos Categóricos Faltantes
Los valores faltantes en los datos categóricos suponen un desafío importante en la fase de preprocesamiento de proyectos de aprendizaje automático. Estas lagunas en el conjunto de datos pueden afectar significativamente la precisión y fiabilidad del modelo si no se abordan adecuadamente. La presencia de valores faltantes puede llevar a resultados sesgados, reducción de la potencia estadística y conclusiones incorrectas. Por lo tanto, es crucial manejarlos con cuidado y consideración.
Existen varias estrategias para tratar los datos categóricos faltantes, cada una con sus ventajas y posibles inconvenientes:
- Eliminación: Implica eliminar filas o columnas con valores faltantes. Aunque es simple, puede llevar a la pérdida de información valiosa.
- Imputación: Este método implica llenar los valores faltantes con estimaciones. Algunas técnicas comunes incluyen imputación por moda, imputación mediante un modelo de predicción, o el uso de una categoría dedicada como "Faltante".
- Métodos avanzados: Incluyen el uso de algoritmos que pueden manejar directamente los valores faltantes o técnicas de imputación múltiple que tienen en cuenta la incertidumbre en los datos faltantes.
La elección de la estrategia depende de factores como la cantidad de datos faltantes, el mecanismo de la falta de datos (si es completamente al azar, al azar, o no al azar), y los requisitos específicos de tu tarea de aprendizaje automático. A menudo es beneficioso experimentar con múltiples enfoques y evaluar su impacto en el rendimiento de tu modelo.
a. Imputación de valores faltantes con la moda
Para datos categóricos nominales, un enfoque común es reemplazar los valores faltantes con la categoría más frecuente (moda).
Ejemplo: Imputación de valores categóricos faltantes
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
# Sample data with missing values
df = pd.DataFrame({
'City': ['New York', 'London', None, 'Paris', 'Paris', 'London', None, 'Tokyo', 'Berlin', None],
'Population': [8400000, 8900000, None, 2100000, 2100000, 8900000, None, 13900000, 3700000, None],
'IsCapital': [False, True, None, True, True, True, None, True, True, None]
})
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Method 1: Fill missing values with the mode (most frequent value)
df['City_Mode'] = df['City'].fillna(df['City'].mode()[0])
# Method 2: Fill missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# Method 3: Use SimpleImputer for numerical data (Population)
imputer = SimpleImputer(strategy='mean')
df['Population_Imputed'] = imputer.fit_transform(df[['Population']])
# Method 4: Forward fill for IsCapital (assuming temporal order)
df['IsCapital_Ffill'] = df['IsCapital'].ffill()
print("\nDataFrame after handling missing values:")
print(df)
# Visualize missing data
plt.figure(figsize=(10, 6))
plt.imshow(df.isnull(), cmap='viridis', aspect='auto')
plt.title('Missing Value Heatmap')
plt.xlabel('Columns')
plt.ylabel('Rows')
plt.colorbar(label='Missing (Yellow)')
plt.tight_layout()
plt.show()
# Compare original and imputed data distributions
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['Population'].hist(ax=ax1, bins=10)
ax1.set_title('Original Population Distribution')
ax1.set_xlabel('Population')
ax1.set_ylabel('Frequency')
df['Population_Imputed'].hist(ax=ax2, bins=10)
ax2.set_title('Imputed Population Distribution')
ax2.set_xlabel('Population')
ax2.set_ylabel('Frequency')
plt.tight_layout()
plt.show()
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
SimpleImputer
de sklearn para la imputación de valores numéricos.
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
None
).
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
- Mostrando los datos originales:
- Imprimimos el DataFrame original y la cantidad de valores faltantes en cada columna.
- Manejo de valores faltantes:
- Método 1 (Imputación por moda): Rellenamos los valores faltantes en la columna 'Ciudad' con la ciudad más frecuente.
- Método 2 (Nueva categoría): Creamos una nueva columna donde las ciudades faltantes se reemplazan por 'Desconocido'.
- Método 3 (Imputación por media): Utilizamos
SimpleImputer
para rellenar los valores faltantes en la columna 'Población' con la media de la población. - Método 4 (Relleno hacia adelante): Utilizamos el método de relleno hacia adelante para la columna 'EsCapital', asumiendo un orden temporal en los datos.
- Visualización de datos faltantes:
- Creamos un mapa de calor para visualizar el patrón de valores faltantes en todo el DataFrame.
- Comparación de distribuciones:
- Creamos histogramas para comparar la distribución de los datos originales de 'Población' con los datos imputados.
Este ejemplo demuestra múltiples técnicas para manejar datos faltantes tanto categóricos como numéricos, incluyendo:
- Imputación por moda para datos categóricos
- Creación de una nueva categoría para valores faltantes
- Imputación por media para datos numéricos usando
SimpleImputer
- Relleno hacia adelante para datos potencialmente ordenados
- Visualización de patrones de datos faltantes
- Comparación de las distribuciones de los datos originales e imputados
Estas técnicas proporcionan un enfoque integral para tratar los datos faltantes, mostrando tanto los métodos de manejo como formas de analizar el impacto de estos métodos en tu conjunto de datos.
b. Usando una categoría separada para datos faltantes
Otra estrategia para manejar valores faltantes en datos categóricos es crear una categoría separada, comúnmente etiquetada como "Desconocido" o "Faltante". Este método implica introducir una nueva categoría específicamente para representar los puntos de datos faltantes. Al hacerlo, se reconoce explícitamente la ausencia de información y se trata como una categoría distinta en sí misma.
Este enfoque ofrece varias ventajas:
- Preservación de información: Retiene el hecho de que los datos estaban faltantes, lo cual podría ser significativo en ciertos análisis.
- Interpretabilidad del modelo: Permite que los modelos aprendan patrones asociados con los datos faltantes.
- Simplicidad: Es fácil de implementar y comprender.
- Consistencia: Proporciona una manera uniforme de manejar valores faltantes en diferentes variables categóricas.
Sin embargo, es importante considerar posibles desventajas:
- Aumento de la dimensionalidad: Para datos codificados con one-hot encoding, agrega una dimensión adicional.
- Posible sesgo: Si los datos faltantes no son aleatorios, este método podría introducir sesgo.
- Pérdida de potencia estadística: En algunos análisis, tratar los datos faltantes como una categoría separada podría reducir la potencia estadística.
Al decidir si usar este enfoque, considera la naturaleza de tus datos, la razón de la falta de datos y los requisitos específicos de tu análisis o tarea de aprendizaje automático.
Ejemplo: Reemplazo de valores faltantes con una nueva categoría
import pandas as pd
import matplotlib.pyplot as plt
# Create a sample dataset with missing values
data = {
'City': ['New York', 'London', None, 'Paris', 'Tokyo', None, 'Berlin', 'Madrid', None, 'Rome'],
'Population': [8.4, 9.0, None, 2.2, 13.9, None, 3.7, 3.2, None, 4.3],
'IsCapital': [False, True, None, True, True, None, True, True, None, True]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Replace missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# For numerical data, we can use mean imputation
df['Population_Imputed'] = df['Population'].fillna(df['Population'].mean())
# For boolean data, we can use mode imputation
df['IsCapital_Imputed'] = df['IsCapital'].fillna(df['IsCapital'].mode()[0])
print("\nDataFrame after handling missing values:")
print(df)
# Visualize the distribution of cities before and after imputation
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['City'].value_counts().plot(kind='bar', ax=ax1, title='City Distribution (Before)')
ax1.set_ylabel('Count')
df['City_Unknown'].value_counts().plot(kind='bar', ax=ax2, title='City Distribution (After)')
ax2.set_ylabel('Count')
plt.tight_layout()
plt.show()
# Analyze the impact of imputation on Population
print("\nPopulation statistics before imputation:")
print(df['Population'].describe())
print("\nPopulation statistics after imputation:")
print(df['Population_Imputed'].describe())
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana).
- El conjunto de datos incluye valores faltantes (None) para demostrar diferentes técnicas de imputación.
- Mostrando los datos originales:
- Imprimimos el DataFrame original y contamos los valores faltantes en cada columna.
- Manejo de valores faltantes:
- Para la columna 'Ciudad', creamos una nueva columna 'Ciudad_Desconocida', donde los valores faltantes se reemplazan por 'Desconocido'.
- Para la columna 'Población', usamos imputación por media para rellenar los valores faltantes.
- Para la columna 'EsCapital', utilizamos imputación por moda para completar los valores faltantes.
- Visualización de los datos:
- Creamos gráficos de barras para comparar la distribución de las ciudades antes y después de la imputación.
- Esto ayuda a visualizar el impacto de agregar la categoría 'Desconocido'.
- Análisis del impacto de la imputación:
- Imprimimos estadísticas descriptivas de la columna 'Población' antes y después de la imputación.
- Esto nos permite ver cómo la imputación por media afecta la distribución general de los datos.
Este ejemplo ampliado demuestra un enfoque más integral para manejar datos faltantes, incluyendo:
- Uso de una nueva categoría ('Desconocido') para datos faltantes categóricos
- Aplicación de imputación por media para datos numéricos
- Uso de imputación por moda para datos booleanos
- Visualización del impacto de la imputación en los datos categóricos
- Análisis del impacto estadístico de la imputación en los datos numéricos
Este enfoque proporciona una visión completa de cómo aplicar diferentes técnicas de imputación y sus efectos en el conjunto de datos, lo cual es crucial para comprender los impactos potenciales en los análisis o modelos de aprendizaje automático posteriores.
Este enfoque marca explícitamente los datos faltantes, lo que a veces puede ayudar a los modelos a aprender que la falta de datos es significativa.
3.3 Codificación y Manejo de Datos Categóricos
En el ámbito de los conjuntos de datos del mundo real, los datos categóricos son una ocurrencia común. Estas características representan categorías o etiquetas distintas, a diferencia de los valores numéricos continuos. El manejo adecuado de los datos categóricos es de suma importancia, ya que la gran mayoría de los algoritmos de aprendizaje automático están diseñados para trabajar con entradas numéricas. Una codificación incorrecta de las variables categóricas puede tener consecuencias graves, potencialmente conduciendo a un rendimiento subóptimo del modelo o incluso a errores durante el proceso de entrenamiento.
Esta sección explora una variedad de técnicas para codificar y gestionar datos categóricos. Exploraremos métodos fundamentales como la codificación one-hot y la codificación por etiquetas, así como enfoques más matizados como la codificación ordinal.
Además, nos adentraremos en técnicas avanzadas, como la codificación por objetivo, que puede ser particularmente útil en ciertos escenarios. También abordaremos los desafíos que plantean las variables categóricas de alta cardinalidad y discutiremos estrategias efectivas para gestionarlas. Al dominar estas técnicas, estarás bien preparado para manejar una amplia gama de escenarios de datos categóricos en tus proyectos de aprendizaje automático.
3.3.1 Entendiendo los Datos Categóricos
Las características categóricas son un concepto fundamental en ciencia de datos y aprendizaje automático, que representan variables que pueden tomar un número limitado de valores o categorías distintas. A diferencia de las variables continuas que pueden tomar cualquier valor numérico dentro de un rango, las variables categóricas son discretas y, a menudo, cualitativas por naturaleza. Comprender estas características es crucial para una preprocesamiento eficaz de los datos y el desarrollo de modelos.
Las características categóricas se pueden clasificar en dos tipos principales:
- Nominales (Sin Orden): Estas categorías no tienen un orden o clasificación inherente. Cada categoría es distinta e independiente de las demás. Por ejemplo:
- Colores: "Rojo", "Verde", "Azul"
- Tipos de sangre: "A", "B", "AB", "O"
- Géneros musicales: "Rock", "Jazz", "Clásico", "Hip-hop"
En estos casos, no hay una manera significativa de decir que una categoría es "mayor" o "menor" que otra.
- Ordinales (Con Orden): Estas categorías tienen un orden o clasificación claro y significativo, aunque los intervalos entre las categorías pueden no ser consistentes o medibles. Algunos ejemplos incluyen:
- Niveles educativos: "Secundaria", "Licenciatura", "Maestría", "Doctorado"
- Satisfacción del cliente: "Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"
- Tallas de camiseta: "XS", "S", "M", "L", "XL"
Aquí, hay una progresión clara de una categoría a otra, incluso si la "distancia" entre categorías no es cuantificable.
La distinción entre categorías nominales y ordinales es crucial porque determina cómo debemos manejar y codificar estas características para los algoritmos de aprendizaje automático. La mayoría de los algoritmos esperan entradas numéricas, por lo que necesitamos convertir los datos categóricos en un formato numérico. Sin embargo, el método de codificación que elijamos puede afectar significativamente el rendimiento y la interpretación del modelo.
Para las categorías nominales, se suelen utilizar técnicas como la codificación one-hot o la codificación por etiquetas. La codificación one-hot crea columnas binarias para cada categoría, mientras que la codificación por etiquetas asigna un entero único a cada categoría. Para las categorías ordinales, podríamos usar la codificación ordinal para preservar la información del orden, o emplear técnicas más avanzadas como la codificación por objetivo.
En las siguientes secciones, profundizaremos en estos métodos de codificación, explorando sus fortalezas, debilidades y casos de uso apropiados. Comprender estas técnicas es esencial para preprocesar eficazmente los datos categóricos y construir modelos de aprendizaje automático robustos.
3.3.2 Codificación One-Hot
La codificación one-hot es un método fundamental y ampliamente utilizado para transformar variables categóricas nominales en un formato numérico que pueda ser utilizado fácilmente por los algoritmos de aprendizaje automático. Esta técnica es particularmente valiosa porque la mayoría de los modelos de aprendizaje automático están diseñados para trabajar con entradas numéricas en lugar de datos categóricos.
Así es como funciona la codificación one-hot:
- Para cada categoría única en la característica original, se crea una nueva columna binaria.
- En estas nuevas columnas, un valor de 1 indica la presencia de la categoría correspondiente para un dato, mientras que un valor de 0 indica su ausencia.
- Este proceso crea un conjunto de características binarias que, en conjunto, representan la variable categórica original.
Por ejemplo, si tenemos una característica "Color" con categorías "Rojo", "Azul" y "Verde", la codificación one-hot crearía tres nuevas columnas: "Color_Rojo", "Color_Azul" y "Color_Verde". Cada fila en el conjunto de datos tendría un 1 en una de estas columnas y 0 en las otras, dependiendo del valor de color original.
La codificación one-hot es particularmente adecuada para variables nominales, que son variables categóricas en las que no existe un orden o clasificación inherente entre las categorías. Ejemplos de tales variables incluyen:
- Nombres de ciudades (p. ej., Nueva York, Londres, Tokio)
- Tipos de productos (p. ej., Electrónica, Ropa, Libros)
- Especies de animales (p. ej., Perro, Gato, Pájaro)
La principal ventaja de la codificación one-hot es que no impone ningún orden artificial a las categorías, lo cual es crucial para las variables nominales. Cada categoría se trata como una característica separada e independiente, lo que permite que los modelos de aprendizaje automático aprendan la importancia de cada categoría por separado.
Sin embargo, es importante tener en cuenta que la codificación one-hot puede generar datos de alta dimensionalidad cuando se trabaja con variables categóricas que tienen muchas categorías únicas. Esto puede resultar en la "maldición de la dimensionalidad" y puede requerir técnicas adicionales de selección de características o reducción de dimensionalidad en algunos casos.
a. Codificación One-Hot con Pandas
Pandas, una biblioteca poderosa para la manipulación de datos en Python, proporciona un método simple y eficiente para aplicar la codificación one-hot utilizando la función get_dummies()
. Esta función es particularmente útil para convertir variables categóricas en un formato adecuado para los algoritmos de aprendizaje automático.
Así es como funciona get_dummies()
:
- Detecta automáticamente las columnas categóricas en tu DataFrame.
- Para cada categoría única en una columna, crea una nueva columna binaria.
- En estas nuevas columnas, asigna un 1 donde la categoría está presente y 0 donde está ausente.
- La columna categórica original se elimina y se reemplaza por estas nuevas columnas binarias.
La función get_dummies()
ofrece varias ventajas:
- Simplicidad: Requiere un código mínimo, lo que facilita su uso incluso para principiantes.
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente.
- Personalización: Ofrece opciones para personalizar el proceso de codificación, como especificar prefijos de columna o manejar categorías desconocidas.
Al utilizar get_dummies()
, puedes transformar rápidamente los datos categóricos en un formato numérico listo para ser utilizado en diversos modelos de aprendizaje automático, agilizando tu flujo de trabajo de preprocesamiento de datos.
Ejemplo: Codificación One-Hot con Pandas
import pandas as pd
import numpy as np
# Create a more comprehensive sample dataset
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', 'New York', 'London', 'Paris'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, 8419000, 8982000, 2141000],
'Continent': ['North America', 'Europe', 'Europe', 'Asia', 'Europe', 'North America', 'Europe', 'Europe']
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Apply one-hot encoding to the 'City' column
city_encoded = pd.get_dummies(df['City'], prefix='City')
# Apply one-hot encoding to the 'Continent' column
continent_encoded = pd.get_dummies(df['Continent'], prefix='Continent')
# Concatenate the encoded columns with the original DataFrame
df_encoded = pd.concat([df, city_encoded, continent_encoded], axis=1)
print("DataFrame after one-hot encoding:")
print(df_encoded)
print("\n")
# Demonstrate handling of high-cardinality columns
df['UniqueID'] = np.arange(len(df))
high_cardinality_encoded = pd.get_dummies(df['UniqueID'], prefix='ID')
df_high_cardinality = pd.concat([df, high_cardinality_encoded], axis=1)
print("DataFrame with high-cardinality column encoded:")
print(df_high_cardinality.head())
print("\n")
# Demonstrate handling of missing values
df_missing = df.copy()
df_missing.loc[1, 'City'] = np.nan
df_missing.loc[3, 'Continent'] = np.nan
print("DataFrame with missing values:")
print(df_missing)
print("\n")
# Handle missing values before encoding
df_missing['City'] = df_missing['City'].fillna('Unknown')
df_missing['Continent'] = df_missing['Continent'].fillna('Unknown')
# Apply one-hot encoding to the DataFrame with handled missing values
df_missing_encoded = pd.get_dummies(df_missing, columns=['City', 'Continent'], prefix=['City', 'Continent'])
print("DataFrame with missing values handled and encoded:")
print(df_missing_encoded)
Este ejemplo de código demuestra un enfoque integral de la codificación one-hot utilizando pandas.
A continuación, se desglosa detalladamente el código y su funcionalidad:
- Preparación de Datos:
- Creamos un conjunto de datos más completo con varias columnas: 'City', 'Population' y 'Continent'.
- Esto nos permite demostrar la codificación para diferentes tipos de variables categóricas.
- Codificación Básica One-Hot:
- Utilizamos
pd.get_dummies()
para codificar las columnas 'City' y 'Continent' por separado. - Se usa el parámetro
prefix
para distinguir las columnas codificadas (por ejemplo, 'City_New York', 'Continent_Europe'). - Luego concatenamos estas columnas codificadas con el DataFrame original.
- Utilizamos
- Manejo de Columnas con Alta Cardinalidad:
- Creamos una columna 'UniqueID' para simular una característica con alta cardinalidad.
- Demostramos cómo la codificación one-hot puede generar un gran número de columnas para características con alta cardinalidad.
- Esto resalta los posibles problemas de uso de memoria y eficiencia computacional en estos casos.
- Manejo de Valores Faltantes:
- Introducimos valores faltantes en las columnas 'City' y 'Continent'.
- Antes de codificar, rellenamos los valores faltantes con 'Unknown' utilizando el método
fillna()
. - Esto asegura que los valores faltantes se traten como una categoría separada durante la codificación.
- Luego aplicamos la codificación one-hot al DataFrame con los valores faltantes gestionados.
- Visualización de Resultados:
- En cada paso, imprimimos el DataFrame para mostrar cómo cambia después de cada operación.
- Esto ayuda a comprender el efecto de cada paso de codificación en la estructura de los datos.
Este ejemplo integral cubre varios aspectos de la codificación one-hot, incluidos el manejo de múltiples columnas categóricas, el tratamiento de características con alta cardinalidad y la gestión de valores faltantes. Proporciona una demostración práctica de cómo utilizar pandas para estas tareas en un escenario del mundo real.
La función get_dummies()
convierte la columna "City" en columnas binarias separadas: City_New York
, City_London
y City_Paris
, que representan cada ciudad. Esto permite que el modelo de aprendizaje automático interprete la característica categórica numéricamente.
b. Codificación One-Hot con Scikit-learn
Scikit-learn ofrece una implementación robusta de la codificación one-hot a través de la clase OneHotEncoder
. Esta clase proporciona un enfoque más flexible y poderoso para codificar variables categóricas, particularmente útil en pipelines complejos de aprendizaje automático o cuando se requiere un control más detallado sobre el proceso de codificación.
La clase OneHotEncoder
destaca por varias razones:
- Flexibilidad: Puede manejar múltiples columnas categóricas simultáneamente, lo que la hace eficiente para conjuntos de datos con numerosas características categóricas.
- Salida en Matriz Dispersa: De forma predeterminada, devuelve una matriz dispersa, lo que es eficiente en términos de memoria para conjuntos de datos con muchas categorías.
- Manejo de Categorías Desconocidas: Ofrece opciones para manejar categorías que no estaban presentes durante el proceso de ajuste, crucial para aplicaciones del mundo real donde pueden aparecer nuevas categorías en los datos de prueba.
- Integración con Pipelines de Scikit-learn: Se integra perfectamente con la clase
Pipeline
de Scikit-learn, lo que permite una fácil combinación con otros pasos de preprocesamiento y modelos.
Cuando se trabaja con pipelines de aprendizaje automático, el OneHotEncoder
puede ser especialmente valioso. Permite definir un esquema de codificación consistente que se puede aplicar de manera uniforme a los conjuntos de datos de entrenamiento y prueba, asegurando que el modelo reciba datos de entrada con un formato consistente.
Para escenarios que requieren más control, el OneHotEncoder
ofrece varios parámetros para personalizar su comportamiento. Por ejemplo, se puede especificar cómo manejar las categorías desconocidas, si usar un formato de salida disperso o denso, e incluso definir una codificación personalizada para características específicas.
Ejemplo: Codificación One-Hot con Scikit-learn
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
import pandas as pd
import numpy as np
# Sample data
data = {
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin', np.nan],
'Country': ['USA', 'UK', 'France', 'Japan', 'Germany', 'USA'],
'Population': [8419000, 8982000, 2141000, 13960000, 3645000, np.nan]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\n")
# Define transformers for categorical and numerical data
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(sparse=False, handle_unknown='ignore'))
])
numerical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean'))
])
# Combine transformers into a ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('cat', categorical_transformer, ['City', 'Country']),
('num', numerical_transformer, ['Population'])
]
)
# Apply the preprocessing pipeline
transformed_data = preprocessor.fit_transform(df)
# Get feature names
onehot_features_city = preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(['City', 'Country'])
numerical_features = ['Population']
feature_names = np.concatenate([onehot_features_city, numerical_features])
# Create a new DataFrame with transformed data
df_encoded = pd.DataFrame(transformed_data, columns=feature_names)
print("Transformed DataFrame:")
print(df_encoded)
Explicación del Desglose del Código:
- Manejo de Valores Faltantes:
- Las columnas categóricas (
City
yCountry
) se rellenan con el valor más frecuente. - La columna numérica (
Population
) se rellena con el valor medio.
- Las columnas categóricas (
- Codificación One-Hot:
- Las columnas categóricas (
City
,Country
) se codifican mediante one-hot, convirtiéndolas en columnas binarias.
- Las columnas categóricas (
- Pipeline con
ColumnTransformer
:- Combina los pasos de preprocesamiento categórico y numérico en un único pipeline.
- Nombres de Características:
- Recupera automáticamente nombres significativos para las características codificadas.
- Resultado Final:
- Se crea un DataFrame limpio y completamente preprocesado (
df_encoded
), listo para análisis o modelado.
- Se crea un DataFrame limpio y completamente preprocesado (
Este ejemplo muestra varias características clave de las capacidades de preprocesamiento de Scikit-learn:
- Manejo de datos faltantes con SimpleImputer
- Codificación one-hot de categorías nominales ('City')
- Codificación de etiquetas de categorías ordinales ('Country')
- Uso de ColumnTransformer para aplicar diferentes transformaciones a diferentes columnas
- Pipeline para encadenar múltiples pasos de preprocesamiento
- Extracción de nombres de características después de la transformación
- Transformación inversa para recuperar las categorías originales de los datos codificados
Este enfoque proporciona un método robusto y escalable para preprocesar tipos de datos mixtos, manejar valores faltantes y preparar datos para modelos de aprendizaje automático.
En este caso, OneHotEncoder
convierte los datos categóricos en una matriz densa de valores binarios, que pueden pasarse directamente a los modelos de aprendizaje automático.
3.3.3 Codificación de Etiquetas (Label Encoding)
La codificación de etiquetas es una técnica que asigna un número entero único a cada categoría en una característica categórica. Este método es particularmente útil para variables categóricas ordinales, donde existe un orden o jerarquía significativa entre las categorías. Al convertir las categorías en valores numéricos, la codificación de etiquetas permite que los algoritmos de aprendizaje automático interpreten y procesen los datos categóricos de manera más efectiva.
La principal ventaja de la codificación de etiquetas radica en su capacidad para preservar la relación ordinal entre las categorías. Por ejemplo, en un conjunto de datos que contiene niveles educativos como "Secundaria", "Licenciatura", "Maestría" y "Doctorado", al codificar estos niveles con números como 0, 1, 2 y 3, respectivamente, mantenemos el orden inherente de los niveles educativos. Esta representación numérica permite a los algoritmos comprender que un Doctorado (3) representa un nivel de educación más alto que una Licenciatura (1).
A continuación, un desglose más detallado de cómo funciona la codificación de etiquetas:
- Identificación: El algoritmo identifica todas las categorías únicas dentro de la característica.
- Ordenación: Para los datos ordinales, las categorías se ordenan normalmente en función de su orden natural. Para los datos nominales sin un orden claro, la ordenación puede ser alfabética o basada en el orden de aparición en el conjunto de datos.
- Asignación: A cada categoría se le asigna un número entero único, generalmente comenzando desde 0 e incrementándose en 1 para cada categoría subsecuente.
- Transformación: Los valores categóricos originales en el conjunto de datos son reemplazados por sus correspondientes codificaciones numéricas.
Es importante destacar que, si bien la codificación de etiquetas es excelente para los datos ordinales, debe usarse con precaución en las variables categóricas nominales (donde no existe un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden o magnitud inexistente, lo que podría inducir a error al modelo de aprendizaje automático.
Además, la codificación de etiquetas puede ser particularmente beneficiosa en ciertos algoritmos, como los árboles de decisión y los bosques aleatorios, que pueden manejar bien las relaciones ordinales. Sin embargo, para los algoritmos sensibles a la magnitud de las características de entrada (como la regresión lineal o las redes neuronales), podrían ser necesarias técnicas adicionales de preprocesamiento, como la normalización, después de la codificación de etiquetas.
Codificación de Etiquetas con Scikit-learn
El LabelEncoder
de Scikit-learn es una herramienta poderosa utilizada para transformar datos categóricos ordinales en números enteros. Este proceso, conocido como codificación de etiquetas, asigna un valor numérico único a cada categoría en una variable categórica. Aquí tienes una explicación más detallada:
- Funcionalidad: El
LabelEncoder
detecta automáticamente todas las categorías únicas en una característica dada y asigna a cada una un número entero único, típicamente comenzando desde 0. - Datos Ordinales: Es particularmente útil para los datos ordinales donde hay un orden claro o jerarquía entre las categorías. Por ejemplo, niveles educativos como 'Secundaria', 'Licenciatura', 'Maestría', 'Doctorado' podrían codificarse como 0, 1, 2, 3 respectivamente.
- Preservación del Orden: El codificador mantiene la relación ordinal entre las categorías, lo cual es crucial para que muchos algoritmos de aprendizaje automático interpreten correctamente los datos.
- Representación Numérica: Al convertir las categorías en enteros, permite que los modelos de aprendizaje automático que requieren entradas numéricas procesen datos categóricos de manera efectiva.
- Reversibilidad: El
LabelEncoder
también proporciona un métodoinverse_transform
, que te permite convertir los números codificados de vuelta a sus etiquetas categóricas originales cuando sea necesario. - Precaución con los Datos Nominales: Aunque es poderoso para datos ordinales, debe usarse con cautela en las variables categóricas nominales (donde no existe un orden inherente), ya que los números asignados podrían implicar un orden o magnitud inexistente.
Comprender estos aspectos del LabelEncoder
es esencial para preprocesar de manera efectiva datos categóricos ordinales en pipelines de aprendizaje automático. Una aplicación adecuada de esta herramienta puede mejorar significativamente la calidad y la interpretabilidad de tus características codificadas.
Ejemplo: Codificación de Etiquetas con Scikit-learn
from sklearn.preprocessing import LabelEncoder
import numpy as np
import pandas as pd
# Sample data
education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Bachelor', 'High School', 'PhD']
# Initialize the LabelEncoder
label_encoder = LabelEncoder()
# Fit and transform the data
education_encoded = label_encoder.fit_transform(education_levels)
# Display the encoded labels
print(f"Original labels: {education_levels}")
print(f"Encoded labels: {education_encoded}")
# Create a dictionary mapping original labels to encoded values
label_mapping = dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_)))
print(f"\nLabel mapping: {label_mapping}")
# Demonstrate inverse transform
decoded_labels = label_encoder.inverse_transform(education_encoded)
print(f"\nDecoded labels: {decoded_labels}")
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': education_levels, 'Encoded': education_encoded})
print("\nDataFrame representation:")
print(df)
# Handling unseen categories
new_education_levels = ['High School', 'Bachelor', 'Master', 'PhD', 'Associate']
try:
new_encoded = label_encoder.transform(new_education_levels)
except ValueError as e:
print(f"\nError: {e}")
print("Note: LabelEncoder cannot handle unseen categories directly.")
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
LabelEncoder
de scikit-learn, que es la principal herramienta que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de LabelEncoder:
- Creamos una instancia de
LabelEncoder
llamadalabel_encoder
.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero único.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos tanto las etiquetas originales como las etiquetas codificadas para mostrar la transformación.
- Creación de un mapeo de etiquetas:
- Creamos un diccionario que mapea cada categoría original a su valor codificado.
- Esto es útil para entender cómo el codificador ha asignado valores a cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto demuestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
LabelEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo muestra varias características clave y consideraciones al utilizar LabelEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de mapear entre valores originales y codificados en ambas direcciones
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
3.3.4 Codificación Ordinal
Cuando se trabaja con variables categóricas ordinales, que son variables con categorías que tienen un orden o jerarquía natural, se puede utilizar el OrdinalEncoder de scikit-learn. Esta herramienta es ideal para manejar datos ordinales de manera efectiva.
El OrdinalEncoder asigna un número entero único a cada categoría mientras conserva el orden inherente de las mismas. Esto es crucial porque permite a los algoritmos de aprendizaje automático entender y aprovechar las relaciones significativas entre las diferentes categorías.
Por ejemplo, considera una variable que representa niveles de educación: 'Secundaria', 'Licenciatura', 'Maestría' y 'Doctorado'. El OrdinalEncoder podría asignar estos valores como 0, 1, 2 y 3 respectivamente. Esta codificación mantiene la progresión natural de los niveles de educación, lo cual puede ser información valiosa para muchos modelos de aprendizaje automático.
A diferencia de la codificación one-hot, que crea columnas binarias para cada categoría, la codificación ordinal da como resultado una sola columna de enteros. Esto puede ser especialmente útil cuando se trabaja con conjuntos de datos que tienen un gran número de variables ordinales, ya que ayuda a mantener el espacio de características más compacto.
Sin embargo, es importante tener en cuenta que aunque OrdinalEncoder es excelente para datos verdaderamente ordinales, debe usarse con precaución con variables categóricas nominales (donde no hay un orden inherente). En tales casos, los números asignados podrían implicar inadvertidamente un orden que no existe, lo cual podría confundir al modelo de aprendizaje automático.
Codificación Ordinal con Scikit-learn
El OrdinalEncoder
de Scikit-learn es una herramienta poderosa diseñada específicamente para codificar variables categóricas ordinales, preservando su orden inherente. Este codificador es particularmente útil cuando se trabaja con variables que tienen una jerarquía o clasificación natural.
El OrdinalEncoder funciona asignando valores enteros a cada categoría en la variable ordinal, asegurando que el orden de estos enteros corresponda al orden natural de las categorías. A diferencia de otros métodos de codificación, el OrdinalEncoder mantiene las relaciones relativas entre las categorías. Por ejemplo, al codificar niveles educativos ('Secundaria', 'Licenciatura', 'Maestría', 'Doctorado'), podría asignar los valores 0, 1, 2 y 3 respectivamente, reflejando la progresión en educación.
Al convertir las categorías en números enteros, el OrdinalEncoder permite que los algoritmos de aprendizaje automático que requieren entrada numérica procesen datos ordinales de manera efectiva, conservando la información ordinal. Además, ofrece flexibilidad al permitir a los usuarios especificar un orden personalizado de las categorías, brindando control sobre cómo se representa la relación ordinal.
El codificador también es escalable, capaz de manejar múltiples características ordinales simultáneamente, lo que lo hace eficiente para conjuntos de datos con varias variables ordinales. Además, como otros codificadores de scikit-learn, el OrdinalEncoder proporciona un método inverse_transform
, que permite convertir los valores codificados de nuevo a sus categorías originales cuando sea necesario.
Ejemplo: Codificación Ordinal con Scikit-learn
from sklearn.preprocessing import OrdinalEncoder
import numpy as np
import pandas as pd
# Sample data with ordinal values
education_levels = [['High School'], ['Bachelor'], ['Master'], ['PhD'], ['High School'], ['Bachelor'], ['Master']]
# Initialize the OrdinalEncoder
ordinal_encoder = OrdinalEncoder(categories=[['High School', 'Bachelor', 'Master', 'PhD']])
# Fit and transform the data
education_encoded = ordinal_encoder.fit_transform(education_levels)
# Print the encoded values
print("Encoded education levels:")
print(education_encoded)
# Create a DataFrame for better visualization
df = pd.DataFrame({'Original': [level[0] for level in education_levels], 'Encoded': education_encoded.flatten()})
print("\nDataFrame representation:")
print(df)
# Demonstrate inverse transform
decoded_levels = ordinal_encoder.inverse_transform(education_encoded)
print("\nDecoded education levels:")
print(decoded_levels)
# Get the category order
category_order = ordinal_encoder.categories_[0]
print("\nCategory order:")
print(category_order)
# Handling unseen categories
new_education_levels = [['High School'], ['Bachelor'], ['Associate']]
try:
new_encoded = ordinal_encoder.transform(new_education_levels)
print("\nEncoded new education levels:")
print(new_encoded)
except ValueError as e:
print(f"\nError: {e}")
print("Note: OrdinalEncoder cannot handle unseen categories directly.")
Aquí tienes la traducción al español del texto proporcionado:
Explicación del desglose del código:
- Importación de las bibliotecas necesarias:
- Importamos
OrdinalEncoder
de scikit-learn, que es la herramienta principal que utilizaremos para la codificación. - También importamos
numpy
ypandas
para manipulación y visualización adicional de datos.
- Importamos
- Creación de datos de ejemplo:
- Creamos una lista de niveles de educación, incluyendo algunas repeticiones para demostrar cómo el codificador maneja valores duplicados.
- Inicialización de OrdinalEncoder:
- Creamos una instancia de
OrdinalEncoder
llamadaordinal_encoder
. - Especificamos explícitamente el orden de las categorías usando el parámetro
categories
. Esto asegura que la codificación refleje el orden natural de los niveles de educación.
- Creamos una instancia de
- Ajuste y transformación de los datos:
- Utilizamos el método
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Este método aprende las categorías únicas y asigna a cada una un número entero basado en el orden especificado.
- Utilizamos el método
- Mostrando los resultados:
- Imprimimos los valores codificados para mostrar la transformación.
- Creación de un DataFrame:
- Usamos pandas para crear un DataFrame que muestra tanto los valores originales como los codificados lado a lado.
- Esto proporciona una visualización clara de cómo se ha codificado cada categoría.
- Demostración de la transformación inversa:
- Utilizamos el método
inverse_transform()
para convertir los valores codificados de nuevo a sus categorías originales. - Esto muestra que la codificación es reversible, lo cual es importante para interpretar los resultados más adelante.
- Utilizamos el método
- Obteniendo el orden de las categorías:
- Accedemos al atributo
categories_
del codificador para ver el orden de las categorías utilizado para la codificación.
- Accedemos al atributo
- Manejo de categorías no vistas:
- Intentamos codificar una lista que incluye una nueva categoría ('Associate') que no estaba en los datos originales.
- Esto demuestra que
OrdinalEncoder
no puede manejar directamente categorías no vistas, lo cual es una limitación importante a tener en cuenta. - Utilizamos un bloque try-except para capturar y mostrar el error que ocurre al intentar codificar una categoría no vista.
Este ejemplo ampliado muestra varias características clave y consideraciones al utilizar OrdinalEncoder
:
- Cómo maneja valores duplicados (reciben la misma codificación)
- La capacidad de especificar un orden personalizado para las categorías
- La creación de un mapeo claro entre las categorías y sus valores codificados
- La capacidad de realizar una transformación inversa de los valores codificados a las categorías originales
- La limitación de no poder manejar categorías no vistas, lo cual es crucial al trabajar con nuevos datos
Al utilizar solo OrdinalEncoder
de Scikit-learn, hemos demostrado un enfoque completo para la codificación ordinal, incluyendo el manejo de varios escenarios y posibles problemas.
3.3.5 Manejo de Variables Categóricas con Alta Cardinalidad
Las características de alta cardinalidad son aquellas que tienen un gran número de categorías o valores únicos. Este concepto es particularmente importante en el contexto del aprendizaje automático y la preprocesamiento de datos. Vamos a desglosarlo más:
Definición: Alta cardinalidad se refiere a columnas o características en un conjunto de datos que tienen un número muy alto de valores únicos en relación con el número de filas del conjunto de datos.
Ejemplo: Un ejemplo típico de una característica de alta cardinalidad es la columna "Ciudad" en un conjunto de datos global. Tal característica podría contener cientos o miles de nombres de ciudades únicas, cada una representando una categoría distinta.
Desafíos con la Codificación One-Hot: Al trabajar con características de alta cardinalidad, los métodos tradicionales de codificación como la codificación one-hot pueden generar problemas importantes:
- Matrices dispersas: La codificación one-hot crea una nueva columna para cada categoría única. Para características de alta cardinalidad, esto resulta en una matriz dispersa, es decir, una matriz con muchos valores cero.
- Explosión de la dimensionalidad: El número de columnas en el conjunto de datos aumenta dramáticamente, lo que puede llevar a la "maldición de la dimensionalidad".
- Ineficiencia computacional: Procesar y almacenar matrices dispersas requiere más recursos computacionales, lo que puede ralentizar significativamente el entrenamiento del modelo.
- Riesgo de sobreajuste: Con tantas características, los modelos pueden empezar a ajustar el ruido en los datos en lugar de los patrones verdaderos, aumentando el riesgo de sobreajuste.
Impacto en el rendimiento del modelo: Estos desafíos pueden afectar negativamente el rendimiento del modelo, su interpretabilidad y su capacidad de generalización.
Dado estos problemas, al trabajar con características de alta cardinalidad, a menudo es necesario utilizar técnicas alternativas de codificación o métodos de ingeniería de características para reducir la dimensionalidad al tiempo que se preserva la información importante.
a. Codificación por Frecuencia
La codificación por frecuencia es una técnica poderosa para manejar características categóricas de alta cardinalidad en el aprendizaje automático. Para cada categoría única en una característica, calcula cuántas veces aparece esa categoría en el conjunto de datos y luego reemplaza el nombre de la categoría por este valor de frecuencia. A diferencia de la codificación one-hot, que crea una nueva columna para cada categoría, la codificación por frecuencia mantiene una sola columna, lo que reduce significativamente la dimensionalidad del conjunto de datos, especialmente para características con muchas categorías únicas.
Aunque reduce la dimensionalidad, la codificación por frecuencia aún retiene información importante sobre las categorías. Las categorías más comunes obtienen valores más altos, lo que puede ser informativo para muchos algoritmos de aprendizaje automático. También maneja naturalmente las categorías raras al asignarles valores muy bajos, lo que puede ayudar a prevenir el sobreajuste a categorías raras que podrían no ser representativas de la distribución general de los datos.
Al convertir las categorías en valores numéricos, la codificación por frecuencia permite a los modelos que requieren entradas numéricas (como muchas redes neuronales) trabajar más fácilmente con datos categóricos. Sin embargo, es importante tener en cuenta que este método asume que la frecuencia de una categoría está directamente relacionada con su importancia o impacto en la variable objetivo, lo cual no siempre puede ser el caso. Este posible inconveniente debe considerarse al decidir si usar la codificación por frecuencia para un conjunto de datos o problema en particular.
En general, la codificación por frecuencia es una técnica simple pero efectiva para reducir la dimensionalidad de características categóricas de alta cardinalidad, ofreciendo un buen equilibrio entre la preservación de la información y la reducción de la dimensionalidad.
Ejemplo: Codificación por Frecuencia en Pandas
# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
# Sample data with high-cardinality categorical feature
df = pd.DataFrame({
'City': ['New York', 'London', 'Paris', 'New York', 'Paris', 'London', 'Paris', 'Tokyo', 'Berlin', 'Madrid'],
'Population': [8419000, 8982000, 2141000, 8419000, 2141000, 8982000, 2141000, 13960000, 3645000, 3223000]
})
# Calculate frequency of each category
city_frequency = df['City'].value_counts(normalize=True)
# Map the frequencies to the original data
df['City_Frequency'] = df['City'].map(city_frequency)
# Calculate mean population for each city
city_population = df.groupby('City')['Population'].mean()
# Map the mean population to the original data
df['City_Mean_Population'] = df['City'].map(city_population)
# Print the resulting DataFrame
print("Resulting DataFrame:")
print(df)
# Print frequency distribution
print("\nFrequency Distribution:")
print(city_frequency)
# Visualize frequency distribution
plt.figure(figsize=(10, 6))
city_frequency.plot(kind='bar')
plt.title('Frequency Distribution of Cities')
plt.xlabel('City')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Visualize mean population by city
plt.figure(figsize=(10, 6))
city_population.plot(kind='bar')
plt.title('Mean Population by City')
plt.xlabel('City')
plt.ylabel('Mean Population')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of new categories
new_df = pd.DataFrame({'City': ['New York', 'London', 'Sydney']})
new_df['City_Frequency'] = new_df['City'].map(city_frequency).fillna(0)
print("\nHandling new categories:")
print(new_df)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con una columna 'Ciudad' (una característica de alta cardinalidad) y una columna 'Población' para análisis adicional.
- Codificación por frecuencia:
- Calculamos la frecuencia de cada ciudad usando
value_counts(normalize=True)
. - Luego, mapeamos estas frecuencias de vuelta al DataFrame original usando
map()
.
- Calculamos la frecuencia de cada ciudad usando
- Ingeniería adicional de características:
- Calculamos la población media para cada ciudad usando
groupby()
ymean()
. - Mapeamos estas poblaciones medias de vuelta al DataFrame original.
- Calculamos la población media para cada ciudad usando
- Mostrando resultados:
- Imprimimos el DataFrame resultante para mostrar los datos originales junto con las nuevas características codificadas.
- También imprimimos la distribución de frecuencia de las ciudades.
- Visualización:
- Creamos dos gráficos de barras usando matplotlib:
a. Un gráfico que muestra la distribución de frecuencia de las ciudades.
b. Un gráfico que muestra la población media por ciudad. - Estas visualizaciones ayudan a entender la distribución de los datos categóricos y su relación con otras variables.
- Creamos dos gráficos de barras usando matplotlib:
- Manejo de nuevas categorías:
- Demostramos cómo manejar nuevas categorías que no estaban en el conjunto de datos original.
- Creamos un nuevo DataFrame con una ciudad ('Sídney') que no estaba en los datos originales.
- Usamos
map()
confillna(0)
para asignar frecuencias, dando un valor de 0 a la nueva categoría.
Este ejemplo muestra varios aspectos importantes del trabajo con datos categóricos de alta cardinalidad utilizando pandas:
- Codificación por frecuencia
- Ingeniería adicional de características (población media por categoría)
- Visualización de datos categóricos
- Manejo de nuevas categorías
Estas técnicas proporcionan un enfoque integral para manejar características de alta cardinalidad, ofreciendo tanto una reducción de la dimensionalidad como la creación de características significativas.
b. Codificación basada en el objetivo
La codificación basada en el objetivo es una técnica sofisticada utilizada en la ingeniería de características para variables categóricas. Implica reemplazar cada categoría con un valor numérico derivado de la media de la variable objetivo para esa categoría específica. Este método es especialmente valioso en tareas de aprendizaje supervisado por varias razones:
- Captura de relaciones: Captura eficazmente la relación entre la característica categórica y la variable objetivo, proporcionando al modelo una entrada más informativa.
- Reducción de la dimensionalidad: A diferencia de la codificación one-hot, la codificación basada en el objetivo no aumenta el número de características, lo que la hace adecuada para variables categóricas de alta cardinalidad.
- Poder predictivo: Los valores codificados reflejan directamente cómo se relaciona cada categoría con la variable objetivo, lo que potencialmente mejora las capacidades predictivas del modelo.
- Manejo de categorías raras: Puede manejar eficazmente categorías raras asignándoles valores basados en la variable objetivo, en lugar de crear características dispersas.
- Salida continua: La característica codificada resultante es continua, lo cual puede ser beneficioso para ciertos algoritmos que funcionan mejor con entradas numéricas.
Sin embargo, es importante tener en cuenta que la codificación basada en el objetivo debe usarse con precaución:
- Potencial de sobreajuste: Puede conducir al sobreajuste si no se valida adecuadamente, ya que utiliza información del objetivo en el paso de preprocesamiento.
- Fugas de datos: Se debe tener cuidado para evitar fugas de datos asegurando que la codificación se realice dentro de los pliegues de la validación cruzada.
- Interpretabilidad: Los valores codificados pueden ser menos interpretables que las categorías originales, lo que podría ser una desventaja en algunas aplicaciones donde la explicabilidad del modelo es crucial.
En general, la codificación basada en el objetivo es una herramienta poderosa que, cuando se usa adecuadamente, puede mejorar significativamente el rendimiento de los modelos de aprendizaje automático en datos categóricos.
Ejemplo: Codificación basada en el objetivo con Category Encoders
import category_encoders as ce
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# Create a larger sample dataset
np.random.seed(42)
cities = ['New York', 'London', 'Paris', 'Tokyo', 'Berlin']
n_samples = 1000
df = pd.DataFrame({
'City': np.random.choice(cities, n_samples),
'Target': np.random.randint(0, 2, n_samples)
})
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(df['City'], df['Target'], test_size=0.2, random_state=42)
# Initialize the TargetEncoder
target_encoder = ce.TargetEncoder()
# Fit and transform the training data
X_train_encoded = target_encoder.fit_transform(X_train, y_train)
# Transform the test data
X_test_encoded = target_encoder.transform(X_test)
# Train a logistic regression model
model = LogisticRegression(random_state=42)
model.fit(X_train_encoded, y_train)
# Make predictions on the test set
y_pred = model.predict(X_test_encoded)
# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Model Accuracy: {accuracy:.2f}")
# Display the encoding for each city
encoding_map = target_encoder.mapping[0]['mapping']
print("\nTarget Encoding Map:")
for city, encoded_value in encoding_map.items():
print(f"{city}: {encoded_value:.4f}")
# Visualize the target encoding
plt.figure(figsize=(10, 6))
plt.bar(encoding_map.keys(), encoding_map.values())
plt.title('Target Encoding of Cities')
plt.xlabel('City')
plt.ylabel('Encoded Value')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Demonstrate handling of unseen categories
new_cities = pd.Series(['New York', 'London', 'San Francisco'])
encoded_new_cities = target_encoder.transform(new_cities)
print("\nEncoding of New Cities (including unseen):")
print(encoded_new_cities)
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos bibliotecas adicionales, incluyendo numpy para la generación de números aleatorios, sklearn para el entrenamiento y evaluación del modelo, y matplotlib para la visualización.
- Creación de un conjunto de datos más grande:
- Generamos un conjunto de datos de muestra más grande con 1000 entradas y 5 ciudades diferentes para demostrar mejor el proceso de codificación basada en el objetivo.
- La variable 'Objetivo' es generada aleatoriamente como 0 o 1 para simular un problema de clasificación binaria.
- División de los datos:
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
train_test_split
para evaluar correctamente nuestra codificación y el modelo.
- Dividimos los datos en conjuntos de entrenamiento y prueba utilizando
- Codificación basada en el objetivo:
- Usamos
TargetEncoder
de la bibliotecacategory_encoders
para realizar la codificación basada en el objetivo. - El codificador se ajusta a los datos de entrenamiento y luego se usa para transformar tanto los datos de entrenamiento como los de prueba.
- Usamos
- Entrenamiento y evaluación del modelo:
- Entrenamos un modelo de regresión logística con los datos codificados.
- El modelo se usa luego para hacer predicciones en el conjunto de prueba, y calculamos su precisión.
- Visualización de la codificación:
- Extraemos el mapa de codificación del
TargetEncoder
para ver cómo se codificó cada ciudad. - Se crea un gráfico de barras para visualizar los valores codificados de cada ciudad.
- Extraemos el mapa de codificación del
- Manejo de categorías no vistas:
- Demostramos cómo
TargetEncoder
maneja nuevas categorías que no estaban presentes en los datos de entrenamiento.
- Demostramos cómo
Este ejemplo ofrece una visión más completa de la codificación basada en el objetivo, incluyendo:
- Trabajar con un conjunto de datos más grande y realista
- División adecuada en entrenamiento y prueba para evitar fugas de datos
- Entrenamiento y evaluación reales de un modelo utilizando las características codificadas
- Visualización de los resultados de la codificación
- Manejo de categorías no vistas
Este enfoque proporciona una imagen más completa de cómo se puede aplicar la codificación basada en el objetivo en una canalización de aprendizaje automático y sus efectos en el rendimiento del modelo.
3.3.6 Manejo de Datos Categóricos Faltantes
Los valores faltantes en los datos categóricos suponen un desafío importante en la fase de preprocesamiento de proyectos de aprendizaje automático. Estas lagunas en el conjunto de datos pueden afectar significativamente la precisión y fiabilidad del modelo si no se abordan adecuadamente. La presencia de valores faltantes puede llevar a resultados sesgados, reducción de la potencia estadística y conclusiones incorrectas. Por lo tanto, es crucial manejarlos con cuidado y consideración.
Existen varias estrategias para tratar los datos categóricos faltantes, cada una con sus ventajas y posibles inconvenientes:
- Eliminación: Implica eliminar filas o columnas con valores faltantes. Aunque es simple, puede llevar a la pérdida de información valiosa.
- Imputación: Este método implica llenar los valores faltantes con estimaciones. Algunas técnicas comunes incluyen imputación por moda, imputación mediante un modelo de predicción, o el uso de una categoría dedicada como "Faltante".
- Métodos avanzados: Incluyen el uso de algoritmos que pueden manejar directamente los valores faltantes o técnicas de imputación múltiple que tienen en cuenta la incertidumbre en los datos faltantes.
La elección de la estrategia depende de factores como la cantidad de datos faltantes, el mecanismo de la falta de datos (si es completamente al azar, al azar, o no al azar), y los requisitos específicos de tu tarea de aprendizaje automático. A menudo es beneficioso experimentar con múltiples enfoques y evaluar su impacto en el rendimiento de tu modelo.
a. Imputación de valores faltantes con la moda
Para datos categóricos nominales, un enfoque común es reemplazar los valores faltantes con la categoría más frecuente (moda).
Ejemplo: Imputación de valores categóricos faltantes
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
# Sample data with missing values
df = pd.DataFrame({
'City': ['New York', 'London', None, 'Paris', 'Paris', 'London', None, 'Tokyo', 'Berlin', None],
'Population': [8400000, 8900000, None, 2100000, 2100000, 8900000, None, 13900000, 3700000, None],
'IsCapital': [False, True, None, True, True, True, None, True, True, None]
})
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Method 1: Fill missing values with the mode (most frequent value)
df['City_Mode'] = df['City'].fillna(df['City'].mode()[0])
# Method 2: Fill missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# Method 3: Use SimpleImputer for numerical data (Population)
imputer = SimpleImputer(strategy='mean')
df['Population_Imputed'] = imputer.fit_transform(df[['Population']])
# Method 4: Forward fill for IsCapital (assuming temporal order)
df['IsCapital_Ffill'] = df['IsCapital'].ffill()
print("\nDataFrame after handling missing values:")
print(df)
# Visualize missing data
plt.figure(figsize=(10, 6))
plt.imshow(df.isnull(), cmap='viridis', aspect='auto')
plt.title('Missing Value Heatmap')
plt.xlabel('Columns')
plt.ylabel('Rows')
plt.colorbar(label='Missing (Yellow)')
plt.tight_layout()
plt.show()
# Compare original and imputed data distributions
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['Population'].hist(ax=ax1, bins=10)
ax1.set_title('Original Population Distribution')
ax1.set_xlabel('Population')
ax1.set_ylabel('Frequency')
df['Population_Imputed'].hist(ax=ax2, bins=10)
ax2.set_title('Imputed Population Distribution')
ax2.set_xlabel('Population')
ax2.set_ylabel('Frequency')
plt.tight_layout()
plt.show()
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
SimpleImputer
de sklearn para la imputación de valores numéricos.
- Importamos pandas para la manipulación de datos, matplotlib para la visualización y
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
None
).
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana), incluyendo valores faltantes (
- Mostrando los datos originales:
- Imprimimos el DataFrame original y la cantidad de valores faltantes en cada columna.
- Manejo de valores faltantes:
- Método 1 (Imputación por moda): Rellenamos los valores faltantes en la columna 'Ciudad' con la ciudad más frecuente.
- Método 2 (Nueva categoría): Creamos una nueva columna donde las ciudades faltantes se reemplazan por 'Desconocido'.
- Método 3 (Imputación por media): Utilizamos
SimpleImputer
para rellenar los valores faltantes en la columna 'Población' con la media de la población. - Método 4 (Relleno hacia adelante): Utilizamos el método de relleno hacia adelante para la columna 'EsCapital', asumiendo un orden temporal en los datos.
- Visualización de datos faltantes:
- Creamos un mapa de calor para visualizar el patrón de valores faltantes en todo el DataFrame.
- Comparación de distribuciones:
- Creamos histogramas para comparar la distribución de los datos originales de 'Población' con los datos imputados.
Este ejemplo demuestra múltiples técnicas para manejar datos faltantes tanto categóricos como numéricos, incluyendo:
- Imputación por moda para datos categóricos
- Creación de una nueva categoría para valores faltantes
- Imputación por media para datos numéricos usando
SimpleImputer
- Relleno hacia adelante para datos potencialmente ordenados
- Visualización de patrones de datos faltantes
- Comparación de las distribuciones de los datos originales e imputados
Estas técnicas proporcionan un enfoque integral para tratar los datos faltantes, mostrando tanto los métodos de manejo como formas de analizar el impacto de estos métodos en tu conjunto de datos.
b. Usando una categoría separada para datos faltantes
Otra estrategia para manejar valores faltantes en datos categóricos es crear una categoría separada, comúnmente etiquetada como "Desconocido" o "Faltante". Este método implica introducir una nueva categoría específicamente para representar los puntos de datos faltantes. Al hacerlo, se reconoce explícitamente la ausencia de información y se trata como una categoría distinta en sí misma.
Este enfoque ofrece varias ventajas:
- Preservación de información: Retiene el hecho de que los datos estaban faltantes, lo cual podría ser significativo en ciertos análisis.
- Interpretabilidad del modelo: Permite que los modelos aprendan patrones asociados con los datos faltantes.
- Simplicidad: Es fácil de implementar y comprender.
- Consistencia: Proporciona una manera uniforme de manejar valores faltantes en diferentes variables categóricas.
Sin embargo, es importante considerar posibles desventajas:
- Aumento de la dimensionalidad: Para datos codificados con one-hot encoding, agrega una dimensión adicional.
- Posible sesgo: Si los datos faltantes no son aleatorios, este método podría introducir sesgo.
- Pérdida de potencia estadística: En algunos análisis, tratar los datos faltantes como una categoría separada podría reducir la potencia estadística.
Al decidir si usar este enfoque, considera la naturaleza de tus datos, la razón de la falta de datos y los requisitos específicos de tu análisis o tarea de aprendizaje automático.
Ejemplo: Reemplazo de valores faltantes con una nueva categoría
import pandas as pd
import matplotlib.pyplot as plt
# Create a sample dataset with missing values
data = {
'City': ['New York', 'London', None, 'Paris', 'Tokyo', None, 'Berlin', 'Madrid', None, 'Rome'],
'Population': [8.4, 9.0, None, 2.2, 13.9, None, 3.7, 3.2, None, 4.3],
'IsCapital': [False, True, None, True, True, None, True, True, None, True]
}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
print("\nMissing values count:")
print(df.isnull().sum())
# Replace missing values with a new category 'Unknown'
df['City_Unknown'] = df['City'].fillna('Unknown')
# For numerical data, we can use mean imputation
df['Population_Imputed'] = df['Population'].fillna(df['Population'].mean())
# For boolean data, we can use mode imputation
df['IsCapital_Imputed'] = df['IsCapital'].fillna(df['IsCapital'].mode()[0])
print("\nDataFrame after handling missing values:")
print(df)
# Visualize the distribution of cities before and after imputation
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
df['City'].value_counts().plot(kind='bar', ax=ax1, title='City Distribution (Before)')
ax1.set_ylabel('Count')
df['City_Unknown'].value_counts().plot(kind='bar', ax=ax2, title='City Distribution (After)')
ax2.set_ylabel('Count')
plt.tight_layout()
plt.show()
# Analyze the impact of imputation on Population
print("\nPopulation statistics before imputation:")
print(df['Population'].describe())
print("\nPopulation statistics after imputation:")
print(df['Population_Imputed'].describe())
Explicación del desglose del código:
- Importación de bibliotecas:
- Importamos pandas para la manipulación de datos y matplotlib para la visualización.
- Creación de datos de ejemplo:
- Creamos un DataFrame con tres columnas: 'Ciudad' (categórica), 'Población' (numérica) y 'EsCapital' (booleana).
- El conjunto de datos incluye valores faltantes (None) para demostrar diferentes técnicas de imputación.
- Mostrando los datos originales:
- Imprimimos el DataFrame original y contamos los valores faltantes en cada columna.
- Manejo de valores faltantes:
- Para la columna 'Ciudad', creamos una nueva columna 'Ciudad_Desconocida', donde los valores faltantes se reemplazan por 'Desconocido'.
- Para la columna 'Población', usamos imputación por media para rellenar los valores faltantes.
- Para la columna 'EsCapital', utilizamos imputación por moda para completar los valores faltantes.
- Visualización de los datos:
- Creamos gráficos de barras para comparar la distribución de las ciudades antes y después de la imputación.
- Esto ayuda a visualizar el impacto de agregar la categoría 'Desconocido'.
- Análisis del impacto de la imputación:
- Imprimimos estadísticas descriptivas de la columna 'Población' antes y después de la imputación.
- Esto nos permite ver cómo la imputación por media afecta la distribución general de los datos.
Este ejemplo ampliado demuestra un enfoque más integral para manejar datos faltantes, incluyendo:
- Uso de una nueva categoría ('Desconocido') para datos faltantes categóricos
- Aplicación de imputación por media para datos numéricos
- Uso de imputación por moda para datos booleanos
- Visualización del impacto de la imputación en los datos categóricos
- Análisis del impacto estadístico de la imputación en los datos numéricos
Este enfoque proporciona una visión completa de cómo aplicar diferentes técnicas de imputación y sus efectos en el conjunto de datos, lo cual es crucial para comprender los impactos potenciales en los análisis o modelos de aprendizaje automático posteriores.
Este enfoque marca explícitamente los datos faltantes, lo que a veces puede ayudar a los modelos a aprender que la falta de datos es significativa.