Columnas calculadas y condicionales
Crea nuevas columnas con lógica personalizada.
Los datos originales rara vez contienen toda la información que necesitas para el análisis. En esta lección aprenderás a crear columnas nuevas calculadas a partir de datos existentes, sin modificar las fuentes originales.
Columnas en Power Query vs DAX
Antes de empezar, es crucial entender la diferencia:
| Aspecto | Columnas en Power Query | Columnas calculadas en DAX |
|---|---|---|
| Cuándo se calculan | Al cargar/refrescar datos | En tiempo real al visualizar |
| Almacenamiento | Físicas en el modelo | Físicas en el modelo |
| Contexto | Fila por fila (sin filtros del reporte) | Contexto de fila + filtros |
| Performance | Se calcula una vez | Se recalcula con cada interacción |
| Query Folding | Puede mantenerlo | No aplica |
| Uso ideal | Transformaciones de datos, limpieza | Cálculos de negocio, agregaciones |
Regla de oro: Si puedes calcular la columna en Power Query, hazlo ahí. Es más eficiente.
Ejemplos que van en Power Query:
- Extraer año de una fecha
- Concatenar nombre y apellido
- Clasificar valores en rangos
- Calcular edad a partir de fecha de nacimiento
Ejemplos que van en DAX:
- Comparar ventas con promedio del sector (filtros dinámicos)
- Clasificar producto según ventas relativas del año seleccionado
- Cálculos que dependen del contexto del usuario
1. Columna personalizada con lenguaje M
La forma más flexible de crear columnas calculadas.
Anatomía de una columna personalizada
- Ve a Agregar columna > Columna personalizada
- Aparece diálogo con:
- Nuevo nombre de columna: Nombre descriptivo
- Fórmula de columna personalizada: Código M
- Columnas disponibles: Lista de columnas existentes
Sintaxis básica
// Referencia a columna actual
[NombreColumna]
// Operaciones aritméticas
[Precio] * [Cantidad]
// Concatenación de texto
[Nombre] & " " & [Apellido]
// Condicional simple
if [Ventas] > 1000 then "Alto" else "Bajo"
Ejemplo 1: Calcular total de venta
Datos originales:
ProductoID | Cantidad | PrecioUnitario
-----------|----------|---------------
P001 | 5 | 25.50
P002 | 2 | 100.00
Agregar columna Total:
- Agregar columna > Columna personalizada
- Nombre:
Total - Fórmula:
[Cantidad] * [PrecioUnitario]
- Aceptar
Resultado:
ProductoID | Cantidad | PrecioUnitario | Total
-----------|----------|----------------|-------
P001 | 5 | 25.50 | 127.50
P002 | 2 | 100.00 | 200.00
Tipo de dato: Power Query intenta detectarlo, pero verifica y ajusta si es necesario.
Ejemplo 2: Nombre completo
Datos:
ClienteID | Nombre | Apellido
----------|--------|----------
C001 | Juan | Pérez
C002 | Ana | López
Fórmula:
[Nombre] & " " & [Apellido]
Resultado:
NombreCompleto
--------------
Juan Pérez
Ana López
Ejemplo 3: Clasificación de ventas
Datos:
VentaID | Monto
--------|-------
V001 | 500
V002 | 1500
V003 | 800
Fórmula con condicional:
if [Monto] >= 1000 then "Alto"
else if [Monto] >= 500 then "Medio"
else "Bajo"
Resultado:
Monto | Clasificación
------|---------------
500 | Medio
1500 | Alto
800 | Medio
Funciones comunes en columnas personalizadas
Funciones de texto
// Mayúsculas
Text.Upper([Nombre])
// Resultado: "JUAN PÉREZ"
// Minúsculas
Text.Lower([Email])
// Resultado: "juan@email.com"
// Capitalizar cada palabra
Text.Proper([Nombre])
// Resultado: "Juan Pérez"
// Longitud de texto
Text.Length([Código])
// Resultado: 5
// Extraer caracteres
Text.Start([Código], 3)
// Resultado: "ABC" de "ABC123"
Text.End([Código], 3)
// Resultado: "123" de "ABC123"
// Reemplazar
Text.Replace([Teléfono], "-", "")
// Resultado: "5551234567" de "555-123-4567"
// Verificar si contiene
Text.Contains([Email], "@")
// Resultado: true/false
Funciones numéricas
// Redondear
Number.Round([Precio], 2)
// Resultado: 19.99 de 19.9876
// Redondear hacia arriba
Number.RoundUp([Total])
// Resultado: 101 de 100.01
// Redondear hacia abajo
Number.RoundDown([Total])
// Resultado: 100 de 100.99
// Valor absoluto
Number.Abs([Diferencia])
// Resultado: 50 de -50
// Módulo (resto de división)
Number.Mod([Número], 2)
// Resultado: 0 (par) o 1 (impar)
Funciones de fecha
// Fecha actual
Date.From(DateTime.LocalNow())
// Año
Date.Year([FechaVenta])
// Resultado: 2026
// Mes (número)
Date.Month([FechaVenta])
// Resultado: 1 (enero)
// Día
Date.Day([FechaVenta])
// Resultado: 27
// Nombre del mes
Date.MonthName([FechaVenta])
// Resultado: "January" (inglés por defecto)
// Día de la semana
Date.DayOfWeek([FechaVenta])
// Resultado: 0 (domingo) a 6 (sábado)
// Diferencia entre fechas
Duration.Days([FechaEntrega] - [FechaOrden])
// Resultado: 5 (días)
// Agregar días
Date.AddDays([FechaInicio], 30)
// Resultado: fecha 30 días después
Funciones lógicas
// Verificar nulo
if [Columna] = null then "Sin datos" else [Columna]
// Múltiples condiciones (AND)
if [Ventas] > 1000 and [Región] = "Norte" then "Destacado" else "Normal"
// Múltiples condiciones (OR)
if [Estado] = "Cancelado" or [Estado] = "Rechazado" then "Inactivo" else "Activo"
// Negación
if not Text.Contains([Email], "@") then "Email inválido" else "OK"
Manejo de errores en columnas personalizadas
// Intentar conversión, usar valor por defecto si falla
try Number.From([Texto]) otherwise 0
// Ejemplo: Calcular descuento, manejar división por cero
try [Descuento] / [PrecioOriginal] otherwise 0
2. Columna condicional (interfaz visual)
Para condicionales simples sin escribir código M.
Cuándo usar columna condicional
✅ Condiciones basadas en una sola columna ✅ IF/THEN/ELSE simples ✅ Clasificaciones o categorizaciones ✅ No requieres cálculos complejos
Paso a paso
Escenario: Clasificar clientes por monto de compra
Datos:
ClienteID | TotalCompras
----------|-------------
C001 | 500
C002 | 2500
C003 | 1200
Crear columna condicional:
- Agregar columna > Columna condicional
- Nuevo nombre de columna:
Segmento - Configurar condiciones:
Si [TotalCompras] es mayor o igual que 2000
Entonces: "Premium"
Sino si [TotalCompras] es mayor o igual que 1000
Entonces: "Gold"
Sino si [TotalCompras] es mayor o igual que 500
Entonces: "Silver"
De lo contrario: "Básico"
- Aceptar
Resultado:
ClienteID | TotalCompras | Segmento
----------|--------------|----------
C001 | 500 | Silver
C002 | 2500 | Premium
C003 | 1200 | Gold
Código M generado:
= Table.AddColumn(#"Paso anterior", "Segmento", each
if [TotalCompras] >= 2000 then "Premium"
else if [TotalCompras] >= 1000 then "Gold"
else if [TotalCompras] >= 500 then "Silver"
else "Básico")
Operadores disponibles
| Operador | Descripción | Ejemplo |
|---|---|---|
| es igual a | Igualdad exacta | [Estado] = "Activo" |
| no es igual a | Diferente | [Estado] ≠ "Cancelado" |
| es mayor que | Estrictamente mayor | [Edad] > 18 |
| es mayor o igual que | Mayor o igual | [Ventas] ≥ 1000 |
| es menor que | Estrictamente menor | [Stock] < 10 |
| es menor o igual que | Menor o igual | [Descuento] ≤ 0.5 |
| empieza con | Texto inicia con | [Código] empieza con "A" |
| no empieza con | Texto NO inicia con | [Email] no empieza con "test" |
| termina con | Texto finaliza con | [Archivo] termina con ".xlsx" |
| no termina con | Texto NO finaliza con | - |
| contiene | Texto contiene substring | [Descripción] contiene "urgente" |
| no contiene | Texto NO contiene | [Comentario] no contiene "spam" |
3. Columnas de fecha y hora
Las fechas son críticas para análisis de series temporales.
Extraer componentes de fecha
Método visual: Selecciona columna de fecha > Agregar columna > Fecha
Opciones disponibles:
- Edad: Días desde la fecha hasta hoy
- Solo fecha: Remueve componente de hora
- Año
- Inicio del año: 1 de enero del año de la fecha
- Fin del año: 31 de diciembre
- Mes (número 1-12)
- Inicio del mes: Primer día del mes
- Fin del mes: Último día del mes
- Días en el mes: 28, 29, 30 o 31
- Día (número 1-31)
- Día de la semana (número 0-6)
- Nombre del día: "Monday", "Tuesday"...
- Trimestre del año: 1, 2, 3, 4
- Semana del año: 1-52
- Semana del mes: 1-5
Ejemplo: Extraer año, mes y trimestre
- Selecciona columna FechaVenta
- Agregar columna > Fecha > Año
- Repite: Mes
- Repite: Trimestre del año
Resultado:
FechaVenta | Año | Mes | Trimestre del año
------------|------|-----|-------------------
2026-01-27 | 2026 | 1 | 1
2026-06-15 | 2026 | 6 | 2
2026-10-03 | 2026 | 10 | 4
Crear columna de hora
Selecciona columna fecha/hora > Agregar columna > Hora
Opciones:
- Hora (0-23)
- Minuto (0-59)
- Segundo (0-59)
- Solo hora: Remueve componente de fecha
Calcular edad o antigüedad
Escenario: Días desde la venta hasta hoy
Método 1: Visual
- Selecciona columna FechaVenta
- Agregar columna > Fecha > Edad
- Se crea columna con valor tipo
Duration
Método 2: Personalizada con días específicos
Duration.Days(Date.From(DateTime.LocalNow()) - [FechaVenta])
Ejemplo práctico: Clasificar por antigüedad
let
DiasAntiguedad = Duration.Days(DateTime.LocalNow() - [FechaContratación]),
Clasificación =
if DiasAntiguedad > 1825 then "5+ años"
else if DiasAntiguedad > 730 then "2-5 años"
else if DiasAntiguedad > 365 then "1-2 años"
else "Menos de 1 año"
in
Clasificación
4. Columna de índice
Agrega una columna con números secuenciales.
Tipos de índice
- Agregar columna > Columna de índice
- Desde 0: 0, 1, 2, 3...
- Desde 1: 1, 2, 3, 4...
- Personalizado: Inicio y incremento a elegir
Usos comunes:
- Crear ID único temporal
- Ranking o posición en lista ordenada
- Agrupar cada N filas
Ejemplo: Ranking de ventas
- Ordena por columna Ventas (descendente)
- Agregar columna > Columna de índice > Desde 1
- Renombra a "Ranking"
Resultado:
Producto | Ventas | Ranking
----------|--------|--------
Laptop | 15000 | 1
Monitor | 8000 | 2
Mouse | 500 | 3
Código M:
= Table.AddIndexColumn(#"Paso anterior", "Ranking", 1, 1)
Índice personalizado
Escenario: Números de lote de 100 en 100
- Agregar columna > Columna de índice > Personalizado
- Valor inicial: 100
- Incremento: 100
- Aceptar
Resultado: 100, 200, 300, 400...
5. Duplicar columna
Para crear copia de una columna antes de transformarla.
- Clic derecho en columna
- Duplicar columna
- Se crea "Columna - Copia"
Uso: Mantener valor original mientras pruebas transformaciones en la copia.
6. Columna a partir de ejemplos
Power Query puede inferir la transformación basándose en ejemplos que proporciones.
Cómo funciona
- Agregar columna > Columna a partir de ejemplos
- De todas las columnas: Usa cualquier columna existente
- De la selección: Usa solo columnas seleccionadas
- Escribe ejemplos en las primeras filas
- Power Query sugiere valores para las demás
- Si es correcto, presiona Aceptar
Ejemplo: Extraer código de área de teléfono
Datos:
Teléfono
--------------
(555) 123-4567
(214) 987-6543
(310) 555-0199
Pasos:
- Agregar columna > Columna a partir de ejemplos
- En la primera fila de la nueva columna, escribe:
555 - En la segunda fila, escribe:
214 - Power Query detecta el patrón y completa:
310 - Verifica y Aceptar
Código M generado automáticamente:
= Table.AddColumn(#"Paso anterior", "Código de área", each Text.BetweenDelimiters([Teléfono], "(", ")"), type text)
¡Increíble! Power Query escribió la fórmula por ti.
Ejemplo: Formato de fecha personalizado
Datos:
FechaVenta
-----------
2026-01-27
2026-06-15
Objetivo: "Ene 2026", "Jun 2026"
- Agregar columna > Columna a partir de ejemplos
- Escribe:
Ene 2026 - Escribe:
Jun 2026 - Power Query genera fórmula automáticamente
Limitaciones:
- Funciona mejor con patrones claros y consistentes
- Puede requerir varios ejemplos para patrones complejos
- Revisa el código M generado (a veces es ineficiente)
7. Casos de Uso Prácticos
Caso 1: Clasificación ABC de productos
Objetivo: Clasificar productos por contribución a ventas
// Columna personalizada: Clasificación ABC
if [%AcumuladoVentas] <= 0.80 then "A"
else if [%AcumuladoVentas] <= 0.95 then "B"
else "C"
Contexto:
- A: 80% de las ventas (productos clave)
- B: Siguiente 15% (importantes)
- C: Último 5% (menor impacto)
Caso 2: Días hasta entrega
Objetivo: Calcular tiempo de entrega en días
// Columna personalizada: DíasEntrega
Duration.Days([FechaEntrega] - [FechaPedido])
Uso: Identificar pedidos con retrasos
Caso 3: Email corporativo vs personal
Objetivo: Clasificar tipo de email
// Columna condicional
if Text.EndsWith([Email], "@empresa.com") then "Corporativo" else "Personal"
O con múltiples dominios:
// Columna personalizada
let
Dominio = Text.AfterDelimiter([Email], "@"),
Tipo = if List.Contains({"empresa.com", "empresa.mx"}, Dominio)
then "Corporativo"
else "Personal"
in
Tipo
Caso 4: Nombre de mes en español
Problema: Date.MonthName devuelve nombres en inglés
Solución:
// Columna personalizada: MesNombre
let
NumeroMes = Date.Month([Fecha]),
NombreMes =
if NumeroMes = 1 then "Enero"
else if NumeroMes = 2 then "Febrero"
else if NumeroMes = 3 then "Marzo"
else if NumeroMes = 4 then "Abril"
else if NumeroMes = 5 then "Mayo"
else if NumeroMes = 6 then "Junio"
else if NumeroMes = 7 then "Julio"
else if NumeroMes = 8 then "Agosto"
else if NumeroMes = 9 then "Septiembre"
else if NumeroMes = 10 then "Octubre"
else if NumeroMes = 11 then "Noviembre"
else "Diciembre"
in
NombreMes
8. Mejores Prácticas
Nombres descriptivos
❌ Columna personalizada 1, Custom
✅ TotalVenta, ClasificaciónCliente, AñoVenta
Orden de transformaciones
- Columnas básicas primero (año, mes de fechas)
- Cálculos simples (Total = Cantidad × Precio)
- Clasificaciones (basadas en cálculos previos)
- Columnas de índice al final (después de ordenar)
Documentación
Agrega comentarios en código M complejo:
// Clasificar cliente según compras anuales
// Premium: $2000+, Gold: $1000-$2000, Silver: $500-$1000, Básico: <$500
if [TotalCompras] >= 2000 then "Premium"
else if [TotalCompras] >= 1000 then "Gold"
else if [TotalCompras] >= 500 then "Silver"
else "Básico"
Verificación de tipos
Después de crear columna calculada:
- Verifica que el tipo de dato sea correcto
- Revisa valores nulos inesperados
- Usa vista de Calidad de columna
Performance
✅ Usa columnas condicionales visuales para condiciones simples (más rápidas) ✅ Evita cálculos innecesarios (si no lo vas a usar, no lo calcules) ✅ Aprovecha Query Folding cuando sea posible ❌ No uses columnas personalizadas para hacer lookup (usa Merge)
Puntos Clave de esta Lección
- Columnas en Power Query son físicas y se calculan al refrescar - A diferencia de medidas DAX que son dinámicas
- Prefiere Power Query sobre DAX para transformaciones - Más eficiente calcularlo al cargar que en tiempo real
- Columna personalizada para cálculos complejos - Lenguaje M completo disponible
- Columna condicional para clasificaciones simples - Interfaz visual más rápida
- Extraer componentes de fecha es esencial - Año, mes, trimestre para análisis temporal
- Columna de índice útil para rankings - Ordena primero, agrega índice después
- Columna a partir de ejemplos es mágica - Pero verifica el código generado
- Nombres descriptivos y documentación - El futuro tú te lo agradecerá
Verificación de Conocimientos
Pregunta 1
Tienes una columna Precio con valores 19.99, 25.50, 30.00. Necesitas una columna que diga "Bajo" si <20, "Medio" si 20-30, "Alto" si >30. ¿Qué método es más apropiado?
A) Columna personalizada con código M B) Columna condicional con interfaz visual C) Columna calculada en DAX D) Merge con tabla de rangos
Ver respuesta
Respuesta: B) Columna condicional con interfaz visual
Es una clasificación simple basada en rangos de una sola columna. Columna condicional es perfecta: rápida, sin código, y genera M eficiente. Columna personalizada también funciona pero es innecesaria. DAX es incorrecto (hazlo en Power Query si puedes). Merge es excesivo para esto.
Pregunta 2
¿Cuál de estas columnas NO debería crearse en Power Query?
A) Año extraído de FechaVenta B) Total = Cantidad × PrecioUnitario C) Comparación de ventas del producto vs promedio de productos en filtro actual del usuario D) Clasificación de cliente según TotalCompras
Ver respuesta
Respuesta: C) Comparación de ventas del producto vs promedio de productos en filtro actual del usuario
Esta requiere contexto dinámico que cambia según filtros del usuario. Solo DAX puede manejar esto. Las otras son cálculos estáticos que se calculan una vez al cargar datos, perfectas para Power Query.
Pregunta 3
Tienes columnas Nombre ("Juan") y Apellido ("Pérez"). ¿Qué código M crea "Juan Pérez"?
A) [Nombre] + [Apellido] B) [Nombre] & " " & [Apellido] C) Concatenate([Nombre], [Apellido]) D) [Nombre] , [Apellido]
Ver respuesta
Respuesta: B) [Nombre] & " " & [Apellido]
En lenguaje M, & es el operador de concatenación de texto. El espacio " " entre las columnas asegura que no quede "JuanPérez" pegado. + es para operaciones numéricas. Concatenate() no existe en M. La opción D crearía una lista, no texto.
Resumen del Módulo 3
¡Felicidades! Has completado el módulo de Transformar Datos con Power Query. Ahora sabes:
✅ Navegar el Editor de Power Query - Interfaz, pasos aplicados, Query Folding ✅ Limpiar datos - Duplicados, nulos, errores, tipos de datos, formatos de texto ✅ Combinar tablas - Merge (joins) y Append (consolidación) de múltiples fuentes ✅ Crear columnas calculadas - Personalizadas, condicionales, de fecha, índices
Flujo completo de preparación de datos
1. CONECTAR
↓
2. FILTRAR filas innecesarias (reduce volumen)
↓
3. SELECCIONAR columnas relevantes (reduce ancho)
↓
4. LIMPIAR (duplicados, nulos, espacios)
↓
5. TIPOS DE DATOS correctos
↓
6. COMBINAR con otras tablas (Merge/Append)
↓
7. COLUMNAS CALCULADAS (clasificaciones, extracciones)
↓
8. CERRAR Y APLICAR
Próximo módulo
En el Módulo 4 aprenderás a Modelar Datos en Power BI:
- Crear relaciones entre tablas
- Esquemas estrella vs copo de nieve
- Cardinalidad y dirección de filtro
- Tablas de dimensiones y hechos
- Jerarquías para drill-down
El modelado correcto es la base de reportes eficientes y cálculos DAX poderosos. Tus datos ya están limpios y transformados, ahora los estructurarás para análisis.
Completaste esta leccion?
Marca esta leccion como completada. Tu progreso se guardara en tu navegador.