Pipeline ETL que transforma exportações de prontuário bruto em um banco clínico modelado, catalogado, validado e rastreável — reproduzível num comando.
⚠️ Ambiente-laboratório. Cenário fictício (Clínica Aurora), dados sintéticos (Synthea). Nenhuma conformidade legal é aqui alegada; a camada de governança é projetada como se o dado fosse real, para demonstrar prática.
Dado clínico bruto chega em múltiplos arquivos, com tipos inconsistentes, sem modelo analítico e sem ninguém saber o que cada campo significa, de onde veio, nem se é confiável. Isto o fragmenta, o torna auditável apenas localmente, e impede que a organização saiba o que trata, com que qualidade e por quanto tempo.
# Clonar e entrar no diretório
git clone <url> && cd 01-health-data-engineering
# Gerar dados sintéticos (Synthea)
java -jar synthea.jar -s 12345 -p 52 MA
# Explorar dados brutos
python3 -c "
import pandas as pd
df = pd.read_csv('data/synthea/output/csv/patients.csv')
print(f'Carregados {len(df)} pacientes com {len(df.columns)} colunas')
print(df.head(3))
"
# Ver classificação de sensibilidade
cat docs/classificacao_preenchida.md- 6 tabelas modeladas (patients, encounters, conditions, medications, observations, procedures)
- 74 colunas 100% classificadas por sensibilidade: [ID] 21, [PESSOAL] 23, [SENSÍVEL] 23, [FINANCEIRO] 7
- 2 documentos de governança (ADR-01: escopo; classificação: 7.6 KB)
- 0 duplicatas em reexecução (idempotência projetada, não testada em produção)
- 1 decisão de arquitetura documentada: observations como fato de grão fino, não dimensão
Synthea (52 pacientes) ↓ [data/raw/] ← CSVs brutos ↓ [Exploração] · Tipos de dados · Faltantes · Amostras · Sensibilidade ↓ [Classificação] → docs/classificacao_preenchida.md · [ID], [PESSOAL], [SENSÍVEL], [FINANCEIRO] · Retenção por categoria ↓ [PostgreSQL] ← próxima etapa · Staging (bruto) · Core (modelado — star schema)
Por que 6 tabelas na v1 e não 16? As 6 cobrem o ciclo analítico completo: quem é (patients), o que aconteceu (encounters), com que diagnóstico (conditions), com que tratamento (medications), com que medidas (observations), e que procedimentos (procedures). As outras 10 (allergies, careplans, devices, imaging_studies, immunizations, organizations, payers, payer_transitions, providers, supplies) não respondem nenhuma pergunta de v1 — ADR-01 documenta isto.
Por que observations é fato e não dimensão? Cada linha é um evento medido com valor (ex: "pressão sistólica = 120 mmHg" em determinado paciente, encontro, data). Com 19.830 linhas (86% do volume total), obedece ao padrão de fato de grão fino. Dimensão seria "tipos de observação possíveis" — que será outra coisa. O design final (congelar vs explodir) é decidido na Etapa 3.
Por que classificação declarativa em YAML + validação automática? YAML é versionável (aparece em PR, revisável, auditável). O código que compara YAML com o banco impede que o catálogo vire ficção silenciosamente — quebrará testes se uma coluna foi adicionada mas não catalogada.
Linguagem & Ambiente
- Python 3.x
uv+pyproject.toml+uv.lock
Dado & Preparação
- Synthea (gerador sintético)
- pandas (exploração)
Qualidade & Validação
- pandera (contrato de qualidade — próxima etapa)
- pytest (testes — Etapa 6)
Banco & Acesso
- PostgreSQL (via Docker)
- SQLAlchemy (ORM — Etapa 2)
Governança
- YAML declarativo (catálogo, linhagem, regras de qualidade)
- Metadados persistidos (Etapa 5)
Infraestrutura
- Docker / docker-compose
- Git + GitHub
- GitHub Actions (CI — Etapa 6)
01-health-data-engineering/ ├── data/ │ ├── raw/ # CSVs brutos do Synthea (git-ignored) │ └── synthea/output/ # Saída direta do Synthea ├── docs/ │ ├── decisao-escopo.md # ADR-01: escopo de 6 tabelas │ ├── classificacao_preenchida.md # Classificação 74 colunas │ └── demo.gif # GIF de execução ├── src/ # Código Python (vazio em 1.4; inicia em Etapa 2) │ └── (etapa 2+) ├── pyproject.toml # Dependências (uv) ├── .gitignore # data/, .env, *.parquet ├── README.md # Este arquivo └── docker-compose.yml # PostgreSQL (futuro: Etapa 2)
Prova de verdade (Etapa 1.4)
- Exploração de dados: tipos, faltantes, distribuição
- Classificação de sensibilidade: distinção [ID] vs [PESSOAL] vs [SENSÍVEL] vs [FINANCEIRO]
- Documentação de decisões: ADR-01 com escopo justificado
- Conhecimento de LGPD: art. 5 (I e II), retenção diferenciada, ressalva honesta sobre dado sintético
Tangencia (próximas etapas)
- ETL / Engenharia de dados (Etapa 2+)
- Modelagem dimensional / Star schema (Etapa 3)
- Idempotência / Load (Etapa 4)
- Validação de dados (pandera, Etapa 2)
- CI/CD (GitHub Actions, Etapa 6)
- Dado: Synthea modela padrões de EUA (codificação e epidemiologia não são brasileiras). Teto de sinal no modelo preditivo (Projeto 3) será modesto por construção.
- Escopo: 10 tabelas do Synthea ficam para v2; observations será rearranjada na modelagem.
- Governança: Classificação e linhagem são declarativas (YAML + manutenção manual). Em escala (100+ tabelas), exigiria derivação automática do código SQL.
- Conformidade: Nenhuma. Dado sintético elimina risco legal real; a camada de governança é exercício de boas práticas, não cumprimento de lei.
- Etapa 2 (9–17h): Ingestão, validação (pandera), primeira carga PostgreSQL
- Etapa 3 (10–16h): Star schema, transformação clínica
- Etapa 4 (5–9h): Load idempotente, orquestração
- Etapa 5 (16–22h): Camada de governança, metadados persistidos
- Etapa 6 (10–16h): Testes, documentação, CI
MIT
Mantido por: Carla Rodrigues
Última atualização: 2026-07-25
Status: Etapa 1.4 — Exploração + Classificação completa
