ptbr-sampler 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ptbr_sampler-0.3.0/LICENSE +21 -0
- ptbr_sampler-0.3.0/PKG-INFO +346 -0
- ptbr_sampler-0.3.0/README.md +286 -0
- ptbr_sampler-0.3.0/THIRD_PARTY_NOTICES.md +59 -0
- ptbr_sampler-0.3.0/ptbr_sampler/__init__.py +120 -0
- ptbr_sampler-0.3.0/ptbr_sampler/__main__.py +6 -0
- ptbr_sampler-0.3.0/ptbr_sampler/br_location_class.py +444 -0
- ptbr_sampler-0.3.0/ptbr_sampler/br_name_class.py +1192 -0
- ptbr_sampler-0.3.0/ptbr_sampler/br_rg_class.py +161 -0
- ptbr_sampler-0.3.0/ptbr_sampler/cli.py +941 -0
- ptbr_sampler-0.3.0/ptbr_sampler/data/dataset_manifest.json +1378 -0
- ptbr_sampler-0.3.0/ptbr_sampler/data_origins.py +290 -0
- ptbr_sampler-0.3.0/ptbr_sampler/datasets.py +480 -0
- ptbr_sampler-0.3.0/ptbr_sampler/document_sampler.py +67 -0
- ptbr_sampler-0.3.0/ptbr_sampler/faker.py +691 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampler.py +960 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampling/__init__.py +22 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampling/alias.py +222 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampling/store.py +216 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampling/validation.py +190 -0
- ptbr_sampler-0.3.0/ptbr_sampler/sampling/vocabulary.py +291 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/__init__.py +1 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/address_for_offline.py +723 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/cei.py +76 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/cep_service.js +26 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/cep_wrapper.py +181 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/cnpj.py +121 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/cpf.py +86 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/phone.py +164 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/pis.py +77 -0
- ptbr_sampler-0.3.0/ptbr_sampler/utils/util.py +28 -0
- ptbr_sampler-0.3.0/pyproject.toml +238 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jandira Tech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ptbr-sampler
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Empirically grounded Brazilian demographic, location, and synthetic document sampler backed by IBGE Census 2022
|
|
5
|
+
Keywords: brazil,pt-br,ibge,census-2022,synthetic-data,faker,names,surnames,cep,cpf,cnpj,data-science
|
|
6
|
+
Author: Jandira Tech, Arthur Souza Rodrigues
|
|
7
|
+
Author-email: Arthur Souza Rodrigues <arthrod@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Natural Language :: Portuguese (Brazilian)
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Dist: tqdm>=4.67.1
|
|
25
|
+
Requires-Dist: typer>=0.15.0
|
|
26
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
27
|
+
Requires-Dist: loguru>=0.7.3
|
|
28
|
+
Requires-Dist: rich>=14.0.0
|
|
29
|
+
Requires-Dist: aiofiles>=24.1.0
|
|
30
|
+
Requires-Dist: numpy>=2.0
|
|
31
|
+
Requires-Dist: pyarrow>=17.0
|
|
32
|
+
Requires-Dist: uv>=0.13.7 ; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.8 ; extra == 'dev'
|
|
34
|
+
Requires-Dist: huggingface-hub>=0.26 ; extra == 'dev'
|
|
35
|
+
Requires-Dist: mkdocs>=1.6 ; extra == 'docs'
|
|
36
|
+
Requires-Dist: mkdocs-material>=9.5 ; extra == 'docs'
|
|
37
|
+
Requires-Dist: pymdown-extensions>=10.12 ; extra == 'docs'
|
|
38
|
+
Requires-Dist: faker>=30.0 ; extra == 'faker'
|
|
39
|
+
Requires-Dist: pytest>=8.3 ; extra == 'test'
|
|
40
|
+
Requires-Dist: pytest-asyncio>=0.24 ; extra == 'test'
|
|
41
|
+
Requires-Dist: pytest-cov>=6.0 ; extra == 'test'
|
|
42
|
+
Requires-Dist: pytest-mock>=3.14 ; extra == 'test'
|
|
43
|
+
Requires-Dist: pytest-timeout>=2.3 ; extra == 'test'
|
|
44
|
+
Requires-Dist: pytest-xdist>=3.6 ; extra == 'test'
|
|
45
|
+
Requires-Dist: coverage[toml]>=7.6 ; extra == 'test'
|
|
46
|
+
Requires-Dist: scipy>=1.14 ; extra == 'test'
|
|
47
|
+
Requires-Dist: faker>=30.0 ; extra == 'test'
|
|
48
|
+
Requires-Python: >=3.12
|
|
49
|
+
Project-URL: Homepage, https://github.com/jandira-tech/ptbr-sampler
|
|
50
|
+
Project-URL: Documentation, https://ptbr-sampler.readthedocs.io/
|
|
51
|
+
Project-URL: Repository, https://github.com/jandira-tech/ptbr-sampler
|
|
52
|
+
Project-URL: Dataset, https://huggingface.co/datasets/arthrod/ptbr-sampler-data
|
|
53
|
+
Project-URL: Issues, https://github.com/jandira-tech/ptbr-sampler/issues
|
|
54
|
+
Project-URL: Changelog, https://github.com/jandira-tech/ptbr-sampler/blob/main/CHANGELOG.md
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Provides-Extra: docs
|
|
57
|
+
Provides-Extra: faker
|
|
58
|
+
Provides-Extra: test
|
|
59
|
+
Description-Content-Type: text/markdown
|
|
60
|
+
|
|
61
|
+
# `ptbr-sampler` `0.3.0` — Gerador Estatístico de Dados Demográficos Brasileiros
|
|
62
|
+
|
|
63
|
+
[](https://pypi.org/project/ptbr-sampler/)
|
|
64
|
+
[](https://www.python.org/downloads/)
|
|
65
|
+
[](https://github.com/jandira-tech/ptbr-sampler/blob/main/LICENSE)
|
|
66
|
+
[](https://ptbr-sampler.readthedocs.io/)
|
|
67
|
+
[](https://huggingface.co/datasets/arthrod/ptbr-sampler-data)
|
|
68
|
+
|
|
69
|
+
Gere nomes completos, localizações municipais, CEPs, endereços, telefones e documentos sintéticos brasileiros (CPF, RG estadual, PIS, CNPJ e CEI) **proporcionais às distribuições populacionais empíricas do Brasil** e fundamentados em dados públicos auditáveis.
|
|
70
|
+
|
|
71
|
+
A partir da versão **`0.3.0`**, o `ptbr-sampler` adota o **Censo Demográfico 2022 do IBGE** (`census_year=2022`, `TimePeriod.ALL`, $N = 203.080.756$ residentes) como padrão primário, integra-se nativamente ao **Faker** (`pip install "ptbr-sampler[faker]"`), suporta injeção determinística e *thread-safe* de `random.Random` (`rng=`), e distribui suas `195` partições de execução via Hugging Face Hub ([`arthrod/ptbr-sampler-data`](https://huggingface.co/datasets/arthrod/ptbr-sampler-data)) com verificação `SHA-256` sob demanda — mantendo o pacote `.whl` publicado no PyPI em **`102,8 KiB` (`< 150 KiB`)**.
|
|
72
|
+
|
|
73
|
+
*Read in English: [README.en.md](https://github.com/jandira-tech/ptbr-sampler/blob/main/README.en.md) | Relatório Técnico Completo: [docs/technical-report.md](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/technical-report.md) | Documentação: [ptbr-sampler.readthedocs.io](https://ptbr-sampler.readthedocs.io/)*
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Sumário
|
|
78
|
+
|
|
79
|
+
1. [Destaques da Versão `0.3.0`](#destaques-da-versão-030)
|
|
80
|
+
2. [Instalação e Pré-Aquecimento Offline / Docker](#instalação-e-pré-aquecimento-offline--docker)
|
|
81
|
+
3. [Uso Rápido: CLI, Python, Injeção de RNG e Faker](#uso-rápido-cli-python-injeção-de-rng-e-faker)
|
|
82
|
+
4. [Arquitetura de Dados e Amostragem](#arquitetura-de-dados-e-amostragem)
|
|
83
|
+
5. [Fundamentação Teórica e Matemática](#fundamentação-teórica-e-matemática)
|
|
84
|
+
6. [Limitações Metodológicas Declaradas](#limitações-metodológicas-declaradas)
|
|
85
|
+
7. [Créditos, Fontes de Dados e Licença](#créditos-fontes-de-dados-e-licença)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Destaques da Versão `0.3.0`
|
|
90
|
+
|
|
91
|
+
- **Censo Demográfico 2022 por Padrão (`census_year=2022`, `TimePeriod.ALL`):** `128.458` prenomes (`99,8207%` da massa nacional com sexo observado diretamente pelo IBGE; `0,0%` de massa atribuída por LLM) e `201.601` sobrenomes nacionais e por UF (`Santos` liderando em Sergipe com `43,38%` de presença; `Silva` em Alagoas `35,75%` e Pernambuco `34,23%`), compilados a partir de [`olob0/ibge-nomes-no-brasil-2022`](https://huggingface.co/datasets/olob0/ibge-nomes-no-brasil-2022) (`05efb85c92af43da2ed4ed088d1e0c9f17160e65`). O Censo 2010 permanece disponível via `census_year=2010` / `--census-year 2010`.
|
|
92
|
+
- **Wheel Ultraleve (`< 150 KiB`) + Cache Criptograficamente Fixado no Hugging Face:** O `.whl` embarca apenas `ptbr_sampler/data/dataset_manifest.json` (`~16 KiB`). Partições Parquet em `float64` são baixadas sob demanda de [`arthrod/ptbr-sampler-data`](https://huggingface.co/datasets/arthrod/ptbr-sampler-data) em commit imutável de 40 caracteres, validadas por `SHA-256` sob lock `fcntl.flock` e gravadas atomicamente em `~/.cache/ptbr-sampler/<hf_revision>/`.
|
|
93
|
+
- **Provedor Nativo para `Faker` (`ptbr-sampler[faker]`):** `PTBRProvider` e `install_ptbr(fake, aliases=False)` oferecem perfis coerentes (`fake.ptbr_profile()`) e métodos escalares em $O(1)$ (`fake.ptbr_name()`, `fake.ptbr_cpf()`, `fake.ptbr_rg()`, `fake.ptbr_cep()`, `fake.ptbr_address()`, `fake.ptbr_phone()`), preservando os métodos padrão de `Faker('pt_BR')` a menos que `aliases=True` seja solicitado explicitamente.
|
|
94
|
+
- **Determinismo Isolado (`rng=random.Random(...)`) e Thread Safety:** Toda aleatoriedade flui por uma instância injetável de `random.Random` sem jamais alterar o estado global de `random` ou `numpy.random`, com caches protegidos por `RLock` e execução síncrona segura mesmo dentro de loops `asyncio` ativos (Jupyter, FastAPI, marimo).
|
|
95
|
+
- **Separação Estrita entre Marginais Observadas e Estimativas de Bayes:** `conditioning_mode='strict'` (padrão) serve exclusivamente tabelas publicadas pelo IBGE (`nacional`, `nacional × sexo`, `nacional × coorte`, `UF`); `conditioning_mode='estimated'` habilita reponderação preguiçosa via regra de Bayes para `UF × sexo` e `coorte × sexo` em memória (`< 5 ms`).
|
|
96
|
+
- **Amostragem em $O(1)$ via Método de Alias de Walker–Vose Compensado (Kahan):** Reconstrução exata do vetor de probabilidades com erro $L_\infty = 1,39 \times 10^{-17}$ em `float64` e validação estatística em quatro camadas com controle de erro familiar de Holm–Bonferroni ($\alpha_{\text{FWER}} = 0,001$).
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Instalação e Pré-Aquecimento Offline / Docker
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Pacote principal (< 150 KiB wheel)
|
|
104
|
+
pip install ptbr-sampler
|
|
105
|
+
# ou com integração oficial ao Faker:
|
|
106
|
+
pip install "ptbr-sampler[faker]"
|
|
107
|
+
|
|
108
|
+
# Com uv:
|
|
109
|
+
uv add ptbr-sampler
|
|
110
|
+
uv add "ptbr-sampler[faker]"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Na primeira execução fora de um checkout git, apenas as partições efetivamente requisitadas são baixadas (`~3,1 MiB` no caminho nacional padrão). Para **containers Docker, pipelines de CI ou ambientes sem acesso externo (*air-gapped*)**:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Pré-baixa e verifica o SHA-256 de todas as partições do Censo 2022
|
|
117
|
+
ptbr datasets prefetch --census-year 2022
|
|
118
|
+
|
|
119
|
+
# Pré-baixa ambos os censos (2022 + legado 2010, 195 arquivos)
|
|
120
|
+
ptbr datasets prefetch --all-vintages
|
|
121
|
+
|
|
122
|
+
# Inspeciona o diretório de cache e audita todos os digests SHA-256
|
|
123
|
+
ptbr datasets status --verify
|
|
124
|
+
|
|
125
|
+
# Execução estritamente offline (falha imediatamente se faltar algum artefato)
|
|
126
|
+
PTBR_SAMPLER_OFFLINE=1 ptbr generate --qty 5 --uf SP
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Variável de Ambiente | Comportamento |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `PTBR_SAMPLER_CACHE_DIR` | Diretório raiz do cache de usuário (padrão: `$XDG_CACHE_HOME/ptbr-sampler` ou `~/.cache/ptbr-sampler`). |
|
|
132
|
+
| `PTBR_SAMPLER_DATA_DIR` | Diretório imutável pré-populado com os artefatos de execução (ideal para imagens Docker multi-stage). |
|
|
133
|
+
| `PTBR_SAMPLER_HF_REPO` | Repositório espelho no Hugging Face Hub (padrão: `arthrod/ptbr-sampler-data`). |
|
|
134
|
+
| `PTBR_SAMPLER_OFFLINE` | Quando `1` ou `true`, bloqueia qualquer chamada HTTP de rede em tempo de execução. |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Uso Rápido: CLI, Python, Injeção de RNG e Faker
|
|
139
|
+
|
|
140
|
+
### 1. Interface de Linha de Comando (`ptbr`)
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Padrão 0.3.0: Censo 2022 (TimePeriod.ALL) + geografia ponderada + tabela Rich
|
|
144
|
+
ptbr generate --qty 5
|
|
145
|
+
|
|
146
|
+
# Fixar uma Unidade da Federação específica (nomes, sobrenomes, cidades, CEPs, DDD e RG de SP)
|
|
147
|
+
ptbr generate --qty 5 --uf SP --format json
|
|
148
|
+
|
|
149
|
+
# Condicionamento empírico por UF sorteada segundo a população IBGE
|
|
150
|
+
ptbr generate --qty 5 --uf-conditioning
|
|
151
|
+
|
|
152
|
+
# Condicionamento por sexo observado ('M', 'F', 'mixed' 50/50 ou 'population' empírico 48,56% M / 51,44% F)
|
|
153
|
+
ptbr generate --qty 5 --sex-conditioning population
|
|
154
|
+
|
|
155
|
+
# Condicionamento conjunto UF × sexo via independência condicional de Bayes (opt-in explícito)
|
|
156
|
+
ptbr generate --qty 5 --uf BA --sex-conditioning F --conditioning-mode estimated
|
|
157
|
+
|
|
158
|
+
# Coorte decenal de nascimento do Censo 2022 (ex.: nascidos em 2010–2019)
|
|
159
|
+
ptbr generate --qty 5 --time-period ate2020
|
|
160
|
+
|
|
161
|
+
# Modo histórico Censo 2010 e modo uniforme ("realismo desativado")
|
|
162
|
+
ptbr generate --qty 5 --census-year 2010
|
|
163
|
+
ptbr generate --qty 5 --random
|
|
164
|
+
|
|
165
|
+
# Catálogo auditável de fontes de dados
|
|
166
|
+
ptbr sources --census-year 2022
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 2. API Python e Injeção Determinística de `random.Random`
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
import random
|
|
173
|
+
from ptbr_sampler import BrazilianNameSampler, TimePeriod, sample
|
|
174
|
+
|
|
175
|
+
# Stream determinístico isolado: não altera random.seed() nem numpy.random.seed() globais
|
|
176
|
+
rng = random.Random(2026)
|
|
177
|
+
|
|
178
|
+
# Perfil completo coerente (nome, UF, município, CEP, endereço, telefone, CPF, RG, PIS, CNPJ, CEI)
|
|
179
|
+
perfil = sample(q=1, all_data=True, uf_conditioning=True, rng=rng)
|
|
180
|
+
|
|
181
|
+
# Filtragem por UF fixa + condicionamento conjunto UF × sexo (opt-in 'estimated')
|
|
182
|
+
amostra_rj = sample(
|
|
183
|
+
q=5,
|
|
184
|
+
uf='RJ',
|
|
185
|
+
sex_conditioning='F',
|
|
186
|
+
conditioning_mode='estimated',
|
|
187
|
+
formatted=False, # dígitos puros para documentos
|
|
188
|
+
rng=random.Random(42),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Coorte de nascidos entre 2020 e 01/08/2022 (Censo 2022)
|
|
192
|
+
coorte_recente = sample(q=5, time_period=TimePeriod.PERIOD_2020_2022, rng=random.Random(7))
|
|
193
|
+
|
|
194
|
+
# Uso direto do amostrador vetorial em Parquet (O(1) por amostra após carga da tabela de alias)
|
|
195
|
+
name_sampler = BrazilianNameSampler.from_parquet(census_year=2022)
|
|
196
|
+
pessoa = name_sampler.get_random_name(uf='SE', return_components=True, rng=random.Random(99))
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 3. Integração Oficial com `Faker` (`ptbr_sampler.faker`)
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from faker import Faker
|
|
203
|
+
from ptbr_sampler.faker import install_ptbr
|
|
204
|
+
|
|
205
|
+
# Por padrão (aliases=False), os métodos padrão do Faker('pt_BR') permanecem intactos
|
|
206
|
+
fake = install_ptbr(
|
|
207
|
+
Faker('pt_BR'),
|
|
208
|
+
uf_conditioning=True,
|
|
209
|
+
sex_conditioning='population',
|
|
210
|
+
conditioning_mode='estimated',
|
|
211
|
+
)
|
|
212
|
+
fake.seed_instance(12345)
|
|
213
|
+
|
|
214
|
+
perfil = fake.ptbr_profile() # Dicionário completo e internamente coerente (UF <-> cidade <-> CEP <-> DDD <-> RG)
|
|
215
|
+
nome = fake.ptbr_name() # Nome completo ponderado pelo Censo 2022
|
|
216
|
+
sobrenome = fake.ptbr_surname() # Sobrenome composto sem repetição de raiz (s2 != s1)
|
|
217
|
+
cpf = fake.ptbr_cpf(formatted=True) # Dígitos verificadores módulo-11 válidos
|
|
218
|
+
rg_sp = fake.ptbr_rg(uf='SP') # RG com regra oficial SSP-SP
|
|
219
|
+
|
|
220
|
+
# Opcional: substituir também os formatadores padrão (fake.name(), fake.cpf(), fake.city(), ...)
|
|
221
|
+
fake_aliased = install_ptbr(Faker('pt_BR'), aliases=True, uf='MG')
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Arquitetura de Dados e Amostragem
|
|
227
|
+
|
|
228
|
+
```mermaid
|
|
229
|
+
flowchart LR
|
|
230
|
+
subgraph Fontes["Fontes Públicas Auditáveis"]
|
|
231
|
+
IBGE22["IBGE Censo 2022<br/>olob0 Parquet (SHA-256)"]
|
|
232
|
+
IBGE24["IBGE População 2024<br/>+ CEP / DDD"]
|
|
233
|
+
IBGE10["Legado Censo 2010<br/>+ genero-nomes"]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
subgraph Build["Ingestão & Validação"]
|
|
237
|
+
ING["ingest_to_parquet.py<br/>float64 + math.fsum"]
|
|
238
|
+
AUD["audit_datasets.py<br/>4 Camadas GoF"]
|
|
239
|
+
HF["Hugging Face Hub<br/>arthrod/ptbr-sampler-data"]
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
subgraph Runtime["Execução (< 150 KiB Wheel)"]
|
|
243
|
+
MAN["dataset_manifest.json<br/>SHA-256 + flock Cache"]
|
|
244
|
+
STORE["PartitionStore (RLock)<br/>+ AliasTable Vose O(1)"]
|
|
245
|
+
API["sample() / CLI ptbr<br/>/ PTBRProvider (Faker)"]
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
IBGE22 --> ING
|
|
249
|
+
IBGE24 --> ING
|
|
250
|
+
IBGE10 --> ING
|
|
251
|
+
ING --> AUD --> HF --> MAN --> STORE --> API
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Detalhes completos de armazenamento, esquemas Parquet e invariantes de cache estão em [`docs/architecture.md`](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/architecture.md) e [`docs/data-origins.md`](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/data-origins.md).
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Fundamentação Teórica e Matemática
|
|
259
|
+
|
|
260
|
+
Toda decisão estatística e numérica do `ptbr-sampler` `0.3.0` é formalmente verificada em código e descrita em profundidade no [Relatório Técnico (`docs/technical-report.md`)](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/technical-report.md).
|
|
261
|
+
|
|
262
|
+
### 1. Método de Alias de Walker–Vose em $O(1)$ com Compensação de Kahan
|
|
263
|
+
|
|
264
|
+
Dado um vocabulário finito de tamanho $M$ com contagens inteiras positivas $(c_1, \dots, c_M)$ (por exemplo, $M = 201.601$ sobrenomes nacionais), os pesos empíricos $w_i = c_i / \sum_{j=1}^M c_j$ são computados em `float64` usando soma exata em ponto flutuante (`math.fsum`, algoritmo de Shewchuk), garantindo $\bigl|\sum_{i=1}^M w_i - 1\bigr| < 10^{-15}$.
|
|
265
|
+
|
|
266
|
+
O algoritmo de Walker (1977) e Vose (1991) particiona os pesos escalados $s_i = M w_i$ em conjuntos `small` ($s_i < 1$) e `large` ($s_i \ge 1$), construindo em tempo linear $O(M)$ dois vetores $(\text{prob}, \text{alias}) \in [0,1]^M \times \{0,\dots,M-1\}^M$. Para evitar o acúmulo de erro de cancelamento catastrófico $O(M \varepsilon_{\text{mach}})$ quando um *hub* massivo como `Silva` ($s_{\text{Silva}} \approx 20.571$) absorve dezenas de milhares de resíduos da cauda longa, `AliasTable.from_weights` aplica:
|
|
267
|
+
1. Absorção em lote via `math.fsum` quando um único item `large` permanece; e
|
|
268
|
+
2. Soma compensada de Kahan (1965) nas transições gerais `large`/`small`.
|
|
269
|
+
|
|
270
|
+
A distribuição categórica exata induzida pelas tabelas construídas é reconstruída deterministicamente em $O(M)$ (sem ruído de Monte Carlo):
|
|
271
|
+
|
|
272
|
+
$$p_j^{\text{alias}} = \frac{1}{M}\left(\text{prob}[j] + \sum_{i:\,\text{alias}[i]=j} \bigl(1 - \text{prob}[i]\bigr)\right)$$
|
|
273
|
+
|
|
274
|
+
Nas partições do Censo 2022, a discrepância máxima medida é $\|p^{\text{alias}} - w\|_\infty = 1,39 \times 10^{-17}$ (precisão de máquina `float64`), contra $\sim 10^{-7}$ em implementações ingênuas em `float32`. Cada sorteio consome tempo constante $O(1)$ independentemente de $M$: sorteia-se $I \sim \text{Uniform}\{0,\dots,M-1\}$ e $U \sim \text{Uniform}[0,1)$, retornando $I$ se $U < \text{prob}[I]$ ou $\text{alias}[I]$ caso contrário.
|
|
275
|
+
|
|
276
|
+
### 2. Censura de Confidencialidade IBGE (`Liv102228`) e Decomposição Exata em 4 Regimes
|
|
277
|
+
|
|
278
|
+
Conforme a [Nota Técnica IBGE Liv102228](https://biblioteca.ibge.gov.br/visualizacao/livros/liv102228.pdf), o Censo 2022 aplica limiares de supressão **decrescentes** conforme a granularidade geográfica aumenta:
|
|
279
|
+
- **Brasil e Brasil × década de nascimento:** células com contagem **`< 20`** são suprimidas;
|
|
280
|
+
- **Unidade da Federação (UF):** células com contagem **`< 15`** são suprimidas;
|
|
281
|
+
- **Município:** células com contagem **`< 10`** são suprimidas.
|
|
282
|
+
|
|
283
|
+
Para cada prenome $i$ publicado no ranking nacional ($N_i \ge 20$), a tabela de detalhes por sexo divulga $(N_{i,M}^{\text{obs}}, N_{i,F}^{\text{obs}}) \in (\mathbb{Z}_{\ge 20} \cup \{\text{NULL}\})^2$. Pela lei de conservação $N_i = N_{i,M} + N_{i,F}$, o `ptbr-sampler` classifica exatamente os `128.458` prenomes (`190.383.184` ocorrências) em quatro regimes disjuntos:
|
|
284
|
+
|
|
285
|
+
| Regime de Censura | Condição Matemática | Prenomes | Massa / Resíduo | Tratamento Estatístico |
|
|
286
|
+
| --- | --- | ---: | ---: | --- |
|
|
287
|
+
| `both_observed` | $N_{i,M} \ge 20 \land N_{i,F} \ge 20$ | `10.582` | Resíduo `0` | Taxas empíricas exatas $p_{i,s} = N_{i,s}/N_i$ |
|
|
288
|
+
| `one_null_exact_zero` | Um sexo `NULL` e $N_i - N_{i,\text{obs}} = 0$ | `55.210` | Resíduo `0` | Zero exato deduzido ($p_{i,\text{obs}} = 1$, $p_{i,\text{null}} = 0$) |
|
|
289
|
+
| `one_null_suppressed_positive` | Um sexo `NULL` e $1 \le N_i - N_{i,\text{obs}} \le 19$ | `57.941` | `232.758` (`0,1223%`) | $p_{i,\text{obs}} = N_{i,\text{obs}}/N_i < 1$; célula suprimida permanece `NaN` (jamais imputada como zero) |
|
|
290
|
+
| `both_null_suppressed` | Ambos `NULL` ($20 \le N_i \le 38$, $1 \le N_{i,M}, N_{i,F} \le 19$) | `4.725` | `108.522` (`0,0570%`) | Mantido na marginal nacional não condicionada; excluído de condicionais de sexo |
|
|
291
|
+
|
|
292
|
+
Isso resulta em cinco métricas de cobertura transparentes no Censo 2022: **96,32%** de tipos no vocabulário com sexo observado, **99,8207%** de massa populacional empírica observada diretamente, **55.210** zeros exatos deduzidos, **0,0%** de massa vinda de LLM e **0,1793%** (`341.280` ocorrências) de massa suprimida.
|
|
293
|
+
|
|
294
|
+
### 3. Independência Condicional de Bayes (`strict` vs. `estimated`)
|
|
295
|
+
|
|
296
|
+
O IBGE publica marginais unidimensionais (`nacional`, `nacional × sexo`, `nacional × década`, `UF`), mas não o cubo cruzado completo `UF × década × sexo`.
|
|
297
|
+
- Em `conditioning_mode='strict'` (padrão), apenas distribuições diretamente observadas são servidas; combinações não observadas levantam `ValueError`.
|
|
298
|
+
- Em `conditioning_mode='estimated'`, sob a hipótese explícita de invariância condicional da razão de sexo dado o prenome $P(S = s \mid X = i, G = g) \approx \hat{P}_{\text{nat}}(S = s \mid X = i)$ para $G \in \{\text{UF}, \text{coorte}\}$, a distribuição a posteriori é construída em memória via regra de Bayes:
|
|
299
|
+
|
|
300
|
+
$$\hat{P}(X = i \mid G = g, S = s) = \frac{P_{\text{obs}}(X = i \mid G = g)\,\hat{p}_{i,s}^{\text{obs}}}{\sum_{k \in \mathcal{S}_{g,s}} P_{\text{obs}}(X = k \mid G = g)\,\hat{p}_{k,s}^{\text{obs}}}, \qquad \hat{p}_{i,s}^{\text{obs}} = \frac{N_{i,s}^{\text{obs}}}{N_i}$$
|
|
301
|
+
|
|
302
|
+
onde $\mathcal{S}_{g,s}$ restringe-se às células com $N_{i,s}^{\text{obs}}$ observado ($\ge 20$). A combinação `UF × coorte` permanece rejeitada em ambos os modos, pois a estrutura etária difere substancialmente entre UFs.
|
|
303
|
+
|
|
304
|
+
### 4. Participação por Slot vs. Presença Populacional de Sobrenomes
|
|
305
|
+
|
|
306
|
+
O percentual divulgado pelo IBGE para `Silva` (`16,76%` = `34.030.104 / 203.080.756`) mede a **presença por pessoa** (união sobre todos os sobrenomes do indivíduo). Como a soma nacional das contagens de sobrenomes é $\sum_k C_k = 333.496.261$, cada residente possui em média $\bar{L} \approx 1,6422$ tokens de sobrenome publicados, e a probabilidade de um único slot é:
|
|
307
|
+
|
|
308
|
+
$$q_i = \frac{C_i}{\sum_{k=1}^{M_S} C_k} \implies q_{\text{Silva}} = 10,2040\%, \quad q_{\text{Santos}} = 6,4071\%$$
|
|
309
|
+
|
|
310
|
+
No modo padrão de dois sobrenomes (`with_only_one_surname=False` em `census_year=2022`), o segundo sobrenome é amostrado condicionalmente sem reposição de raiz ortográfica ($S_2 \neq S_1$):
|
|
311
|
+
|
|
312
|
+
$$P(S_1 = i, S_2 = j) = \frac{q_i\,q_j}{1 - q_i}\,\mathbf{1}_{[i \neq j]}$$
|
|
313
|
+
|
|
314
|
+
evitando nomes irreais como `"Maria da Silva Silva"` e aproximando a incidência de presença em dois slots $P(i \in \{S_1, S_2\}) = q_i + \sum_{k \neq i} q_k \frac{q_i}{1 - q_k} \approx 19,65\%$ para `Silva`.
|
|
315
|
+
|
|
316
|
+
### 5. Validação de Aderência (*Goodness-of-Fit*) em Quatro Camadas
|
|
317
|
+
|
|
318
|
+
Em vez de aplicar o teste de Kolmogorov–Smirnov a categorias nominais (inválido por depender da ordenação arbitrária dos rótulos) ou truncar o qui-quadrado apenas no top-50 reescalonado (cego a vazamentos de massa cabeça–cauda), a suíte `ptbr_sampler/sampling/validation.py` verifica:
|
|
319
|
+
1. **Camada A (Conservação determinística):** somas exatas, esquemas Arrow `float64`, digests `SHA-256` e invariantes dos 4 regimes de censura.
|
|
320
|
+
2. **Camada B (Reconstrução exata da tabela de alias):** $\mathrm{TVD}(p^{\text{alias}}, w) = \frac{1}{2}\|p^{\text{alias}} - w\|_1 < 10^{-13}$ em todas as partições.
|
|
321
|
+
3. **Camada C (Monte Carlo multinomial exaustivo):** agrupamento adaptativo da cauda longa em *bins* disjuntos exaustivos ($\sum_j p_j = 1$) com contagem esperada $E_j = n p_j \ge 5$, estatística de Pearson $X^2 = \sum_{j=1}^K (O_j - E_j)^2 / E_j \sim \chi^2_{K-1}$, controle de taxa de erro familiar (FWER) pelo procedimento *step-down* de Holm (1979) em $\alpha = 0,001$, e dois controles negativos obrigatórios (vazamento de 2% de massa para a cauda e truncamento `top_40`).
|
|
322
|
+
4. **Camada D (Coerência demográfica entre tabelas):** mistura das UFs ponderada pela população vs. marginal nacional ($\mathrm{TVD} = 0,030919$, limitada pela censura `< 15` por UF) e razão entre soma das décadas e total nacional (`0,978767`, limitada pela censura `< 20` por década).
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Limitações Metodológicas Declaradas
|
|
327
|
+
|
|
328
|
+
- **Datas de referência mistas (`2022` vs. `2024`):** Prenomes e sobrenomes padrão refletem o estoque residente em **1º de agosto de 2022** (`203,08M`), enquanto os pesos municipais/estaduais de localização (`locations_data.json` e `cities_with_ceps.json`) utilizam as Estimativas da População IBGE de **1º de julho de 2024** (`212,6M`).
|
|
329
|
+
- **Normalização diacrítica do IBGE 2022:** As tabelas oficiais do Censo 2022 removem sinais diacríticos (`Joao`, `Goncalves`), preservando distinções consonantais/vocálicas (`Ana` vs. `Anna`, `Luis` vs. `Luiz`). O `ptbr-sampler` aplica *Title Case* sem inventar acentuação heurística.
|
|
330
|
+
- **Nomes compostos (segundo prenome) e preposições:** O IBGE divulga apenas o primeiro prenome e raízes de sobrenomes sem conectivos. A incidência de segundo prenome (`percentage_with_second = 30,99%` em `middle_names.json`, higienizado por `vocabulary.py`) e os conectivos (`da`, `de`, `dos`) provêm de convenções autorais/cartorárias documentadas.
|
|
331
|
+
- **Documentos e endereços 100% sintéticos:** CPFs, RGs, PIS, CNPJs, CEIs, logradouros offline e números de telefone são gerados algoritmicamente a partir de regras matemáticas de dígitos verificadores; nenhuma pessoa real é referenciada.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Créditos, Fontes de Dados e Licença
|
|
336
|
+
|
|
337
|
+
### Créditos e Fontes Estatísticas
|
|
338
|
+
- **IBGE — Instituto Brasileiro de Geografia e Estatística:** *Censo Demográfico 2022: Nomes no Brasil* e [Nota Técnica Liv102228](https://biblioteca.ibge.gov.br/visualizacao/livros/liv102228.pdf) (2025); *Censo Demográfico 2010 — API Nomes v2* (2016); *Estimativas da População Residente nos Municípios* (2024). Dados públicos sob a política de disseminação aberta do IBGE (Decreto nº 8.777/2016).
|
|
339
|
+
- **Gabriel Lobo (`olob0`):** compilação pública reproduzível em Parquet [`olob0/ibge-nomes-no-brasil-2022`](https://huggingface.co/datasets/olob0/ibge-nomes-no-brasil-2022) (fixada no commit `05efb85c92af43da2ed4ed088d1e0c9f17160e65`).
|
|
340
|
+
- **Álvaro Justen (`@turicas`) e Brasil.IO:** dataset [`genero-nomes`](https://brasil.io/dataset/genero-nomes/files/) ([CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)), utilizado exclusivamente no modo histórico opcional `census_year=2010`.
|
|
341
|
+
- **Arpen-Brasil (Portal da Transparência do Registro Civil):** rankings anuais de registros de nascimento utilizados como referência comparativa de fluxo vs. estoque ([`docs/sources/arpen-2024-rankings.md`](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/sources/arpen-2024-rankings.md)).
|
|
342
|
+
- **Correios / ViaCEP e Anatel:** faixas postais de CEP e códigos nacionais de área (DDD) por município.
|
|
343
|
+
- **Referências Teóricas:** A. J. Walker (*ACM TOMS*, 1977); M. D. Vose (*IEEE TSE*, 1991); W. Kahan (*CACM*, 1965); S. Holm (*Scandinavian Journal of Statistics*, 1979). Bibliografia completa em [`docs/sources/bibliography.md`](https://github.com/jandira-tech/ptbr-sampler/blob/main/docs/sources/bibliography.md).
|
|
344
|
+
|
|
345
|
+
### Licença
|
|
346
|
+
O código-fonte deste repositório é distribuído sob a **Licença MIT** (`Copyright (c) 2026 Jandira Tech`) — veja [`LICENSE`](https://github.com/jandira-tech/ptbr-sampler/blob/main/LICENSE). As atribuições e termos específicos de cada base pública ou compilação de terceiros estão detalhados em [`THIRD_PARTY_NOTICES.md`](https://github.com/jandira-tech/ptbr-sampler/blob/main/THIRD_PARTY_NOTICES.md).
|