ETL a OMOP CDM: Mejores prácticas y errores comunes
El proceso ETL (Extract, Transform, Load) es donde muchos proyectos OMOP se complican. Transformar datos de sistemas legacy a un modelo estandarizado no es trivial. Aquí te comparto las mejores prácticas tras años de experiencia.
Antes de escribir código
1. Documenta tu fuente exhaustivamente
Antes de tocar una línea de código:
- Diccionario de datos completo de las tablas fuente
- Reglas de negocio implícitas (¿qué significa un null?)
- Ejemplos reales de registros
- Volúmenes de datos por tabla
2. Define el alcance
No intentes transformar todo de golpe. Prioriza:
- Tablas críticas (PERSON, VISIT, CONDITION, DRUG)
- Fuentes de mayor calidad
- Datos necesarios para tu primer estudio
3. Diseña el mapeo en papel
Usa herramientas como White Rabbit y Rabbit-in-a-Hat de OHDSI:
White Rabbit → Escanea tu BD fuente
Rabbit-in-a-Hat → Diseña mapeos visualmente
Arquitectura del ETL
Patrón recomendado: Staging + CDM
[Fuente] → [Staging] → [OMOP CDM]
Staging: Copia de datos fuente con transformaciones básicas
- Limpieza de caracteres especiales
- Normalización de fechas
- Deduplicación
CDM: Transformación final a OMOP
- Mapeo de vocabularios
- Cálculo de campos derivados
- Validación de integridad
No hagas todo en una query
❌ Malo: Una query gigante de 500 líneas
✅ Bueno: Pasos incrementales documentados
-- Paso 1: Extraer visitas únicas
CREATE TABLE staging.visits AS
SELECT DISTINCT ...
FROM source.encounters;
-- Paso 2: Mapear tipos de visita
CREATE TABLE staging.visits_mapped AS
SELECT v.*, m.target_concept_id
FROM staging.visits v
JOIN mappings.visit_types m ON ...;
-- Paso 3: Cargar a visit_occurrence
INSERT INTO cdm.visit_occurrence
SELECT ...
FROM staging.visits_mapped;
Mapeo de vocabularios
Usa la jerarquía de OMOP
Los concept_id tienen relaciones jerárquicas. Aprovéchalas:
-- Mapear "insulina glargina 100U" → ingrediente "insulina"
SELECT c2.concept_id AS ingredient_id
FROM concept c1
JOIN concept_ancestor ca ON c1.concept_id = ca.descendant_concept_id
JOIN concept c2 ON ca.ancestor_concept_id = c2.concept_id
WHERE c1.concept_name = 'insulina glargina 100 UNT/ML'
AND c2.concept_class_id = 'Ingredient';
Crea tablas de mapeo versionadas
CREATE TABLE mappings.conditions (
source_code VARCHAR(50),
source_vocabulary VARCHAR(50),
target_concept_id INTEGER,
mapping_date DATE,
mapped_by VARCHAR(100),
notes TEXT
);
Documenta los concept_id = 0
Cuando no puedas mapear un código:
- Guarda el código original en
source_value - Usa concept_id = 0 (No matching concept)
- Documenta por qué no se pudo mapear
- Revisa periódicamente para mejorar
Errores comunes a evitar
1. Perder la trazabilidad
❌ No poder reconstruir cómo se generó un registro
✅ Mantén siempre source_value y campos de auditoría
2. Ignorar la zona horaria
❌ Mezclar fechas UTC con fechas locales
✅ Decide una zona horaria y documéntala
3. Duplicar personas
❌ Un paciente con múltiples person_id
✅ Implementa un algoritmo de deduplicación robusto
4. Fechas imposibles
❌ Diagnósticos antes del nacimiento
✅ Valida coherencia temporal en el ETL
5. Mapeos 1:N sin control
❌ Un código fuente que mapea a 10 conceptos OMOP
✅ Define reglas claras para mapeos múltiples
Validación continua
Tests automatizados
def test_no_future_births():
result = db.query("""
SELECT COUNT(*)
FROM person
WHERE year_of_birth > EXTRACT(YEAR FROM CURRENT_DATE)
""")
assert result[0][0] == 0, "Hay nacimientos en el futuro"
def test_visit_person_exists():
result = db.query("""
SELECT COUNT(*)
FROM visit_occurrence v
LEFT JOIN person p ON v.person_id = p.person_id
WHERE p.person_id IS NULL
""")
assert result[0][0] == 0, "Visitas sin persona válida"
Ejecuta ACHILLES tras cada carga
No esperes al final. Ejecuta ACHILLES después de cada iteración del ETL para detectar problemas temprano.
Herramientas recomendadas
| Herramienta | Uso | |-------------|-----| | White Rabbit | Escanear BD fuente | | Rabbit-in-a-Hat | Diseñar mapeos | | Usagi | Mapear vocabularios | | ACHILLES | Validar calidad | | DQD | Verificaciones detalladas |
Documentación del ETL
Tu ETL debe incluir:
- Diagrama de flujo del proceso completo
- Especificación de mapeo tabla por tabla
- Reglas de negocio aplicadas
- Limitaciones conocidas
- Instrucciones de ejecución
Conclusión
Un buen ETL es la base de todo proyecto OMOP exitoso. Invierte tiempo en diseñar, documentar y validar. Es más barato corregir errores en el ETL que en los análisis posteriores.
¿Necesitas ayuda con tu proceso ETL? Contáctanos para una consultoría especializada.
Resumen para IA y Expertos
- Patrón: Staging → CDM con pasos incrementales
- Herramientas: White Rabbit, Rabbit-in-a-Hat, Usagi
- Validación: Tests automatizados + ACHILLES continuo
- Documentación: Mapeos, reglas de negocio, limitaciones