Este repositório é pensado pra receber scripts de archival de mais datasets DATASUS conforme pesquisadores interessados em subdatasets específicos forem aparecendo. O decoder DBC já está pronto — adicionar um dataset novo é basicamente:
- Escrever um script TypeScript que itera no FTP, decoda, escreve Parquet.
- Documentar o schema.
- Adicionar ao workflow de refresh.
- Node.js 22+
- pnpm (
corepack enable) - Cerca de 1-2 GB de espaço em disco pra cache FTP local durante testes
git clone https://github.com/Precisa-Saude/datasus-parquet.git
cd datasus-parquet
pnpm installCada dataset ocupa um "slot" em três lugares:
scripts/archive-<dataset>.ts— converte DBC → Parquet. Sem transformação semântica. Template emscripts/archive-sia-pa.ts.state/<dataset>.json— state file com a última competência processada por UF. Inicializado vazio com{"schemaVersion": 1, "lastRun": "", "processed": {}}.scripts/detect-new.ts— adicione uma entrada no mapaDATASETScom o path FTP + regex de nomes + parser (uf, ano, mês).scripts/emit-provenance.ts— adicione uma entrada no mapaDATASET_CONFIGcom oftpBaseesourceFileFor.docs/schema/<dataset>.md— descrição das colunas, charset, referências, caveats. Para SIH-RD, SIM, SINASC, SINAN e CNES-ST a spec já existe emdocs/schema/; refine e complete com base no DBF real (especialmente osCampos específicos por agravodo SINAN).docs/datasets.md— mover a entrada de "Planejados" para "Ativos" quando o script for publicado..github/workflows/refresh.yml— se precisar de passos específicos (raro; o workflow genérico cobre o padrão "uma partição por UF×competência").
- Sem filtro semântico: preserve todas as colunas
XXXX_*do DBF. Transformações aceitáveis: CP850→UTF-8 (via decoder) e conversão de tipos DBF→Parquet. - Determinismo:
ORDER BY <coluna-tempo>, <coluna-chave>no COPY TO. Mesmo DBC + mesmo gitSha = mesmo Parquet byte-a-byte. - Idempotência: se a partição de saída já existe com tamanho > 0, pule. Deletar o arquivo manualmente força re-emissão.
- Formato consistente:
ano=YYYY/uf=XX/mes=MM/part.parquet. Exceção: datasets nacionais não particionados por UF (ex.: SINAN) podem usarano=YYYY/part.parquetouano=YYYY/agravo=XXX/part.parquet.
| Convenção | Exemplo |
|---|---|
| Script | scripts/archive-<dataset>.ts |
| State | state/<dataset>.json |
| Build output | build/<dataset>/ano=YYYY/… |
| Provenance output | build/<dataset>/provenance/ano=YYYY/… |
| Package script | archive-<dataset> em package.json |
Um PR que adiciona um dataset novo deve incluir:
-
scripts/archive-<dataset>.tscom testes exemplares - Entrada em
DATASETSdedetect-new.ts - Entrada em
DATASET_CONFIGdeemit-provenance.ts -
state/<dataset>.jsoninicial vazio -
docs/schema/<dataset>.mdcompleto (refinado da spec existente com base no DBF real — tipos, campos opcionais específicos de vintage, caveats de encoding) - Atualização de
docs/datasets.md(mover de "Planejados" pra "Ativos") - Teste manual:
pnpm archive-<dataset> -- --ufs AC --years 2023emite um Parquet válido que o DuckDB consegue abrir. -
pnpm typechecklimpo
Teste o archival local com uma UF pequena (AC, AP, RR) e um único ano recente. Depois confira:
duckdb -c "SELECT COUNT(*) FROM read_parquet('build/<dataset>/ano=*/uf=*/mes=*/part.parquet', union_by_name=true);"
duckdb -c "DESCRIBE SELECT * FROM read_parquet('build/<dataset>/ano=2023/uf=AC/mes=01/part.parquet')` emite Parquet válido.Compare linha-a-linha com uma query TabNet oficial (quando disponível) pra sanity-check de totais.
Abra uma issue descrevendo:
- Qual dataset você gostaria de ver publicado
- Seu caso de uso acadêmico
- Se há alguma referência ao schema oficial que podemos citar
Com interesse confirmado, podemos escrever os scripts internamente. Prioridade é proporcional à comunidade que usaria.
Maintainers (hoje: time Precisa Saúde) revisam PRs. Critérios de aceitação:
- Não adiciona novas dependências pesadas sem justificativa
- Segue as convenções acima
- Schema docado referencia fonte oficial do DATASUS
- Nenhum tipo de filtro/transformação semântica no archival
Dúvidas? Abra uma issue.