Target Encoding en Power BI: La Guía Definitiva Sin Data Leakage

Target Encoding en Power BI:
La Guía Definitiva Sin Data Leakage

Agregar columna índice

Domina esta técnica esencial para modelos predictivos con validación cruzada, smoothing y prevención de overfitting. Código M paso a paso + mejores prácticas.

¿Qué es Target Encoding (Mean Encoding)?

Target Encoding es una técnica de codificación categórica que reemplaza cada categoría por el promedio de la variable objetivo para esa categoría. Es especialmente poderosa en modelos predictivos porque captura la relación real entre la categoría y el resultado.

Ejemplo Simple:
Ciudad Ventas
Madrid1000
Barcelona800
Madrid1200
Valencia600
Target Encoding:
Ciudad Target_Encoded
Madrid1100
Barcelona800
Valencia600
Ventaja clave: Reduce dimensionalidad (1 columna vs. N en One-Hot) y mejora el rendimiento predictivo al codificar información útil.

¿Cuándo Usar Target Encoding?

Alta Cardinalidad

>50 categorías únicas

ML Supervisado

Regresión o clasificación

Feature Engineering

AutoML, XGBoost, etc.

Riesgos Críticos: Data Leakage y Overfitting

Data Leakage: El Error Más Común

Si calculas el promedio usando toda la tabla y luego entrenas el modelo, el modelo ve información del futuro. ¡Overfitting garantizado!

Incorrecto (Data Leakage)
// ¡NO HAGAS ESTO!
PromedioGlobal = Table.Group(TodaLaTabla, {"Ciudad"}, {{"Avg", each List.Average([Ventas])}})
Correcto (Sin Leakage)
// Usa solo datos de entrenamiento
PromedioTrain = Table.Group(Entrenamiento, {"Ciudad"}, {{"Avg", each List.Average([Ventas])}})

Implementación Paso a Paso en Power Query

1 Prepara tus datos

Asegúrate de tener una columna categórica (ej. Ciudad) y una variable objetivo numérica (ej. Ventas).

2 Divide en Entrenamiento y Prueba

Usa Table.AddIndexColumn + Table.SelectRows para separar datos.

let
    Fuente = TuTabla,
    ConIndice = Table.AddIndexColumn(Fuente, "Índice", 0, 1),
    TotalFilas = Table.RowCount(ConIndice),
    Entrenamiento = Table.SelectRows(ConIndice, each [Índice] < TotalFilas * 0.8),
    Prueba = Table.SelectRows(ConIndice, each [Índice] >= TotalFilas * 0.8)
in
    [Entrenamiento, Prueba]

3 Calcula promedios en Entrenamiento

Promedios = Table.Group(Entrenamiento, {"Ciudad"}, {
    {"Target_Mean", each List.Average([Ventas]), type number},
    {"Conteo", each Table.RowCount(_), Int64.Type}
})

4 Une con todo el dataset

Resultado = Table.NestedJoin(Fuente, {"Ciudad"}, Promedios, {"Ciudad"}, "Encoding", JoinKind.LeftOuter),
Expandido = Table.ExpandTableColumn(Resultado, "Encoding", {"Target_Mean", "Conteo"}, {"Target_Encoded", "Cat_Count"})

Código M Completo (Listo para Copiar)

let
    // 1. Cargar datos
    Fuente = TuTablaOriginal,
    
    // 2. Agregar índice para división
    ConIndice = Table.AddIndexColumn(Fuente, "Índice", 0, 1, Int64.Type),
    TotalFilas = Table.RowCount(ConIndice),
    
    // 3. Dividir 80/20
    Entrenamiento = Table.SelectRows(ConIndice, each [Índice] < TotalFilas * 0.8),
    Prueba = Table.SelectRows(ConIndice, each [Índice] >= TotalFilas * 0.8),
    
    // 4. Calcular Target Encoding en entrenamiento
    EncodingTable = Table.Group(Entrenamiento, {"Ciudad"}, {
        {"Target_Mean", each List.Average([Ventas]), type nullable number},
        {"Cat_Count", each Table.RowCount(_), Int64.Type}
    }),
    
    // 5. Calcular promedio global (para smoothing)
    PromedioGlobal = List.Average(Entrenamiento[Ventas]),
    
    // 6. Aplicar smoothing (evita overfitting en categorías raras)
    MinSamples = 10,
    EncodingConSmoothing = Table.AddColumn(EncodingTable, "Target_Encoded", each 
        if [Cat_Count] < MinSamples then PromedioGlobal
        else ([Target_Mean] * [Cat_Count] + PromedioGlobal * MinSamples) / ([Cat_Count] + MinSamples)
    ),
    
    // 7. Unir con dataset completo
    Resultado = Table.NestedJoin(ConIndice, {"Ciudad"}, EncodingConSmoothing, {"Ciudad"}, "Temp", JoinKind.LeftOuter),
    Expandido = Table.ExpandTableColumn(Resultado, "Temp", {"Target_Encoded"}, {"Ciudad_Target"}),
    
    // 8. Limpiar
    Final = Table.SelectColumns(Expandido, List.RemoveItems(Table.ColumnNames(Expandido), {"Índice", "Temp"}))
in
    Final
Smoothing incluido: Categorías con menos de 10 muestras usan promedio global. ¡Evita overfitting!

Uso en DAX: Medidas Dinámicas

Ventas_Promedio_Ciudad = 
CALCULATE(
    AVERAGE(Ventas[Ventas]),
    ALLEXCEPT(Ciudades, Ciudades[Ciudad])
)

// Con filtro de fecha
Impacto_Temporal = 
CALCULATE(
    [Ventas_Promedio_Ciudad],
    DATESINPERIOD(Calendar[Date], MAX(Calendar[Date]), -30, DAY)
)

Conclusión: Tu Modelo Listo para Producción

Sin Data Leakage
Baja Dimensionalidad
Mejor Predicción

¡Ya dominas Target Encoding como un Data Scientist profesional! Implementa esta técnica en tus modelos de AutoML, exporta a Azure ML o intégrala en dashboards predictivos.

Entradas populares de este blog

Cómo Equilibrar Múltiples Productos con Pedidos a la Medida

Maximiza la rentabilidad de tu negocio: Cómo optimizar la selección de proveedores de mercancías.

Descubriendo el Poder de los Modelos de Clasificación en Machine Learning: Predicciones Precisas y Clasificaciones Sorprendentes

Optimización del Inventario Multiproducto en Espacios Reducidos: Una guía para la eficiencia en gestión de stocks

Domina tu Almacén sin arruinarte: El Juego del Modelo de Inventario Múltiproductos con Presupuesto ajustado

¡Plan Desagregado de Producción como un jefe!

Análisis ABC en Power BI con DAX: Guía Completa para Profesionales

El Desafío del Empaque en Contenedores: Optimizando Espacios en contenedores con Ingenio

¡Optimización de Portafolios de Productos: El arte de maximizar el rendimiento!

Cómo Realizar One-Hot Encoding en Power BI: Guía Paso a Paso para Principiantes y Expertos