Ir para o conteúdo

Como consultar dados com o climasus4py

O contrato central do climasus4py é DuckDBPyRelation. Todas as funções do pipeline constroem uma consulta lazy — nenhuma linha de dado chega à RAM até que você chame materialize() ou sus_export().

Três portas de entrada

Baixa, cacheia e abre dados do DATASUS como DuckDB lazy:

import climasus4py as cs

rel = cs.sus_data_import("SIM-DO", "SP", 2023)

Também aceita múltiplos anos:

rel = cs.sus_data_import("SIM-DO", "SP", [2020, 2021, 2022, 2023])

Abre qualquer Parquet ou GeoParquet local como relação lazy:

rel = cs.sus_data_read("dados/cache/SIM-DO/SP_2023_all.parquet")

Aceita lista ou glob:

rel = cs.sus_data_read(["dados/SIM_SP_2022.parquet", "dados/SIM_SP_2023.parquet"])
rel = cs.sus_data_read("dados/SIM_SP_*.parquet")

Executa SQL DuckDB arbitrário como ponto de entrada:

rel = cs.sus_sql("""
    SELECT * FROM read_parquet('dados/externo.parquet')
    WHERE UF = 'SP'
""")

Encadeamento de etapas

Após a entrada, o pipeline segue a ordem canônica:

rel = cs.sus_data_import("SIM-DO", "SP", 2023)
rel = cs.sus_data_clean_encoding(rel)
rel = cs.sus_data_standardize(rel, system="SIM-DO")
rel = cs.sus_filter(rel, codes=["J00-J99"], age_min=15, age_max=64, uf="SP")
rel = cs.sus_data_create_variables(rel, age_group="epidemiological_default", epi_week=True)
rel = cs.sus_data_aggregate(rel, time="month", geo="municipality")

Todo o bloco acima é zero RAM — apenas SQL sendo construído.

Parâmetros avançados de sus_filter

match_type — precisão no código CID-10

Por padrão, sus_filter usa prefixo de 3 caracteres ("starts_with"):

# "starts_with" (padrão): J18 casa com J189, J180, J181...
rel = cs.sus_filter(rel, codes=["J18"])

# "exact": apenas J189 — sem prefixo
rel = cs.sus_filter(rel, codes=["J189"], match_type="exact")

education — filtro por escolaridade

Auto-detecta a coluna entre education, education_2010, ESC, ESC2010:

rel = cs.sus_filter(rel, education=["1", "2"])   # fundamental incompleto/completo

city — filtro por nome de município

Resolve o nome para código IBGE via climasus-data/spatial/municipalities.parquet:

rel = cs.sus_filter(rel, city="São Paulo")
rel = cs.sus_filter(rel, city=["São Paulo", "Rio de Janeiro"])

Quando um nome casa múltiplos municípios (ex: "São José"), todos os códigos são usados e um UserWarning é emitido.

drop_ignored — remover valores ignorados

Remove linhas onde colunas demográficas detectáveis (sexo, raça, escolaridade, idade) contêm valores codificados como ignorado/desconhecido (9, 99, Ignorado, etc.):

rel = cs.sus_filter(rel, drop_ignored=True)

# Combinável com outros filtros:
rel = cs.sus_filter(rel, sex="F", drop_ignored=True, education=["3", "4"])

Transformações SQL no meio do pipeline

Use .pipe(cs.sus_sql, ...) para injetar SQL arbitrário em qualquer ponto. O marcador {data} é substituído pelo nome da relação atual:

rel = cs.sus_data_aggregate(rel, time="month", geo="municipality")
rel = rel.pipe(
    cs.sus_sql,
    "SELECT *, count / population AS rate FROM {data}",
)

Para transformações DuckDB nativas (sem precisar de sus_sql):

rel = rel.filter("count > 5")
rel = rel.select("municipality_code, month, count")

Enriquecimentos

Depois do aggregate, aplique enriquecimentos opcionais. Todos retornam DuckDBPyRelation — sem RAM até o fim:

rel = cs.sus_spatial_join(rel)                                   # adiciona geometry_wkt
rel = cs.sus_census(rel, year=2022, variables=["population_2021"])  # indicadores IBGE
rel = cs.sus_climate(rel, variables=["temp_mean"], years=[2023])    # INMET
rel = cs.sus_fill_gaps(rel, method="linear")                # interpolação lazy

Veja o guia completo de enriquecimentos.

Saídas

Para disco (sus_export)

Escreve sem coletar em memória. Preferido para bases grandes:

cs.sus_export(rel, "resultado/sim_sp_2023.parquet")   # Parquet (padrão)
cs.sus_export(rel, "resultado/sim_sp_2023.csv")       # CSV

Para RAM (materialize)

Carrega o resultado em um formato in-memory. Use quando precisar de análise interativa ou integração com outras bibliotecas:

df     = cs.materialize(rel)                    # auto: pandas ou GeoDataFrame
df     = cs.materialize(rel, how="pandas")
gdf    = cs.materialize(rel, how="geopandas")   # requer geometry_wkt
table  = cs.materialize(rel, how="pyarrow")
polars = cs.materialize(rel, how="polars")

Veja a referência completa do materialize.

Exemplo completo

import climasus4py as cs

# 1. Entrada
rel = cs.sus_data_import("SIM-DO", "SP", 2023)

# 2. Pipeline core (lazy)
rel = cs.sus_data_clean_encoding(rel)
rel = cs.sus_data_standardize(rel, system="SIM-DO")
rel = cs.sus_filter(rel, groups="respiratory", age_min=0, age_max=14)
rel = cs.sus_data_create_variables(rel, age_group="epidemiological_default")
rel = cs.sus_data_aggregate(rel, time="month", geo="municipality")

# 3. Enriquecimento (lazy)
rel = cs.sus_climate(rel, variables=["temp_mean", "precipitation"], years=[2023])

# 4. Saída — escolha uma:
cs.sus_export(rel, "sim_resp_criancas_sp_2023.parquet")  # disco
df = cs.materialize(rel)                                  # RAM