Geocoding Brazilian Polling Stations with Administrative Data Sets

Author

F. Daniel Hidalgo

Published

August 14, 2026

This document outlines an approach to geocoding Brazilian polling station that heavily relies on administrative datasets. In addition to detailing our approach, we also provide an honest, held-out estimate of the error of our method, measured out-of-fold on the subset of stations with independent TSE coordinates.

Our general approach is to generate a series of potential coordinates from a variety of administrative datasets. We use a machine learning model trained on a subset of the data with coordinates provided by Supreme Electoral Tribunal (TSE) to choose among the candidate coordinates. Inputs to this model are mostly measures of the quality of string matches between the polling station address and administrative data sources, as well as other characteristics of the address and municipality of the polling station. For each polling station, we select the coordinates with the predicted smallest error among the possible coordinates.

Data Sources

To geocode the polling stations, we leverage four main data sources:

  • Cadastro Nacional de Endereços para Fins Estatísticos (CNEFE) from the 2010 and the 2022 editions of the Census.
  • Cadastro Nacional de Endereços para Fins Estatísticos from the 2017 Agricultural Census.
  • Catálogo de Escolas from INEP.
  • The geocodebr geocoder, which resolves an address against IBGE’s own address surface.

The CNEFE datasets are national databases of addresses prepared by IBGE for the census and include detailed data on streets and addresses. The 2010 and 2017 versions includes private addresses, as well as listings of government buildings (such as schools) and the names of local establishments (such as the names of schools or businesses). The 20171 version only includes agricultural properties. Addresses in rural census tracts (setores censitários) in the 2010 CNEFE have longitude and latitude, while all agricultural properties in the 2017 CNEFE are geocoded. The 2022 CNEFE geocodes all addresses.

The 2010 Census data did not include coordinates for addresses in urban census tracts. To partially overcome this issue, we compute the centroid of the census tract and assign this coordinate to each property in the urban census tract. Because urban census tracts tend to be compact, tract centroid should still be fairly close to the true coordinates. Nevertheless, this imputation step will lead to more error for urban addresses than rural addresses when the chosen coordinate is from the 2010 CNEFE data.

The INEP data is a catalog of private and public schools with addresses and longitude and latitude.2

String Matching

To geocode polling stations, we use fuzzy string matching to match polling stations to coordinates in the administrative datasets by name, address, street, or neighborhood. This string matching procedure generates several candidate coordinates. To choose among these possible coordinates, we use a boosted tree model trained on a sample of polling stations with coordinates provided by the election authorities.

The general approach is a follows:

  1. Normalize3 name and address of polling station.

  2. Normalize addresses and school names in administrative datasets.

  3. Find the “medioid” (i.e. the median point) for all unique streets and neighborhoods in the CNEFE datasets.

  4. Compute the Jaccard string distance over character trigrams between polling station name and the names of schools in the INEP and CNEFE data in the same municipality as the polling station.

  5. Compute the string distance between the address of polling stations and address of schools in INEP and CNEFE data.

  6. Compute the string distance between the street name and neighborhood name of the polling station and street and neighborhood names from the CNEFE datasets.

  7. For each candidate produced by steps 4–6, compute a further string distance for every address component the matched reference record happens to carry, not only the component the match was made on: school name, street, neighborhood, and the whole address.

The string matching procedure above generates up to ten potential matches; together with the coordinate geocodebr resolves directly, each polling station has up to eleven candidate coordinates.

Choosing Among Potential Matches

After string matching, we use boosted tree models to predict the distance between the possible coordinates and the true coordinates. We treat the coordinates provided by the election authorities as the “ground truth”. Two questions have to be answered about each candidate, and they are not the same question: which candidate is likely to be closest, and how far off the one we ship might be. We therefore fit two models on the same features and the same training split, differing only in what they estimate. The selection model estimates a candidate’s expected error and is what ranks candidates; the bound model estimates the 90th percentile of that error and, after a conformal correction, becomes the published conf_dist_km. Both models are fit on the following set of covariates:

  • Trigram string distance of the match that produced the candidate (string-matched sources only).
  • geocodebr’s uncertainty radius, as a separate covariate. It is a distance in kilometers rather than a normalized string distance, so the two do not share a scale and cannot share a column: a six-metre radius would otherwise sort below every possible string distance, and a coarse one above every possible string distance. Each is missing for the candidates the other describes.
  • Four per-component string distances between the polling station and the matched reference record: school name, street, neighborhood, and whole address line (step 7 above). Each is missing when the source carries no such field.
  • Coordinate data source
  • Measures of where the station’s other candidates fall, which let the model treat independent references landing on the same spot as evidence and a lone outlier as suspect: how many candidates the station has at all; the distance to the nearest candidate drawn from a different reference dataset, and which dataset that is; how many different datasets fall within 500 metres; the spread of the station’s whole candidate cloud (the median distance between its pairs); and how far this candidate sits from the cloud’s centre. Agreement is counted across the five underlying datasets rather than the individual matches.
  • Indicator for whether the address mentions the city center (“centro”)
  • Indicator for whether the address mentions being in the countryside (includes the word “rural”)
  • Indicator for whether the address mentions a school
  • Indicator for whether the address gives no house number (“s/n”), which is true of roughly a quarter of polling stations and signals informal or rural addressing
  • Log of municipal population
  • Proportion of the population classified as rural
  • Area of the municipality

We use the implementation of the boosted tree model provided in the lightgbm package and use the tidymodels framework for preprocessing and training. We split the polling stations with ground truth coordinates in half by municipality, training on one half and holding out the other. We tune the hyperparameters of each model using adaptive resampling4 and 10 fold cross-validation, each on the loss it is trained for: squared error for the selection model, pinball loss for the bound. The held-out half then serves as the calibration set for the conformal correction that turns the bound model’s prediction into conf_dist_km. That correction is computed on each station’s selected candidate rather than on all of them, so the published bound covers the coordinate that actually ships. For each polling station, we choose the candidate coordinate with the smallest expected error under the selection model.

Example of String Matching

To illustrate the string matching procedure, the table below shows the string matching procedure for one polling station where the coordinates are known. “String distance” is the Jaccard distance over character trigrams between the address component and its potential match. “Expected error” is the error the selection model predicts for that candidate, and “Error bound” is the calibrated 90% upper bound the bound model produces for it. The blue row shows the selected match, which is the candidate with the smallest expected error. Its error bound is the conf_dist_km published for the station, and it is not necessarily the smallest bound in the table — the two models are ranking on different quantities. The last column labeled “True error (km)” is the distance between the known TSE coordinates and the coordinates from each candidate.

Example of String Matching
Polling Station Name is COLEGIO FRANCISCANO AVE MARIA. Polling Station Address is RUA URUGUAIANA, 420
Data Polling Station String Match String Distance Expected Error (km) Error Bound (km) True Error (km)
geocodebr NA NA NA 0.02 0.08 0.03
2022 CNEFE School franciscano ave maria ave maria 0.63 0.02 0.08 0.03
INEP School Address rua uruguaiana 420 bosque jaguara barao 190 rua bosque 0.79 0.03 0.07 0.03
INEP School Name franciscano ave maria franciscano ave maria 0.00 0.03 0.07 0.03
2010 CNEFE Street rua uruguaiana 420 rua uruguaiana 0.25 0.09 0.19 0.12
2022 CNEFE Street rua uruguaiana 420 rua uruguaiana 0.25 0.12 0.20 0.13
2010 CNEFE School franciscano ave maria ave maria 0.63 0.22 0.26 0.21
2010 CNEFE Neighborhood bosque bosque 0.00 0.23 0.30 0.27
2022 CNEFE Neighborhood bosque bosque 0.00 0.25 0.31 0.27
2017 CNEFE Street rua uruguaiana 420 rua um 0.82 8.04 8.64 7.88
Highlighted row is the selected match (lowest expected error).

Estimating Geocoding Error

Estimating accuracy honestly is constrained by one fact: wherever the TSE has a coordinate, our published output is that TSE coordinate, and the TSE coordinate is also the model’s training target. The model-selected coordinate reaches the output only for stations the TSE did not cover. So accuracy can only be measured on the TSE-covered subset, and it must be measured out-of-fold — each covered station scored by a model refit on other municipalities.

On the covered set, the out-of-fold median error is 0.03 km and 85.1% of stations land within 500 m of their TSE coordinate, at a match rate of 100.0% over 258,555 covered stations. Positional error is a right-skewed distribution, so we report percentiles and within-threshold shares rather than a single mean, and always alongside the match rate (the two trade off).

The table below cuts accuracy by urban/rural census tract and by region; rural stations are multiples worse than urban, the dominant axis of variation. Strata below the held-out sample-size floor are suppressed (counts shown, medians not).

Out-of-fold geocoding error (TSE-covered set)
N covered Match % Median km <500m % <1km %
overall
all 258,555 100.0 0.03 85.1 89.4
urban_rural
urban 176,890 100.0 0.03 92.0 95.3
rural 79,524 100.0 0.05 69.7 76.1
NA 2,141 100.0 0.02 91.5 94.1
region
Norte 24,696 100.0 0.02 83.4 86.1
Nordeste 93,096 100.0 0.02 87.5 91.6
Sudeste 60,044 100.0 0.03 93.1 95.5
Sul 63,347 100.0 0.06 73.6 80.9
Centro-Oeste 17,372 100.0 0.03 89.0 92.2
Error in kilometres. Suppressed strata show counts only.

The published conf_dist_km claims the true location is within it for at least 90% of stations. Out of fold it holds for 90.0%, at a median bound of 0.21 km against a median realized error of 0.03 km. It also ranks: dropping the 50% of stations with the widest bounds lowers the realized median error from 0.03 km to 0.02 km and raises the share within 500 m from 85.1% to 98.1%.

Is the selection model doing the work?

A model that barely beats a one-line rule is not paying for its complexity. We score a trivial deterministic alternative through the same protocol: for each station, take the highest-precedence candidate available — INEP school matched on name, then CNEFE school, then INEP matched on address, then a geocoded address, then the matched street’s median coordinate, then the neighborhood’s centroid — breaking ties within a rank on the closest string match. It trains on nothing. Both selectors rank the same candidates, so they geocode exactly the same stations and the comparison is pure accuracy.

On the covered set, the heuristic reaches a median error of 0.05 km with 65.7% of stations within 500 m, against 0.03 km and 85.1% for the selection model — a difference of -0.02 km in median error and +19.4 percentage points within 500 m (a negative and a positive, respectively, favour the model).

The full per-stratum comparison is available from the baseline_comparison pipeline target.

How much of this could an off-the-shelf geocoder do?

geocodebr is one of the candidate sources, and it is built on IBGE’s own aggregation of the same 2022 census address file that two of our reference tables — matched street segments and matched neighborhoods — are built from. That overlap raises a fair question: are those hand-built tables earning their place, or would the off-the-shelf geocoder do as well on its own? We answer it by scoring geocodebr’s coordinates against the TSE ground truth on the stations where one of those two tables currently supplies the winning match, comparing only stations both approaches resolve so a difference in accuracy is not a difference in coverage in disguise.

On the 19,483 covered stations the 2022 street and neighborhood tables win, geocodebr returns a coordinate for 19,332. Where both resolve the station, geocodebr’s median error is 1.68 km against 0.54 km for the pipeline’s pick, and 30.8% of its coordinates land within 500 m against 48.0% — a difference of +1.14 km and -17.2 percentage points (a negative and a positive, respectively, favour geocodebr).

The breakdown by geocodebr’s own precision tier — how far down its cascade each result came from — is available from the geocodebr_vs_model pipeline target, along with the same comparison over the whole covered set.

A separate, covered-only Google reference-validation (Google-vs-TSE agreement) can be produced by running scripts/generate_google_reference.R once to freeze data/google_geocoded.csv; it quantifies Google’s error budget and is not a pipeline accuracy number.

Footnotes

  1. Details on the 2017 CNEFE can be found at this link↩︎

  2. The data can be found at this link↩︎

  3. We remove common, but uninformative words, such as “povoado” and “localidade”. We standardize common street abbreviations such as replacing “Av” with “Avenida”. Finally, for polling station names, we remove words most common in school names, such as “unidade escolar” and “colegio estadual”. These are very common, yet not used consistently and as a result, are relatively uninformative. We found that removing them improves matching performance.↩︎

  4. See the finetune package reference materials for more information on adaptive resampling.↩︎