pkgdown/extra.css

Skip to contents

The problem

ESTBAN is assembled by the Central Bank from the monthly returns of each institution. Once in a while a bank’s return does not make it into the file. The bank is still listed, with every branch and every account equal to zero. A documented case is Banco Santander from January to March 2025: three consecutive months at zero in the whole country, then back to normal in April.

This is a non-report, not a zero balance sheet. Summing those rows into a municipal series makes credit and deposits fall by the bank’s share for three months and jump back, and any model fed with the series reads that as a real shock. Re-downloading does not help: the published files are what they are.

Detecting it

estban_flag_nonreport() marks every row of an institution-month whose accounts sum to zero across the whole table. The wider the table, the safer the test: one dormant branch can legitimately have zero everywhere, but a bank with zeros in every city of a state (or of the country) has not reported.

Let us build a three-month series from the extract shipped with the package and make one bank vanish in February:

library(estbanr)

f  <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr")
m1 <- estban_read(f, uf = "PE")
verb <- grep("^verbete_", names(m1))

m2 <- m1; m2$ref <- 202402L; m2[, verb] <- m2[, verb] * 1.05
m3 <- m1; m3$ref <- 202403L; m3[, verb] <- m3[, verb] * 1.10
m2[m2$cnpj == "60746948", verb] <- 0          # Bradesco: nothing in February

x <- rbind(m1, m2, m3)
flagged <- estban_flag_nonreport(x)
unique(flagged[flagged$nonreport, c("nome_instituicao", "ref")])
#> # A tibble: 1 × 2
#>   nome_instituicao     ref
#>   <chr>              <int>
#> 1 BCO BRADESCO S.A. 202402

Fixing it

estban_impute_nonreport() treats the flagged institution-months as missing, collapses branches to one row per institution and municipality, and fills interior gaps by linear interpolation along each (institution, municipality, account) series. Gaps at the start or end of a series are left as NA: a bank that stopped reporting last month stays missing until the file is revised, instead of being invented.

imp <- estban_impute_nonreport(x)
#> ℹ 1 institution-month flagged as non-report; interpolating interior gaps.
v <- "verbete_160_operacoes_de_credito"
imp[imp$cnpj == "60746948" & imp$municipio == "CARUARU", c("ref", v, "imputed")]
#> # A tibble: 3 × 3
#>      ref verbete_160_operacoes_de_credito imputed
#>    <int>                            <dbl>   <int>
#> 1 202401                        23110341        0
#> 2 202402                        24265858.      45
#> 3 202403                        25421375.       0

February is now the midpoint of January and March, and the imputed column says how many accounts were filled in that row (all 45).

Effect on the municipal series

estban_by_municipality() runs the imputation by default. Compare the credit series of Caruaru with and without it:

raw <- estban_by_municipality(x, impute = FALSE)
fix <- estban_by_municipality(x)
#> ℹ 1 institution-month flagged as non-report; interpolating interior gaps.
data.frame(
  ref     = raw$ref[raw$municipio == "CARUARU"],
  raw     = raw[[v]][raw$municipio == "CARUARU"],
  imputed = fix[[v]][fix$municipio == "CARUARU"]
)
#>      ref        raw    imputed
#> 1 202401 3368237459 3368237459
#> 2 202402 3512383474 3536649332
#> 3 202403 3705061205 3705061205

Without the treatment, February is short by the whole credit of the missing bank (here a small share of the city, so the total does not even fall, which is exactly what makes the error hard to spot); with it, February sits between January and March as it should.

When not to impute

  • Short extracts. With a single month there are no neighbours; the flag still works, the interpolation cannot.
  • Genuine exits. A bank that closed all branches in a municipality shows zero from then on. That is an edge gap and is left as NA by design, but if the closure happened between two reported months in your window (it reopened later), the interpolation would bridge it. Look at the imputed column and at nonreport before trusting a long bridge.
  • Balance identities. Interpolated accounts no longer add up exactly to the totals (verbete_399_total_do_ativo, verbete_899_total_do_passivo), because each account is interpolated separately. Recompute totals from components if you need the identity.