Pular para conteúdo

quantilica-catalog

Modelo de dados canônico e adaptadores para normalizar observações de diferentes fontes num esquema unificado. Resolve o problema central do cruzamento de dados: cada fonte usa estrutura, nomes de colunas e granularidade geográfica diferentes.

O problema: SIDRA usa localidade, BCB-SGS não tem geografia, INMET usa código de estação. Para cruzar um índice BCB com dados climáticos do INMET, você precisa de um modelo comum. quantilica-catalog fornece esse modelo.

Instalação

uv add "quantilica-catalog @ git+https://github.com/Quantilica/quantilica-catalog.git"

O Modelo: Star Schema

O catálogo organiza os dados em um star schema com uma tabela fato e dimensões de suporte:

fact_observation  (o que? quando? onde? quanto?)
├── dim_indicator      — metadados do indicador (nome, categoria, frequência)
├── dim_geo_entity     — entidades geográficas (estados, municípios, estações)
├── dim_geo_relationship — hierarquias entre entidades geográficas
└── dim_geo_code       — códigos externos (IBGE, INMET, etc.)

Tabela Fato: fact_observation

Cada linha responde: qual foi o valor do indicador X no tempo T no lugar G?

from quantilica.catalog import OBSERVATION_CONTRACT
# Schema: indicator_id (Utf8), date (Date), geo_id (Utf8?),
#         value (Float64?), date_end (Date?)
Campo Tipo Descrição
indicator_id Utf8 "fonte:id" — ex.: "bcb-sgs:433", "sidra:1705:93"
date Date Data de início da observação
geo_id Utf8? null para séries nacionais sem desagregação geográfica
value Float64? Valor numérico
date_end Date? Data de fim (séries com intervalo, ex.: trimestres móveis)

Adaptadores

Os adaptadores convertem DataFrames no formato de cada fetcher para o formato canônico:

from quantilica.catalog.adapters.bcb_sgs import to_observations as sgs_obs
from quantilica.catalog.adapters.sidra import to_observations as sidra_obs
import polars as pl

# BCB-SGS → observações canônicas (sem geo_id — série nacional)
df_sgs = pl.read_parquet("series_433.parquet")  # colunas series_id/date/value
obs = sgs_obs(df_sgs)
# indicator_id="bcb-sgs:433", geo_id=null

Adaptadores disponíveis e formato do indicator_id gerado:

Módulo Fonte Formato do indicator_id
adapters.bcb_sgs BCB-SGS "bcb-sgs:{series_id}"
adapters.rtn Tesouro Nacional RTN "rtn:{planilha}:{coluna}"
adapters.inmet INMET BDMEP "inmet:{variável}"
adapters.tesouro_direto Tesouro Direto "td:{tipo_titulo}"
adapters.sidra IBGE SIDRA "sidra:{agregado_id}:{variavel_id}" (ou :{categoria_ids} se classificado)

SIDRA com categorias

Quando o agregado SIDRA tem classificações (ex.: desemprego por faixa etária), o indicator_id inclui os IDs das categorias separados por |: "sidra:1705:93:49223|49702".

Dimensão de Indicadores

from quantilica.catalog import IndicatorEntry, DataCategory, Frequency, entries_to_frame

entries = [
    IndicatorEntry(
        indicator_id="bcb-sgs:433",
        source_id="bcb",
        source_dataset_id="sgs",
        name="IPCA — Variação mensal",
        category=DataCategory.PRICES,
        unit="%",
        frequency=Frequency.MONTHLY,
    ),
]

dim_df = entries_to_frame(entries)

Categorias (DataCategory): monetary, fiscal, financial, climate, labor, trade, health, demographic, economic, prices.

Frequências (Frequency): hourly, daily, weekly, monthly, quarterly, semi_annual, rolling_quarterly, yearly, multi_year, irregular.

Dimensão Geográfica

Entidades — dim_geo_entity

from quantilica.catalog import GeoEntityEntry, GeoType, state_id, municipality_id

entries = [
    GeoEntityEntry(geo_id=state_id("SP"), geo_type=GeoType.TERRITORY, name="São Paulo"),
    GeoEntityEntry(geo_id=municipality_id("3550308"), geo_type=GeoType.TERRITORY, name="São Paulo"),
]

Construtores de geo_id:

Função Exemplo de saída
country_id() "BR"
region_id("1") "BR:R:1"
state_id("SP") "BR:SP"
mesoregion_id("3515") "BR:MR:3515"
microregion_id("35061") "BR:MCR:35061"
municipality_id("3550308") "BR:M:3550308"
district_id("355030805") "BR:D:355030805"
census_sector_id("350030805000001") "BR:CS:350030805000001"
station_id("INMET", "A701") "INMET:A701"

Hierarquias — dim_geo_relationship

from quantilica.catalog import GeoRelationshipEntry, RelType, GeoSystem

rel = GeoRelationshipEntry(
    from_geo_id=municipality_id("3550308"),
    to_geo_id=state_id("SP"),
    rel_type=RelType.ADMINISTRATIVE_PARENT,
    system=GeoSystem.IBGE_TRADITIONAL,
)

Tipos de relação (RelType): administrative_parent, contains, overlaps, borders.

Sistemas (GeoSystem): ibge_traditional, ibge_rgint, ibge_census, datasus_health, ana_hydrographic, inmet.

Códigos externos — dim_geo_code

from quantilica.catalog import GeoCodeEntry

code = GeoCodeEntry(geo_id=state_id("SP"), system="ibge", code="35")

Persistência em PostgreSQL

Para um data warehouse, o pacote fornece o DDL pronto (CREATE_ALL_GEO_TABLES em quantilica.catalog.sql.ddl), que cria as três tabelas de dimensão geográfica — dim_geo_entity, dim_geo_relationship e dim_geo_code — com índices otimizados para lookup por código e consultas de hierarquia.

Por que um modelo canônico?

Sem quantilica-catalog, cruzar IPCA (BCB-SGS) com temperatura por estado (INMET) exige renomear colunas de cada fonte, decidir um identificador de indicador ad hoc e alinhar a granularidade geográfica manualmente.

O catálogo faz isso uma vez, tornando os dados inter-operáveis por construção: um JOIN em indicator_id + geo_id + date une qualquer par de fontes.

Saiba Mais

Repositório

github.com/Quantilica/quantilica-catalog — MIT.