{cnefetools} provides helper functions to efficiently work with the Brazilian National Address File for Statistical Purposes (Cadastro Nacional de Endereços para Fins Estatísticos, CNEFE), an address-level dataset released by the Brazilian Institute of Geography and Statistics (Instituto Brasileiro de Geografia e Estatística, IBGE).
Install the stable version from CRAN:
install.packages("cnefetools")
To install the development version from GitHub:
# install.packages("pak")
pak::pak("pedreirajr/cnefetools")
# or
# install.packages("remotes")
remotes::install_github("pedreirajr/cnefetools")
| Function | Description |
|----|----|
| read_cnefe() | Downloads and reads CNEFE data for a municipality, or reads a local file with file = ..., and returns an Arrow table or sf object |
| cnefe_counts() | Aggregates address counts to H3 hexagons or user-provided polygons |
| compute_lumi() | Computes land-use mix indices on H3 hexagons or user-provided polygons |
| tracts_to_h3() | Dasymetric interpolation of census tract variables to an H3 grid via CNEFE dwelling points |
| tracts_to_polygon() | Dasymetric interpolation of census tract variables to user-provided polygons via CNEFE dwelling points |
| cnefe_doc() | Opens the official CNEFE methodological note (PDF) |
| cnefe_dictionary() | Opens the official CNEFE variable dictionary (Excel) |
| cnefe_export() | Writes a municipality to a persistent file of your choice (Parquet, CSV or gzipped CSV) |
| clear_cache_muni(), clear_cache_tracts() | Delete cached CNEFE files or census tract Parquet files from the cache directory |
read_cnefe() downloads and reads the CNEFE CSV for a municipality,
returning an Arrow table by default:
library(cnefetools)
library(dplyr)
# Read CNEFE data for Salvador as an Arrow table
tab_ssa <- read_cnefe(2927408, cache = TRUE)
tab_ssa |>
collect() |> # materialize the arrow table in R
tibble() |>
head()
#> # A tibble: 6 × 34
#> COD_UNICO_ENDERECO COD_UF COD_MUNICIPIO COD_DISTRITO COD_SUBDISTRITO COD_SETOR
#> <int> <int> <int> <int> <int64> <chr>
#> 1 222386741 29 2927408 292740805 29274080518 29274080…
#> 2 27995350 29 2927408 292740805 29274080522 29274080…
#> 3 28034841 29 2927408 292740805 29274080522 29274080…
#> 4 217544957 29 2927408 292740805 29274080518 29274080…
#> 5 217639781 29 2927408 292740805 29274080526 29274080…
#> 6 217639701 29 2927408 292740805 29274080526 29274080…
#> # ℹ 28 more variables: NUM_QUADRA <int>, NUM_FACE <int>, CEP <int>,
#> # DSC_LOCALIDADE <chr>, NOM_TIPO_SEGLOGR <chr>, NOM_TITULO_SEGLOGR <chr>,
#> # NOM_SEGLOGR <chr>, NUM_ENDERECO <int>, DSC_MODIFICADOR <chr>,
#> # NOM_COMP_ELEM1 <chr>, VAL_COMP_ELEM1 <chr>, NOM_COMP_ELEM2 <chr>,
#> # VAL_COMP_ELEM2 <chr>, NOM_COMP_ELEM3 <chr>, VAL_COMP_ELEM3 <chr>,
#> # NOM_COMP_ELEM4 <chr>, VAL_COMP_ELEM4 <chr>, NOM_COMP_ELEM5 <chr>,
#> # VAL_COMP_ELEM5 <chr>, LATITUDE <dbl>, LONGITUDE <dbl>, …
Setting output = "sf" returns an sf object instead. The example
below reads data for Salvador, filters religious facilities
(COD_ESPECIE == 8), and plots them:
library(sf)
library(ggplot2)
# Reading CNEFE data
tab_ssa_sf <- read_cnefe(
code_muni = 2927408,
output = "sf",
cache = TRUE
)
# Filtering religious establishments
temples_ssa <- tab_ssa_sf |>
filter(COD_ESPECIE == 8)
# Ploting religious establishments points for Salvador
ggplot() +
geom_sf(data = temples_ssa, size = 0.3, alpha = 0.6) +
coord_sf() +
theme_minimal()

Warning: For large municipalities, CNEFE may contain millions of address points. Plotting all coordinates at once can be slow and memory-intensive, so consider filtering or sampling before creating maps.
By default, cache = TRUE keeps each municipality you download, so
later calls don’t download it again. The ZIP published by IBGE is
converted once, on the first download, into a gzipped CSV, which takes
about the same disk space and is faster to read.
The cache lives in tools::R_user_dir("cnefetools", "cache") unless you
point it somewhere else. You can do that for a single call with the
cache_dir argument, which every function that reads data accepts, or
for the whole session with the CNEFETOOLS_CACHE_DIR environment
variable. The argument wins when both are set:
# One call
tab_ssa <- read_cnefe(code_muni = 2927408, cache_dir = "D:/cnefe-cache")
# The whole session (or set it in your .Renviron)
Sys.setenv(CNEFETOOLS_CACHE_DIR = "D:/cnefe-cache")
If you prefer to avoid persistent caching, set:
tab_ssa <- read_cnefe(code_muni = 2927408, cache = FALSE)
In this case, the file is stored in a temporary location and removed after reading. The Cache and exported copies article covers all of this in more detail.
The cache is meant to be disposable, and the cleaning functions below
empty it. If an analysis needs a copy of the data that stays put,
cnefe_export() writes a municipality to a folder of your choice as
Parquet (the default), CSV or gzipped CSV, and read_cnefe(file = ...)
reads it back without downloading anything:
path <- cnefe_export(2927408, path = "data/cnefe")
tab_ssa <- read_cnefe(file = path)
file also accepts the ZIP exactly as IBGE publishes it, so a file you
downloaded by other means can be read the same way.
{cnefetools} includes local copies of the official methodological note and the variable dictionary for the 2022 CNEFE released by IBGE.
# Open the official methodological note (PDF)
cnefe_doc(year = 2022)
# Open the official variable dictionary (.xls spreadsheet)
cnefe_dictionary(year = 2022)
cnefe_counts()cnefe_counts() aggregates CNEFE address points into spatial units and
returns an sf object with counts by address category (addr_type1 to
addr_type8). Below is an example using H3 hexagons for São Paulo at
resolution 9:
library(cnefetools)
library(sf)
library(ggplot2)
# Producing CNEFE counts
hex_sp <- cnefe_counts(
code_muni = 3550308,
h3_resolution = 9,
cache = TRUE,
verbose = TRUE
)
Below we plot the count of private households (addr_type1) per
hexagon:
# Plotting private households (addr_type1) for São Paulo
ggplot(hex_sp) +
geom_sf(aes(fill = addr_type1), color = NA) +
scale_fill_viridis_c(option = "magma") +
coord_sf() +
labs(
fill = "Count",
title = "Private households (addr_type1)",
subtitle = "São Paulo (IBGE 3550308), H3 resolution 9"
) +
theme_minimal()+
theme(
plot.title.position = "plot",
axis.text.x = element_text(size = 5),
axis.text.y = element_text(size = 5)
)

cnefe_counts() also supports user-supplied polygons to aggregate
counts to custom polygons instead of H3 hexagons (just pass an sf
object to polygon). See the cnefe_counts
article
for details.
compute_lumi()compute_lumi() computes land-use mix indicators on spatial units for
any municipality covered by the 2022 CNEFE dataset (Pedreira Junior et
al.,
2026).
Available indicators include the Entropy Index (ei), the
Herfindahl-Hirschman Index (hhi), the Balance Index (bal), the Index
of Concentration at Extremes (ice), an adapted HHI (hhi_adp), and
the Bidirectional Global-centered Balance Index (bgbi).
All of them rest on a binary split: an address counts as residential
when it’s a private household (COD_ESPECIE == 1) and as
non-residential otherwise, and buildings under construction (type 7) are
left out. So the indices measure the balance between housing and all
other uses, not how diverse those other uses are. The residential share
itself is returned as p_res, and if you need the individual
non-residential types, cnefe_counts() keeps all eight.
Below is an example for Fortaleza at H3 resolution 8:
library(cnefetools)
library(sf)
library(ggplot2)
# Computing land use mix indices
lumi_ftl <- compute_lumi(
code_muni = 2304400,
h3_resolution = 8,
cache = TRUE,
verbose = TRUE
)
Below we plot the Bidirectional Global-centered Balance Index (BGBI), where positive values indicate residential dominance and negative values indicate non-residential dominance:
# Plotting the BGBI index
ggplot(lumi_ftl) +
geom_sf(aes(fill = bgbi), color = NA) +
scale_fill_distiller(
type = "div",
palette = "RdBu",
direction = 1
) +
coord_sf() +
labs(
fill = "BGBI",
title = "Bidirectional Global-centered Balance Index (BGBI)",
subtitle = "Fortaleza (IBGE 2304400), H3 resolution 8"
) +
theme_minimal()+
theme(
plot.title.position = "plot",
axis.text.x = element_text(size = 5),
axis.text.y = element_text(size = 5)
)

compute_lumi() also supports user-supplied polygons to compute indices
on custom polygons. Likewise, just pass an sf object to polygon. See
the compute_lumi
article
for details.
tracts_to_h3()tracts_to_h3() performs a dasymetric interpolation, considering two
stages: first, census tract totals are allocated to individual CNEFE
dwelling points inside each tract; then, the allocated values are
aggregated to an H3 grid at the chosen resolution. This leverages the
fine-grained spatial distribution of addresses in CNEFE to produce more
realistic sub-tract estimates than simple areal weighting.
library(cnefetools)
library(ggplot2)
# Performing dasymetric interpolation
rec_hex <- tracts_to_h3(
code_muni = 2611606,
h3_resolution = 9,
vars = c("pop_ph", "avg_inc_resp"),
cache = TRUE,
verbose = TRUE
)
The resulting H3 grid can be mapped to visualize the spatial
distribution of each variable. Below we plot the private-household
population (pop_ph):
ggplot(rec_hex) +
geom_sf(aes(fill = pop_ph), color = NA) +
scale_fill_viridis_c() +
coord_sf() +
labs(
title = "Dasymetric interpolation to H3 using CNEFE (Recife)",
subtitle = "Private-household population (pop_ph), H3 resolution 9",
fill = "Population"
) +
theme_minimal() +
theme(
plot.title.position = "plot",
axis.text.x = element_text(size = 5),
axis.text.y = element_text(size = 5)
)

And the average income of the household head (avg_inc_resp):
ggplot(rec_hex) +
geom_sf(aes(fill = avg_inc_resp), color = NA) +
scale_fill_viridis_c() +
coord_sf() +
labs(
title = "Dasymetric interpolation to H3 using CNEFE (Recife)",
subtitle = "Average income of the responsible person (avg_inc_resp), H3 resolution 9",
fill = "Income"
) +
theme_minimal() +
theme(
plot.title.position = "plot",
axis.text.x = element_text(size = 5),
axis.text.y = element_text(size = 5)
)

The full list of available variables is documented in the
tracts_variables_ref dataset (see ?tracts_variables_ref). For
allocation rules and diagnostic details, see the tracts_to
article.
tracts_to_polygon()tracts_to_polygon() follows the same two-stage workflow as
tracts_to_h3(), but aggregates the allocated values to user-provided
polygons (e.g. neighborhoods, administrative divisions, or custom areas)
instead of an H3 grid. Let’s generate the neighborhoods of Recife with
the read_neighborhood() function from the geobr package and
interpolate the average income of household heads per neighborhood:
library(geobr)
# Reading neighborhoods from geobr package
rec_nei <- read_neighborhood(year = 2022, simplified = F, showProgress = F) |>
filter(name_muni == 'Recife')
# Dasymetric interpolation to neighborhoods
rec_poly <- tracts_to_polygon(
code_muni = 2611606,
polygon = rec_nei,
vars = c("pop_ph", "avg_inc_resp"),
cache = TRUE,
verbose = F
)
Below we plot the interpolated average income of the household head
(avg_inc_resp) at the neighborhood level:
# Plotting variables at the neighborhood level
ggplot(rec_poly) +
geom_sf(aes(fill = avg_inc_resp), color = NA) +
scale_fill_viridis_c() +
coord_sf() +
labs(
title = "Dasymetric interpolation to neighborhoods using CNEFE (Recife)",
subtitle = "Average income of the responsible person (avg_inc_resp)",
fill = "Income"
) +
theme_minimal() +
theme(
plot.title.position = "plot",
axis.text.x = element_text(size = 5),
axis.text.y = element_text(size = 5)
)

See the tracts_to article for details.
Under the hood, {cnefetools} uses DuckDB as
its default backend. DuckDB reads the cached gzipped CSV directly,
decompressing it natively, and aggregates as it scans, so the full
address table never has to sit in memory. Its advantage over pure R
grows with the size of the municipality. On São Paulo, the largest in
the country, cnefe_counts() runs more than 15 times faster and its
peak memory is more than 12 times smaller.
Two DuckDB extensions do the spatial work:
The R package duckspatial
bridges sf objects and DuckDB’s spatial extension.
All extensions are installed and loaded automatically on first use. You can set how many threads and how much memory DuckDB may use:
options(cnefetools.duckdb_config = list(threads = 4, memory_limit = "4GB"))
cnefe_counts() and compute_lumi() also have a pure-R backend
(backend = "r"), built on h3jsr and sf. Use it when DuckDB
extensions can’t be installed, for example on some restricted computing
clusters. It isn’t the lighter option as it holds the address table in R
memory, so on large municipalities it needs far more RAM than DuckDB.
See the benchmark
article
for the measurements.
While caching speeds up repeated analyses by avoiding redundant downloads, users may want to free up disk space or force a fresh download. {cnefetools} provides two dedicated functions for fine-grained control over the local cache, allowing you to remove cached files selectively or all at once.
clear_cache_muni() deletes cached CNEFE files from the cache
directory. You can remove all cached files at once or target a specific
municipality by its seven-digit IBGE code:
clear_cache_muni() # delete all cached CNEFE files
clear_cache_muni(2919207) # delete only the file for Lauro de Freitas-BA
clear_cache_tracts() removes cached census tract Parquet files. You
can filter by state using a two-letter UF abbreviation, a two-digit
numeric state code, or a seven-digit municipality code (resolved to its
state automatically):
clear_cache_tracts() # delete all cached census tract Parquets
clear_cache_tracts("BA") # delete only the Parquet for Bahia
clear_cache_tracts(29) # same, using the numeric state code
clear_cache_tracts(2919207) # same, using a municipality code
If you moved the cache with cache_dir, pass the same cache_dir to
these functions, so they clean the folder you’re actually using.
If you use {cnefetools} in your work, please cite it as:
Pedreira Junior, J.U. & Stabile, B.H.M. (2026). cnefetools: Access and Analysis of Brazilian CNEFE Address Data. R package, available on CRAN: https://CRAN.R-project.org/package=cnefetools
If you use the land use mix index functions in compute_lumi(),
particularly the BGBI, please also cite:
Pedreira Junior, J. U.; Louro, T. V.; Assis, L. B. M.; Brito, P. L.; Bomfim, F. G. (2026). BGBI: A citywide-referenced and bidirectional land use mix index for planning and policy evaluation. Land Use Policy, 169, 108135. DOI
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.