| Title: | Brazilian Monthly Banking Statistics by Municipality (ESTBAN) |
|---|---|
| Description: | Download, read and tidy the ESTBAN (Estatistica Bancaria Mensal por Municipio, Monthly Banking Statistics by Municipality) files published by the Brazilian Central Bank (Banco Central do Brasil) for every bank branch and municipality in Brazil. Each file reports balance-sheet accounts of the COSIF (Plano Contabil das Instituicoes do Sistema Financeiro Nacional, the chart of accounts of the Brazilian financial system) such as credit operations, deposits and savings. Files are fetched from the official site <https://www.bcb.gov.br/estatisticas/estatisticabancariamunicipios> with an idempotent local cache, read from their Latin-1 encoded CSV (comma-separated values) layout into tibbles, optionally filtered by state, and aggregated by municipality. Includes tools to detect and impute institution-month non-reports (an institution present in the file with every account equal to zero), which would otherwise be mistaken for zero balances. |
| Authors: | Andre Leite [aut, cre] (ORCID: <https://orcid.org/0000-0002-4718-9766>), Marcos Wasiliew [aut], Hugo Vasconcelos [aut] (ORCID: <https://orcid.org/0000-0001-6249-0920>), Carlos Amorim [aut] (ORCID: <https://orcid.org/0000-0001-6315-8305>), Diogo Bezerra [aut] (ORCID: <https://orcid.org/0000-0002-1216-8674>), Júlia Nascimento Barreto [aut] |
| Maintainer: | Andre Leite <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.1 |
| Built: | 2026-09-30 19:45:24 UTC |
| Source: | https://github.com/cran/estbanr |
Sums every account over the institutions (and branches) of each
municipality and month. With impute = TRUE (the default) non-reported
institution-months are interpolated first with
estban_impute_nonreport(), so the municipal series does not collapse
when a bank is missing from a file.
estban_by_municipality(df, impute = TRUE, long = FALSE)estban_by_municipality(df, impute = TRUE, long = FALSE)
df |
A tibble from |
impute |
Logical. Interpolate non-reports before summing (default
|
long |
Logical. Return one row per municipality, month and account
( |
A tibble keyed by uf, codmun_ibge, municipio and ref.
In wide form the account columns follow; in long form the columns
verbete (clean column name) and value follow.
f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) m <- estban_by_municipality(x, impute = FALSE) m[, c("uf", "municipio", "ref", "verbete_160_operacoes_de_credito", "verbete_420_depositos_de_poupanca")] head(estban_by_municipality(x, impute = FALSE, long = TRUE))f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) m <- estban_by_municipality(x, impute = FALSE) m[, c("uf", "municipio", "ref", "verbete_160_operacoes_de_credito", "verbete_420_depositos_de_poupanca")] head(estban_by_municipality(x, impute = FALSE, long = TRUE))
The directory where downloaded ESTBAN files are kept. Resolution order:
estban_cache_dir(cache_dir = NULL, create = TRUE)estban_cache_dir(cache_dir = NULL, create = TRUE)
cache_dir |
Optional directory path. When |
create |
Logical. Create the directory when it does not exist
(default |
the cache_dir argument;
the ESTBANR_CACHE_DIR environment variable;
the estbanr.cache_dir R option;
a session-scoped folder under base::tempdir() (the default, so the
package never writes outside the temporary directory unless you opt
in).
Set one of the persistent options (2 or 3) to keep files across sessions and avoid re-downloading months you already have.
A normalized directory path (character scalar).
estban_cache_dir() # Persistent cache for the current session only: old <- options(estbanr.cache_dir = file.path(tempdir(), "estban-cache")) estban_cache_dir() options(old)estban_cache_dir() # Persistent cache for the current session only: old <- options(estbanr.cache_dir = file.path(tempdir(), "estban-cache")) estban_cache_dir() options(old)
Lower case, accents stripped, every run of non-alphanumeric characters
collapsed to a single underscore. Combined columns such as
"VERBETE_141_... + VERBETE_142_..." become one long name, so nothing is
lost and estban_verbetes() can map the name back to its account codes.
estban_clean_names(x)estban_clean_names(x)
x |
Character vector of column names. |
Character vector.
estban_clean_names(c("#DATA_BASE", "VERBETE_160_OPERACOES_DE_CREDITO", "VERBETE_174_PROV_P/_OPER_CREDITOS"))estban_clean_names(c("#DATA_BASE", "VERBETE_160_OPERACOES_DE_CREDITO", "VERBETE_174_PROV_P/_OPER_CREDITOS"))
estban_columns() lists the columns of the monthly file for a level, in
file order, with their snake_case names. estban_verbetes() restricts
the list to the balance-sheet accounts (VERBETE_*), parsing the
three-digit 'COSIF' codes out of the column name. Some columns combine
several accounts (for instance VERBETE_141 + VERBETE_142); those have
more than one code in codes and n_codes > 1.
estban_columns(level = c("agencia", "municipio")) estban_verbetes(level = c("agencia", "municipio"))estban_columns(level = c("agencia", "municipio")) estban_verbetes(level = c("agencia", "municipio"))
level |
|
The dictionary is built from the January 2024 files (see
data-raw/verbetes.R in the source repository) and covers both levels,
which share the same accounts.
A tibble. estban_columns() has position, column (original
name), name (clean name) and kind ("id" or "verbete").
estban_verbetes() has column, name, codes (character, codes
separated by ;), code (first code, integer), n_codes, side
("ativo" for codes below 400, "passivo" otherwise) and
description.
estban_columns()[1:8, ] v <- estban_verbetes() v[v$code %in% c(160, 420, 432), c("name", "codes", "side")] # Combined columns v[v$n_codes > 1, c("codes", "n_codes")]estban_columns()[1:8, ] v <- estban_verbetes() v[v$code %in% c(160, 420, 432), c("name", "codes", "side")] # Combined columns v[v$n_codes > 1, c("codes", "n_codes")]
Downloads the monthly file for ref, trying each name variant from
estban_url(), unzips it when needed and returns the path to the CSV in
the cache directory. Months already in the cache are not downloaded
again unless force = TRUE.
estban_download( ref, level = c("agencia", "municipio"), cache_dir = NULL, force = FALSE, timeout = 300, verbose = TRUE )estban_download( ref, level = c("agencia", "municipio"), cache_dir = NULL, force = FALSE, timeout = 300, verbose = TRUE )
ref |
Reference month as |
level |
|
cache_dir |
Directory for downloaded files. See |
force |
Logical. Re-download even when the CSV is already cached. |
timeout |
Seconds allowed for one download (default 300). |
verbose |
Logical. Emit progress messages (default |
The path to the cached CSV (invisibly NULL when the month is
not published under any of the known names, with a warning).
# Needs network access to www.bcb.gov.br (about 2 MB); skipped when offline. csv <- tryCatch(estban_download(202401, verbose = FALSE), error = function(e) NULL) if (!is.null(csv)) { pe <- estban_read(csv, uf = "PE") nrow(pe) }# Needs network access to www.bcb.gov.br (about 2 MB); skipped when offline. csv <- tryCatch(estban_download(202401, verbose = FALSE), error = function(e) NULL) if (!is.null(csv)) { pe <- estban_read(csv, uf = "PE") nrow(pe) }
Convenience wrapper around estban_download() and estban_read() for a
range of reference months. Months that are not published are skipped
with a warning, so the result may cover fewer months than requested;
check unique(result$ref).
estban_fetch( start, end = start, uf = NULL, level = c("agencia", "municipio"), cache_dir = NULL, clean_names = TRUE, force = FALSE, verbose = TRUE )estban_fetch( start, end = start, uf = NULL, level = c("agencia", "municipio"), cache_dir = NULL, clean_names = TRUE, force = FALSE, verbose = TRUE )
start, end
|
Reference months as |
uf |
Optional character vector of two-letter state codes to keep
(e.g. |
level |
|
cache_dir |
Directory for downloaded files. See |
clean_names |
Logical. Convert column names to |
force |
Logical. Re-download even when the CSV is already cached. |
verbose |
Logical. Emit progress messages (default |
A tibble with all requested months stacked (see estban_read()).
# Needs network access; about 2 MB per month. x <- tryCatch(estban_fetch(202401, 202403, uf = "PE", verbose = FALSE), error = function(e) NULL) if (!is.null(x)) table(x$ref)# Needs network access; about 2 MB per month. x <- tryCatch(estban_fetch(202401, 202403, uf = "PE", verbose = FALSE), error = function(e) NULL) if (!is.null(x)) table(x$ref)
An institution can be present in an ESTBAN file with every account equal to zero in every branch and municipality of the extract. That is not a zero balance sheet: it is a non-report (the bank's return did not make it into that month's file). A documented case is Banco Santander in January to March 2025, zeroed in the whole country. Summing such rows into a municipal total makes credit and deposits collapse for three months and then jump back, which any time-series model reads as a real shock.
estban_flag_nonreport(df)estban_flag_nonreport(df)
df |
A tibble from |
estban_flag_nonreport() adds a logical column nonreport that is
TRUE for every row of an institution-month whose accounts sum to zero
across the whole table. Run it on the largest extract you have (ideally a
state or the country), because the test is "zero everywhere in the
data", and a single municipality can legitimately have a dormant branch.
df with an extra logical column nonreport.
f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) x <- estban_flag_nonreport(x) table(x$nonreport) # A synthetic non-report: zero every account of one bank in one month y <- x bank <- y$cnpj == y$cnpj[[1]] y[bank, grep("^verbete_", names(y))] <- 0 table(estban_flag_nonreport(y)$nonreport, y$cnpj == y$cnpj[[1]])f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) x <- estban_flag_nonreport(x) table(x$nonreport) # A synthetic non-report: zero every account of one bank in one month y <- x bank <- y$cnpj == y$cnpj[[1]] y[bank, grep("^verbete_", names(y))] <- 0 table(estban_flag_nonreport(y)$nonreport, y$cnpj == y$cnpj[[1]])
Treats every institution-month flagged by estban_flag_nonreport() as
missing and fills interior gaps by linear interpolation along the
monthly series of each (institution, municipality, account). Gaps at
the start or end of a series are left as NA (no extrapolation), so a
bank that stopped reporting last month stays missing until the file is
revised, instead of being invented.
estban_impute_nonreport(df)estban_impute_nonreport(df)
df |
A tibble from |
Rows are first summed to one row per institution and municipality (branches of the same bank in the same city are added), because that is the level at which the interpolation is meaningful and stable.
A tibble with one row per cnpj, codmun_ibge and ref, the
identification columns, the account columns (imputed where possible)
and an integer column imputed with the number of accounts filled in
that row. A message reports how many institution-months were treated.
# Three months of a two-bank, one-city extract, with bank B zeroed in the # middle month. See vignette("nonreport-imputation") for the full story. f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") m1 <- estban_read(f, uf = "PE") m2 <- m1; m2$ref <- 202402L m3 <- m1; m3$ref <- 202403L verb <- grep("^verbete_", names(m1)) m2[m2$cnpj == "60746948", verb] <- 0 # Bradesco "vanishes" in February m3[, verb] <- m3[, verb] * 1.10 # and everything grows 10% by March x <- rbind(m1, m2, m3) imp <- estban_impute_nonreport(x) imp[imp$cnpj == "60746948" & imp$municipio == "CARUARU", c("ref", "verbete_160_operacoes_de_credito", "imputed")]# Three months of a two-bank, one-city extract, with bank B zeroed in the # middle month. See vignette("nonreport-imputation") for the full story. f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") m1 <- estban_read(f, uf = "PE") m2 <- m1; m2$ref <- 202402L m3 <- m1; m3$ref <- 202403L verb <- grep("^verbete_", names(m1)) m2[m2$cnpj == "60746948", verb] <- 0 # Bradesco "vanishes" in February m3[, verb] <- m3[, verb] * 1.10 # and everything grows 10% by March x <- rbind(m1, m2, m3) imp <- estban_impute_nonreport(x) imp[imp$cnpj == "60746948" & imp$municipio == "CARUARU", c("ref", "verbete_160_operacoes_de_credito", "imputed")]
Reads a monthly ESTBAN file as published by the Central Bank: two title
lines to skip, ; as separator, Latin-1 encoding, one row per bank
branch (level = "agencia") or per institution and municipality
(level = "municipio"). Account columns (VERBETE_*) are returned as
doubles in Brazilian reais; codes are kept as character to preserve
leading zeros.
estban_read(path, uf = NULL, clean_names = TRUE, ref = NULL)estban_read(path, uf = NULL, clean_names = TRUE, ref = NULL)
path |
Path to a CSV downloaded with |
uf |
Optional character vector of two-letter state codes to keep
(e.g. |
clean_names |
Logical. Convert column names to |
ref |
Optional reference month to record in the |
A tibble with a leading integer column ref (AAAAMM), the
identification columns and one numeric column per account.
# A small real extract shipped with the package (PE and PB, January 2024) f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) x[, 1:8] # Keep one state and the original column names pe <- estban_read(f, uf = "PE", clean_names = FALSE) names(pe)[1:10]# A small real extract shipped with the package (PE and PB, January 2024) f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr") x <- estban_read(f) x[, 1:8] # Keep one state and the original column names pe <- estban_read(f, uf = "PE", clean_names = FALSE) names(pe)[1:10]
The Central Bank has changed the file naming over the years, so for a
given month more than one name may exist. The candidates are tried in
order by estban_download(); the first that answers 200 wins.
estban_url(ref, level = c("agencia", "municipio"))estban_url(ref, level = c("agencia", "municipio"))
ref |
Reference month as |
level |
|
A character vector of URLs, most likely first.
estban_url(202401) estban_url("202401", level = "municipio")estban_url(202401) estban_url("202401", level = "municipio")