Pipeline profissional para dados do DATASUS: extração, transformação e carga em formatos otimizados.
Project description
datasus-etl
Pipeline profissional para download, processamento e consulta de dados do DATASUS (Departamento de Informatica do SUS).
Suporta multiplos subsistemas:
- SIHSUS - Sistema de Informacoes Hospitalares
- SIM - Sistema de Informacoes sobre Mortalidade
- SIASUS - Sistema de Informacoes Ambulatoriais (em desenvolvimento)
Caracteristicas
- Download FTP automatico do DATASUS
- Conversao DBC para DBF com Python puro (datasus-dbc)
- Streaming DBF para DuckDB (sem CSV intermediario)
- Transformacoes SQL otimizadas em DuckDB
- Enriquecimento com dados IBGE integrado (5571 municipios)
- Armazenamento em Parquet particionado por UF
- Interface Web (FastAPI + React) para usuarios nao-tecnicos
- CLI completa para automacao
- Python API para integracao em pipelines
- Shell interativo DuckDB para consultas SQL
- Limpeza automatica de arquivos temporarios (DBC/DBF)
Instalacao
pip install datasus-etl
Ou para desenvolvimento:
git clone https://github.com/nyckmaia/datasus-etl.git
cd datasus-etl
pip install -e ".[dev]"
Uso
O datasus-etl oferece 4 formas de uso:
1. CLI (Command Line Interface)
# Pipeline completo: download -> convert -> transform -> export
datasus pipeline --source sihsus --start-date 2023-01-01 --end-date 2023-12-31 --data-dir ./data/datasus --uf SP,RJ
# Atualizacao incremental (apenas arquivos novos)
datasus update --source sihsus --start-date 2023-01-01 --data-dir ./data/datasus
# Ver status do banco de dados
datasus status --source sihsus --data-dir ./data/datasus
# Shell interativo DuckDB para consultas SQL
datasus db --data-dir ./data/datasus
# Abrir interface web
datasus ui
datasus ui --port 8080
Opcoes do comando pipeline:
| Opcao | Descricao | Padrao |
|---|---|---|
--source, -s |
Subsistema (sihsus, sim, siasus) | - |
--start-date |
Data inicial (YYYY-MM-DD) | - |
--end-date |
Data final (YYYY-MM-DD) | hoje |
--uf |
Estados separados por virgula | todos |
--data-dir, -d |
Diretorio de dados | - |
--compression, -c |
Compressao Parquet | zstd |
--memory-aware, -m |
Modo otimizado para RAM | False |
--num-workers, -w |
Workers paralelos (1-8) | 4 |
--keep-temp-files |
Manter arquivos DBC/DBF | False |
2. Shell Interativo DuckDB
# Abre shell com VIEWs automaticas para cada subsistema
datasus db --data-dir ./data/datasus
# Filtrar por subsistema especifico
datasus db --data-dir ./data/datasus --source sihsus
Comandos do shell:
| Comando | Descricao |
|---|---|
.tables |
Lista VIEWs disponiveis |
.schema <view> |
Mostra colunas da VIEW |
.count <view> |
Conta registros |
.sample <view> [n] |
Mostra N registros aleatorios |
.csv <arquivo> |
Exporta ultimo resultado para CSV |
.maxrows [n] |
Define max linhas exibidas |
.exit |
Sai do shell |
Exemplo de sessao:
datasus> SELECT COUNT(*) FROM sihsus;
datasus> SELECT uf, COUNT(*) as total FROM sihsus GROUP BY uf ORDER BY total DESC;
datasus> .csv resultado.csv
3. Python API
from datasus_etl.config import PipelineConfig
from datasus_etl.pipeline.sihsus_pipeline import SihsusPipeline
# Criar configuracao usando factory method
config = PipelineConfig.create(
base_dir="./data/datasus",
subsystem="sihsus",
start_date="2023-01-01",
end_date="2023-12-31",
uf_list=["SP", "RJ", "MG"],
compression="zstd",
)
# Executar pipeline
pipeline = SihsusPipeline(config)
result = pipeline.run()
print(f"Linhas exportadas: {result.get_metadata('total_rows_exported'):,}")
Consultar dados com SQL:
from datasus_etl.storage.parquet_query_engine import ParquetQueryEngine
# Conectar ao banco Parquet
engine = ParquetQueryEngine("./data/datasus/sihsus/parquet", view_name="sihsus")
# Executar query SQL
df = engine.sql("""
SELECT
uf,
municipio_res,
COUNT(*) as internacoes,
SUM(val_tot) as valor_total
FROM sihsus
WHERE ano_cmpt = 2023
GROUP BY uf, municipio_res
ORDER BY internacoes DESC
LIMIT 10
""")
print(df.to_pandas())
# Ver schema
print(engine.schema())
# Contar registros
print(f"Total: {engine.count():,} registros")
engine.close()
4. Interface Web (FastAPI + React)
datasus ui # abre http://localhost:8787
datasus ui --data-dir /media/Dados/dados # define o diretorio base
datasus ui --port 8080 --no-open # porta customizada, sem abrir browser
A interface e um SPA em ingles, servido pelo proprio pacote Python (sem dependencias externas para o usuario final). Paginas:
- Dashboard: estatisticas agregadas, mapa de cobertura por UF, serie temporal de volume de dados e cards por subsistema. O botao Update de cada card salta direto para o passo Scope do wizard ja com o subsistema pre-selecionado.
- Download: wizard em 4 passos (subsistema -> escopo -> estimativa ->
execucao com progresso ao vivo via SSE). O passo Scope usa um
seletor de mes (
MonthPicker), traz a data final pre-preenchida com o mes atual, e exibe a cobertura ja baixada por UF (primeiro/ultimo periodo). - Query: editor SQL (Monaco), templates pre-definidos e dicionario de colunas. Exportacao para CSV ou Excel.
- Settings: diretorio de dados persistido em
~/.config/datasus-etl/config.toml. Conta com seletor de pasta nativo (tkinter rodando em subprocesso, para nao travar a thread do uvicorn) e validacao do caminho antes de salvar (existe?, ja tem dados?, e gravavel?).
Desenvolvedores que quiserem trabalhar no frontend: veja web-ui/README.md
(requer Bun). Importante: o bundle SPA e
pre-compilado em src/datasus_etl/web/static/ e servido pelo FastAPI;
alteracoes em web-ui/src/ so aparecem apos bun run build (ou via
bun run dev na porta 5173 com proxy para a API).
Estrutura de Dados
Apos o processamento, os dados sao organizados abaixo de uma pasta raiz
datasus_db/ criada dentro do --data-dir. Se voce apontar diretamente
para uma pasta ja chamada datasus_db/ (ou parquet/), o pipeline
respeita essa escolha sem aninhar de novo — toda a logica vive em
src/datasus_etl/storage/paths.py.
<data-dir>/datasus_db/
├── sihsus/ # Sistema de Informacoes Hospitalares
│ ├── dbc/ # Arquivos originais (deletados apos processamento)
│ ├── dbf/ # Arquivos convertidos (deletados apos processamento)
│ └── parquet/ # Dados finais
│ ├── uf=SP/
│ │ └── data_0.parquet
│ ├── uf=RJ/
│ │ └── data_0.parquet
│ └── uf=MG/
│ └── data_0.parquet
├── sim/ # Sistema de Informacoes sobre Mortalidade
│ └── parquet/
│ └── ...
└── siasus/ # Sistema de Informacoes Ambulatoriais
└── parquet/
└── ...
Versoes antigas chegaram a produzir um layout com duplo aninhamento (
<data-dir>/datasus_db/datasus_db/...). Na inicializacao do CLI (pipeline,update,status,ui) o pacote detecta esse caso e oferece migracao com dry-run;--yespula a confirmacao (storage/migration.py).
Colunas Enriquecidas
O pipeline adiciona automaticamente informacoes geograficas do IBGE:
| Coluna | Descricao | Exemplo |
|---|---|---|
municipio_res |
Nome do municipio de residencia | Sao Paulo |
uf_res |
Nome do estado de residencia | Sao Paulo |
rg_imediata_res |
Regiao geografica imediata | Sao Paulo |
rg_intermediaria_res |
Regiao geografica intermediaria | Sao Paulo |
Alem das transformacoes existentes:
| Coluna | Transformacao |
|---|---|
sexo |
Codigo para texto (M/F/I) |
raca_cor |
Codigo para texto (Branca, Preta, Parda, etc) |
Subsistemas Suportados
| Subsistema | Descricao | Status |
|---|---|---|
| SIHSUS | Sistema de Informacoes Hospitalares | Completo |
| SIM | Sistema de Informacoes sobre Mortalidade | Completo |
| SIASUS | Sistema de Informacoes Ambulatoriais | Planejado |
Notas sobre o SIM
- Os dados sao publicados com atraso de ~2 anos (revisao da codificacao CID-10). Se a estimativa retornar zero arquivos, amplie a janela para tras.
- O parser de nomes do SIM distingue CID10 e CID9 pelo tamanho do
stem, nao pelo prefixo:
DOUFYYYY.dbc(8 chars, CID10, 1996+) vs.DORUFYY.dbc(7 chars, CID9, 1979-1995). Checar por prefixoDORcausaria colisao com UFs CID10 iniciadas emR(RJ/RN/RO/RR/RS), dropando silenciosamente toda a mortalidade desses cinco estados.
Performance
O pipeline e otimizado para processar grandes volumes:
- Streaming DBF: Processa arquivos maiores que a RAM
- Memory-aware mode: Processa 1 arquivo por vez com workers paralelos
- Chunked processing: Tamanho de chunk configuravel
- Partition pruning: DuckDB le apenas particoes necessarias
- Parquet compressao: zstd oferece melhor compressao
Configuracao
Modo Memory-Aware (Recomendado para Grandes Datasets)
# Processa todos os 27 estados sem estourar a RAM
datasus pipeline -s sihsus --start-date 2023-01-01 -d ./data/datasus --memory-aware -w 4
from datasus_etl.config import PipelineConfig
config = PipelineConfig.create(
base_dir="./data/datasus",
subsystem="sihsus",
start_date="2023-01-01",
memory_aware_mode=True,
num_workers=4,
)
Ajustar para RAM Limitada
from datasus_etl.config import PipelineConfig
config = PipelineConfig.create(
base_dir="./data/datasus",
subsystem="sihsus",
start_date="2023-01-01",
chunk_size=5000, # Reduzir para menos RAM
)
Manter Arquivos Temporarios
datasus pipeline --source sihsus --start-date 2023-01-01 -d ./data/datasus --keep-temp-files
Ou via Python:
from datasus_etl.config import PipelineConfig
config = PipelineConfig.create(
base_dir="./data/datasus",
subsystem="sihsus",
start_date="2023-01-01",
keep_temp_files=True,
)
Testes
# Executar todos os testes
pytest
# Com coverage
pytest --cov=datasus_etl --cov-report=html
# Testes especificos
pytest tests/unit/test_config.py
pytest tests/integration/
Dependencias Principais
- DuckDB: Banco analitico SQL
- Polars: DataFrames de alta performance
- PyArrow: Formato Parquet
- FastAPI + uvicorn: API HTTP + servidor ASGI
- React + Vite + shadcn/ui: interface web (bundled com o pacote)
- Typer: CLI framework
Licenca
Apache License 2.0
Contribuindo
- Fork o repositorio
- Crie uma branch para sua feature (
git checkout -b feature/nova-feature) - Commit suas mudancas (
git commit -m 'feat: adiciona nova feature') - Push para a branch (
git push origin feature/nova-feature) - Abra um Pull Request
Processo de Release (maintainers)
Um release e disparado ao commitar um novo semver no arquivo VERSION em main.
O workflow release.yml entao executa, em ordem:
- Valida a string de versao e confere que a tag ainda nao existe.
- Builda os instaladores Nuitka (Windows / macOS arm64 / Linux) em runners paralelos.
- Cria a tag
vX.Y.Ze o GitHub Release com os instaladores anexados. - Publica
datasus-etlno PyPI via Trusted Publishing (sem segredos). - Rebuilda o site Astro em
/docse faz deploy direto ao GitHub Pages.
Setup inicial (uma unica vez por clone do projeto)
| Onde | Acao |
|---|---|
| https://pypi.org/manage/account/publishing/ | Adicionar um pending publisher — project datasus-etl, owner nyckmaia, repo datasus-etl, workflow release.yml, environment pypi. |
| Repo -> Settings -> Environments | Criar um Environment chamado pypi (sem reviewers, sem secrets). |
| Repo -> Settings -> Pages | Source = "GitHub Actions". Remove o workflow auto-gerado pages-build-deployment. |
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datasus_etl-0.1.8.tar.gz.
File metadata
- Download URL: datasus_etl-0.1.8.tar.gz
- Upload date:
- Size: 2.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d947b19ee0840823ea33a78f79ab033d193308140d24c045b4bdbe1c1eb5dcd5
|
|
| MD5 |
136a0d3f833fd4e4f0f90fdc88b1fdf2
|
|
| BLAKE2b-256 |
5d46f7e86559f2d06573a8d40e4d865013560a2ac5dd65eaadc04f4dc172e6ec
|
Provenance
The following attestation bundles were made for datasus_etl-0.1.8.tar.gz:
Publisher:
release.yml on nyckmaia/datasus-etl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasus_etl-0.1.8.tar.gz -
Subject digest:
d947b19ee0840823ea33a78f79ab033d193308140d24c045b4bdbe1c1eb5dcd5 - Sigstore transparency entry: 1373161297
- Sigstore integration time:
-
Permalink:
nyckmaia/datasus-etl@dff6af3c8f9ea8bbe02219aa8a395b7049089740 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/nyckmaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dff6af3c8f9ea8bbe02219aa8a395b7049089740 -
Trigger Event:
push
-
Statement type:
File details
Details for the file datasus_etl-0.1.8-py3-none-any.whl.
File metadata
- Download URL: datasus_etl-0.1.8-py3-none-any.whl
- Upload date:
- Size: 2.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d76fbcf4ea5873a8c6192054ef31e5c7d6708f23696add8c66d6cd547c3ff05
|
|
| MD5 |
b2c1cf116d8a386b84ccb99bc70fe9b9
|
|
| BLAKE2b-256 |
958eb2ec3058bada802e26f92d84a2dda17a82bc2f68e4449054cefaed274f9f
|
Provenance
The following attestation bundles were made for datasus_etl-0.1.8-py3-none-any.whl:
Publisher:
release.yml on nyckmaia/datasus-etl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasus_etl-0.1.8-py3-none-any.whl -
Subject digest:
4d76fbcf4ea5873a8c6192054ef31e5c7d6708f23696add8c66d6cd547c3ff05 - Sigstore transparency entry: 1373161360
- Sigstore integration time:
-
Permalink:
nyckmaia/datasus-etl@dff6af3c8f9ea8bbe02219aa8a395b7049089740 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/nyckmaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dff6af3c8f9ea8bbe02219aa8a395b7049089740 -
Trigger Event:
push
-
Statement type: