Saltar al contenido

lección 5

Great Expectations: el framework profesional de validación

Instalación, Expectations, Suites, Data Sources y reportes HTML. El estándar de la industria para validación de datos.

55 min

### De artesanal a industrial: por qué necesitas un framework

En la lección anterior construiste validadores con Python puro. Funcionan. Pero imagina que tu empresa tiene 47 tablas, cada una con 15-20 reglas de validación, y el equipo crece de 2 a 8 ingenieros. De repente necesitas: reportes que los no-técnicos puedan leer, historial de resultados, integración con Airflow, documentación automática de las reglas, alertas cuando algo cambia... Escribir todo eso a mano sería reinventar la rueda.

Aquí entra Great Expectations (GE). Es el framework open-source más usado para validación de datos en Python. Lo usan empresas como GitHub, Shopify, Heineken, y cientos más. La idea central es elegante: en vez de escribir código imperativo ("if len(df) == 0: raise..."), DECLARAS tus expectativas sobre los datos de forma legible: "espero que esta columna no tenga nulos", "espero que los valores estén entre 0 y 1000", "espero que haya al menos 100 filas".

Analogía: es la diferencia entre escribir tests unitarios a mano (funciones con asserts) y usar un framework de testing como pytest (fixtures, parametrize, reportes, plugins). GE es el "pytest de los datos".

### Paso 1: Instalar Great Expectations

La instalación es un simple pip install. Asegúrate de estar en tu entorno virtual:

1# 🟦 Windows (PowerShell) — con tu venv activado:
2.venv\Scripts\activate
3pip install great-expectations
4
5# 🍎 Mac (Terminal/zsh) — con tu venv activado:
6source .venv/bin/activate
7pip install great-expectations
8
9# Verificar la instalación:
10python -c "import great_expectations as gx; print(f'GX version: {gx.__version__}')"

La instalación incluye muchas dependencias — puede tardar 1-2 minutos

Great Expectations es un paquete GRANDE (instala muchas dependencias). En un proyecto real, ponlo en tu requirements.txt o pyproject.toml. Si ves errores de compatibilidad, asegúrate de tener Python 3.9 o superior. La versión actual (1.x) cambió significativamente respecto a la 0.x, así que cuidado con tutoriales antiguos.

### Los conceptos clave de Great Expectations

GE tiene su propio vocabulario. Antes de escribir código, necesitas entender 4 conceptos fundamentales:

  1. 01.Expectation: una declaración sobre cómo DEBERÍAN ser los datos. Ej: "espero que la columna email no tenga nulos". Es el átomo de la validación.
  2. 02.Expectation Suite: un conjunto de Expectations agrupadas para un dataset concreto. Ej: "la suite de validación para la tabla pedidos" con 15 expectations.
  3. 03.Data Source: la conexión a los datos que quieres validar — un CSV, un DataFrame de Pandas, una tabla de PostgreSQL, un bucket de S3...
  4. 04.Validation Result: el resultado de ejecutar una Suite contra un Data Source. Incluye qué pasó, qué falló y estadísticas detalladas.
GE separa los datos (source), las reglas (suite) y la ejecución (validation)

### Tu primera validación con Great Expectations

Vamos a hacer algo práctico: validar un DataFrame de pedidos usando GE. El flujo es: crear un contexto, definir las expectations, ejecutar la validación y ver los resultados.

1import great_expectations as gx
2import pandas as pd
3
4# 1. Crear un contexto efímero (in-memory, sin archivos de configuración)
5context = gx.get_context()
6
7# 2. Crear nuestros datos de ejemplo
8pedidos = pd.DataFrame({
9 'pedido_id': [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010],
10 'cliente': ['Ana', 'Luis', None, 'María', 'Pedro', 'Laura', 'Carlos', 'Eva', None, 'Javi'],
11 'importe': [150.0, 25.0, 300.0, -10.0, 50.0, 75.0, 120.0, 0.0, 200.0, 45.0],
12 'email': ['ana@mail.com', 'luis@mail.com', 'maria@mail.com', None, 'pedro@mail.com',
13 'laura@', 'carlos@mail.com', 'eva@mail.com', 'iris@mail.com', None],
14})
15
16# 3. Conectar datos como Data Source
17data_source = context.data_sources.add_pandas("mi_source")
18data_asset = data_source.add_dataframe_asset(name="pedidos")
19batch_definition = data_asset.add_batch_definition_whole_dataframe("batch_pedidos")
20
21# 4. Crear una Expectation Suite
22suite = gx.ExpectationSuite(name="suite_pedidos")
23
24# 5. Añadir Expectations (reglas de validación)
25suite.add_expectation(
26 gx.expectations.ExpectColumnValuesToNotBeNull(column="pedido_id")
27)
28suite.add_expectation(
29 gx.expectations.ExpectColumnValuesToNotBeNull(column="importe")
30)
31suite.add_expectation(
32 gx.expectations.ExpectColumnValuesToBeBetween(
33 column="importe", min_value=0.01, max_value=50000
34 )
35)
36suite.add_expectation(
37 gx.expectations.ExpectColumnValuesToBeUnique(column="pedido_id")
38)
39
40# Registrar la suite en el contexto
41suite = context.suites.add(suite)
42
43# 6. Crear y ejecutar la validación
44validation_definition = context.validation_definitions.add(
45 gx.ValidationDefinition(
46 name="validar_pedidos",
47 data=batch_definition,
48 suite=suite,
49 )
50)
51
52# Ejecutar con el DataFrame real
53results = validation_definition.run(batch_parameters={"dataframe": pedidos})
54
55# 7. Ver resultados
56print(f"¿Pasó todo? {results.success}")
57print(f"Resultados por expectation:")
58for result in results.results:
59 estado = "✅" if result.success else "🔴"
60 print(f" {estado} {result.expectation_config.type}: {result.result}")

Flujo completo de GE: contexto → datos → suite → validación → resultados

### Las Expectations más útiles

GE tiene más de 300 Expectations predefinidas. No necesitas conocerlas todas — con unas 15-20 cubres el 90% de los casos. Estas son las que usarás constantemente:

1# === COMPLETITUD ===
2# Columna sin nulos
3ExpectColumnValuesToNotBeNull(column="pedido_id")
4# Columna con máximo X% de nulos
5ExpectColumnValuesToNotBeNull(column="email", mostly=0.95) # 95% no-null
6
7# === UNICIDAD ===
8# Valores únicos
9ExpectColumnValuesToBeUnique(column="pedido_id")
10# Combinación de columnas única
11ExpectCompoundColumnsToBeUnique(column_list=["fecha", "tienda", "producto"])
12
13# === VALIDEZ ===
14# Valores en un rango
15ExpectColumnValuesToBeBetween(column="edad", min_value=0, max_value=120)
16# Valores de un conjunto
17ExpectColumnValuesToBeInSet(column="estado", value_set=["activo", "inactivo", "baja"])
18# Formato regex
19ExpectColumnValuesToMatchRegex(column="email", regex=r".+@.+\..+")
20# Tipo de dato
21ExpectColumnValuesToBeOfType(column="importe", type_="float")
22
23# === VOLUMEN ===
24# Número mínimo de filas
25ExpectTableRowCountToBeBetween(min_value=100, max_value=100000)
26# Número de columnas
27ExpectTableColumnCountToEqual(value=8)
28
29# === DISTRIBUCIÓN ===
30# Media dentro de un rango (detectar anomalías)
31ExpectColumnMeanToBeBetween(column="importe", min_value=20, max_value=500)
32# Mediana
33ExpectColumnMedianToBeBetween(column="edad", min_value=25, max_value=55)

Las expectations más comunes — con estas 15 cubres la mayoría de escenarios

Consejo de senior: el parámetro "mostly" es tu mejor amigo. En datos reales, NUNCA hay 0% de nulos ni 0 duplicados. Siempre hay algo de ruido. mostly=0.98 significa "espero que al menos el 98% de los registros cumplan esta regla". Es la diferencia entre un check rígido que falla constantemente y uno realista que alerta cuando hay un problema REAL.

### Generar reportes HTML

Una de las killer features de GE es la generación automática de reportes HTML interactivos. Son documentos que puedes enviar al equipo de producto, al data analyst o al PM sin que necesiten saber Python. Muestran qué checks pasaron, cuáles fallaron, estadísticas de cada columna y el detalle de cada expectation.

1import great_expectations as gx
2
3# Después de ejecutar la validación, generar reporte HTML
4# (usando el context y results del ejemplo anterior)
5
6# Opción 1: Data Docs (la forma integrada de GE)
7# GE genera un sitio web estático completo con:
8# - Historial de validaciones
9# - Detalle de cada suite
10# - Estadísticas de datos
11
12# Configurar Data Docs
13context.add_or_update_data_docs_site(
14 site_config={
15 "class_name": "SiteBuilder",
16 "store_backend": {
17 "class_name": "TupleFilesystemStoreBackend",
18 "base_directory": "data_docs/",
19 },
20 "site_index_builder": {"class_name": "DefaultSiteIndexBuilder"},
21 },
22 site_name="mi_sitio_docs",
23)
24
25# Construir y abrir los docs
26context.build_data_docs()
27# Esto genera archivos HTML en data_docs/ que puedes abrir en el navegador
28
29# Opción 2: Resultado programático (para integrar en alertas)
30print(f"Suite: {results.suite_name}")
31print(f"Éxito global: {results.success}")
32print(f"Total expectations: {len(results.results)}")
33print(f"Pasaron: {sum(1 for r in results.results if r.success)}")
34print(f"Fallaron: {sum(1 for r in results.results if not r.success)}")

Data Docs genera un sitio HTML completo con historial de validaciones

### Integrar GE en tu pipeline diario

El patrón más común es ejecutar GE como un paso del pipeline: DESPUÉS de la ingesta pero ANTES de cargar datos en producción. Si la validación falla, el pipeline se detiene y alerta al equipo. Si pasa, los datos se cargan con confianza.

1import great_expectations as gx
2import pandas as pd
3import sys
4
5def pipeline_con_validacion():
6 """Pipeline ETL con validación integrada."""
7
8 # Paso 1: Ingesta
9 print("📥 Ingesta de datos...")
10 df = pd.read_csv("data/pedidos_hoy.csv")
11 print(f" Ingestados {len(df)} registros")
12
13 # Paso 2: Validación con GE
14 print("🔍 Validando datos...")
15 context = gx.get_context()
16
17 # Configurar source y suite (normalmente se hace una vez)
18 data_source = context.data_sources.add_pandas("pipeline_source")
19 data_asset = data_source.add_dataframe_asset(name="pedidos_raw")
20 batch_def = data_asset.add_batch_definition_whole_dataframe("batch")
21
22 suite = gx.ExpectationSuite(name="pedidos_ingesta")
23 suite.add_expectation(gx.expectations.ExpectTableRowCountToBeBetween(min_value=50))
24 suite.add_expectation(gx.expectations.ExpectColumnValuesToNotBeNull(column="pedido_id"))
25 suite.add_expectation(gx.expectations.ExpectColumnValuesToBeUnique(column="pedido_id"))
26 suite.add_expectation(gx.expectations.ExpectColumnValuesToBeBetween(
27 column="importe", min_value=0.01, max_value=50000
28 ))
29 suite = context.suites.add(suite)
30
31 validation_def = context.validation_definitions.add(
32 gx.ValidationDefinition(name="val_pedidos", data=batch_def, suite=suite)
33 )
34
35 results = validation_def.run(batch_parameters={"dataframe": df})
36
37 if not results.success:
38 print("🔴 VALIDACIÓN FALLIDA — pipeline abortado")
39 for r in results.results:
40 if not r.success:
41 print(f" ❌ {r.expectation_config.type}")
42 # Aquí enviarías alerta (Slack, email, PagerDuty)
43 sys.exit(1)
44
45 print("✅ Validación OK")
46
47 # Paso 3: Transformación (solo si validación pasó)
48 print("⚙️ Transformando datos...")
49 df['importe_con_iva'] = df['importe'] * 1.21
50
51 # Paso 4: Carga
52 print("📤 Cargando en warehouse...")
53 df.to_parquet("output/pedidos_gold.parquet")
54 print(f" ✅ {len(df)} registros cargados correctamente")
55
56# Ejecutar
57pipeline_con_validacion()

Patrón producción: ingesta → validación GE → transformación → carga. Si falla la validación, NADA se carga.

Lo que le diría a mi yo de hace 5 años: no intentes validar TODO desde el día 1. Empieza con 5 expectations básicas (volumen, nulos en campos clave, duplicados, rango de valores, tipo de datos). Después añade más a medida que descubras problemas. Las mejores suites de validación se construyen con el tiempo, alimentadas por cada incidente real.

Great Expectations transforma la validación de datos de algo que "deberías hacer" a algo que es parte integral de tu pipeline. En la próxima lección vamos un paso más allá: contratos de datos — acuerdos FORMALES entre quien produce datos y quien los consume.

## ejercicios

[01]

Crear una Expectation Suite para ventas Black Friday

Es el día después del Black Friday. El CEO quiere el informe de ventas en 2 horas. ANTES de generar el informe, necesitas validar que los datos son correctos (el año pasado hubo duplicados y nadie se enteró). Crea una suite GE completa para el dataset de ventas.

Cargando editor...
[02]

Usar el parámetro mostly para validaciones realistas

Tu suite de validación falla TODOS los días porque tienes expectations demasiado estrictas. El dataset siempre tiene un 1-2% de ruido inevitable. Ajusta las expectations con el parámetro mostly para que solo alerten cuando hay un problema REAL (> 5% de anomalías).

Cargando editor...
[03]

Pipeline ETL con validación GE en entrada y salida

Construye un mini-pipeline que: 1) Lee datos raw, 2) Valida la entrada con GE, 3) Transforma, 4) Valida la salida con GE. Si cualquier validación falla, el pipeline debe abortar con un mensaje claro.

Cargando editor...

Regístrate para guardar tu progreso.

## comentarios

Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.

Inicia sesión para comentar y responder.

cargando comentarios...