library(dplyr)
library(stringr)
library(knitr)
# ---------------------------------------------------------------------------
# CAMINHO DAS BASES DE DADOS <-- ajuste aqui se necessário (veja seção acima)
# ---------------------------------------------------------------------------
pasta_dados <- "../dados"
# Monta o caminho completo de um arquivo dentro da pasta de dados.
# Ex.: caminho_dado("rcl_receita.csv.gz") -> "../dados/rcl_receita.csv.gz"
caminho_dado <- function(arquivo) file.path(pasta_dados, arquivo)
# ---------------------------------------------------------------------------
# Funções auxiliares de leitura e formatação
# ---------------------------------------------------------------------------
# Lê um CSV comprimido (.csv.gz). Marcamos os nomes das colunas como UTF-8
# para que os acentos (ex.: "Categoria Econômica") sejam reconhecidos em
# qualquer sistema operacional.
ler_csv_gz <- function(caminho) {
df <- read.csv(gzfile(caminho), check.names = FALSE, stringsAsFactors = FALSE)
Encoding(names(df)) <- "UTF-8"
df
}
# Seleciona uma coluna pelo NOME. Normaliza acentos, espaços extras e
# caracteres invisíveis (BOM) que costumam vir no cabeçalho exportado — assim
# a leitura é legível e ao mesmo tempo tolerante a variações do arquivo.
# Se o nome não existir, para com mensagem clara em vez de somar a coluna errada.
coluna <- function(dados, nome) {
normalizar <- function(x) {
x <- iconv(x, to = "ASCII//TRANSLIT")
tolower(trimws(gsub("[^A-Za-z0-9]+", " ", x)))
}
i <- match(normalizar(nome), normalizar(names(dados)))
if (is.na(i)) {
stop("Coluna nao encontrada no arquivo: '", nome, "'.\nColunas disponiveis: ",
paste(names(dados), collapse = " | "), call. = FALSE)
}
dados[[i]]
}
# Formata um número grande em "R$ mil" com separador de milhar brasileiro.
# Todos os valores do demonstrativo oficial são expressos em R$ mil, então
# dividimos por 1.000 antes de exibir.
em_mil <- function(reais) {
format(round(reais / 1000), big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
# A "fonte" no Siga Brasil vem com 4 dígitos, mas o código de fonte que
# precisamos comparar tem 3 dígitos (regra de conversão SOF -> Siga).
# Esta função pega sempre os 3 últimos dígitos. Ex.: "1054" -> "054".
fonte_3digitos <- function(x) {
str_sub(str_pad(as.character(x), 4, pad = "0"), -3, -1)
}RREO Anexo 3 - Demonstrativo da Receita Corrente Líquida (RCL)
Material Suplementar - Documento Quarto Executável
Sobre este documento
Este é um documento Quarto executável: o mesmo arquivo que gera o relatório contém o código que produz os resultados. Faz parte de um projeto experimental / piloto de transparência fiscal — uma prova de conceito que demonstra a reprodução de demonstrativos oficiais a partir de dados públicos.
A intenção aqui não é só mostrar que os números batem, mas explicar por que cada valor entra ou sai da conta — de forma que alguém da área de contabilidade, mesmo sem experiência em programação, consiga acompanhar cada passo e reconhecer os critérios do Manual de Demonstrativos Fiscais (MDF-STN).
Para reproduzir os resultados:
O que é a Receita Corrente Líquida (RCL)
A RCL é a “régua” da Lei de Responsabilidade Fiscal. Quase todos os limites fiscais da União (gasto com pessoal, dívida, garantias) são expressos como um percentual da RCL. Por isso, calcular a RCL corretamente é o primeiro passo para verificar qualquer um desses limites.
A ideia central é simples, e cabe em uma frase:
RCL = todas as Receitas Correntes, MENOS algumas deduções previstas em lei.
O trabalho todo está em identificar corretamente quais receitas deduzir. A LRF (art. 2º, IV) manda tirar da conta as receitas que, embora arrecadadas, “não são livres” — porque já têm destino certo (previdência, partilha com estados e municípios, PIS/PASEP etc.). Deduzi-las evita contar como “capacidade de gasto” um dinheiro que na prática já está comprometido.
Este documento calcula a RCL em três blocos, seguindo o próprio demonstrativo oficial:
- Receita Corrente (I) — o ponto de partida (tudo que é corrente)
- Deduções (II) — as parcelas que a lei manda tirar (itens 11 a 15 + transferências constitucionais)
- RCL (III) = (I) − (II)
Fontes de dados
Todos os dados vêm do Siga Brasil (Senado Federal), portal público de acesso livre: https://www12.senado.leg.br/orcamento/sigabrasil
Receitas — rcl_receita.csv.gz
Caminho no portal: Painel de Receitas → Arrecadação → Ano 2025 → exportar em Excel (depois comprimido para .csv.gz).
| Coluna no arquivo | Papel no cálculo |
|---|---|
Categoria Econômica (Cod) Receita |
1 = Corrente, 2 = Capital. Só a Corrente entra na RCL. |
Natureza Receita (Cod) Rec |
Código de 8 dígitos que identifica o que é a receita (ex.: contribuição previdenciária, PIS/PASEP). É o principal critério das deduções. |
Fonte (Cod) Rec |
Identifica a “bolsa” de onde vem o recurso (ex.: fonte da Seguridade, fonte do Servidor). Usada em conjunto com a natureza. |
Arrecadação |
O valor efetivamente arrecadado (é o que somamos). |
Despesas — despesa_unificada.csv.gz
A última dedução (Transferências Constitucionais a estados e municípios) não é uma receita a menos, e sim uma despesa de repasse obrigatório. Por isso ela é medida pelo lado da despesa.
Este demonstrativo usa a mesma base de despesa dos demais — a base unificada do Siga Brasil. Foi verificado que os valores apurados aqui são idênticos, centavo a centavo, aos da extração específica que a RCL usava antes.
| Coluna no arquivo | Papel no cálculo |
|---|---|
Ação (Cod) DESP |
Identifica as ações de transferência (FPE, FPM, IPI-Exportação etc.). |
Programa (Cod) DESP |
Confirma que a ação pertence ao programa de transferências (0903). |
Modalidade Aplicação (Cod) DESP |
30–46 = repasse a outro ente (estado/município). |
Empenhado (R$) |
Valor da transferência. |
RP Cancelado NProc / Proc (R$) |
Restos a Pagar cancelados — precisam ser subtraídos, pois foram empenhados mas nunca serão pagos. |
Onde estão os dados (leia antes de executar)
Este documento lê os arquivos de dados a partir da pasta dados/ do repositório. Como o .qmd está em standalones/, o caminho padrão é ../dados (a pasta dados que fica um nível acima).
Se você renderizar o documento a partir da própria pasta standalones/, não precisa mudar nada. Se os seus arquivos estiverem em outro lugar, basta ajustar uma única linha no bloco de configuração abaixo — a variável pasta_dados. Exemplos:
- Arquivos na mesma pasta do
.qmd:pasta_dados <- "." - Arquivos em
dados/um nível acima (padrão):pasta_dados <- "../dados" - Um caminho completo no seu computador:
pasta_dados <- "C:/Users/voce/Desktop/dados"(use barras normais/, mesmo no Windows)
Configuração inicial
Passo 1 — Receita Corrente (I)
O ponto de partida da RCL é somar toda a receita de categoria econômica “Corrente” (código 1). Nada é filtrado aqui ainda — as exclusões vêm no passo seguinte.
receita <- ler_csv_gz(caminho_dado("rcl_receita.csv.gz"))
# As colunas do arquivo, na ordem em que aparecem, são:
# 1: Categoria Econômica (Cod) 2: Natureza Receita (Cod)
# 3: Fonte (Cod) 4: Arrecadação
receita <- data.frame(
cat_economica = as.integer(coluna(receita, "Categoria Econômica (Cod) Receita")),
natureza = as.character(coluna(receita, "Natureza Receita (Cod) Rec")),
fonte = fonte_3digitos(coluna(receita, "Fonte (Cod) Rec")),
valor = as.numeric(coluna(receita, "Arrecadação")),
stringsAsFactors = FALSE
)
receita <- receita[!is.na(receita$cat_economica), ] # descarta o total geral
# Atalho: soma o "valor" apenas das linhas que satisfazem uma condição.
# Vamos reutilizar muito esta função nas deduções.
somar_se <- function(condicao) sum(receita$valor[condicao], na.rm = TRUE)
# (I) RECEITA CORRENTE = tudo que é categoria econômica 1 (Corrente)
receita_corrente <- somar_se(receita$cat_economica == 1)
cat("Receita Corrente (I): R$", em_mil(receita_corrente), "mil\n")Receita Corrente (I): R$ 2.981.798.817 mil
Passo 2 — As deduções (II)
Agora identificamos, uma a uma, as parcelas que a lei manda tirar da Receita Corrente. Cada subseção abaixo corresponde a uma linha do demonstrativo oficial. Em todas elas, a lógica é a mesma: somar apenas as receitas correntes que se encaixam em um critério específico.
Dedução 12 — Contribuição do Servidor (RPPS)
É a contribuição previdenciária dos servidores públicos federais para o seu próprio regime (RPPS). Identificada pelas fontes do Servidor (055 e 056), mais uma natureza específica de contribuição patronal.
fontes_servidor <- c("055", "056")
deducao_12 <- somar_se(
receita$cat_economica == 1 &
(receita$fonte %in% fontes_servidor | receita$natureza == "12150116")
)
cat("(-) 12 Contribuição Servidor: R$", em_mil(deducao_12), "mil\n")(-) 12 Contribuição Servidor: R$ 18.982.523 mil
Dedução 13 — Compensação Financeira entre Regimes (RGPS/RPPS)
Quando um trabalhador migra entre o regime geral (INSS) e um regime próprio (servidor), há acerto de contas entre os regimes. Esse valor é uma receita que “só passa pelo caixa” — não é capacidade de gasto — e por isso é deduzida. São exatamente as naturezas de compensação que já havíamos separado na dedução 11.
deducao_13 <- somar_se(
receita$cat_economica == 1 &
receita$natureza %in% nat_compensacao_rpps
)
cat("(-) 13 Compensação RGPS/RPPS: R$", em_mil(deducao_13), "mil\n")(-) 13 Compensação RGPS/RPPS: R$ 183.866 mil
Dedução 14 — Contribuição para o Custeio das Pensões Militares
Contribuição específica dos militares para o custeio de suas pensões. Identificada por três “famílias” de natureza de receita, reconhecidas pelos seus dígitos iniciais.
# str_detect com "^" testa se o código COMEÇA com aquele prefixo.
# Ex.: "^1210051" pega qualquer natureza que comece com 1210051.
deducao_14 <- somar_se(
receita$cat_economica == 1 &
str_detect(receita$natureza, "^1210051|^1215041|^121911")
)
cat("(-) 14 Pensões Militares: R$", em_mil(deducao_14), "mil\n")(-) 14 Pensões Militares: R$ 9.569.993 mil
Dedução 15 — Contribuição para o PIS/PASEP
Esta é a dedução mais sutil, porque o PIS/PASEP pode aparecer de duas formas na base, e as duas precisam ser capturadas:
- Pela natureza: receitas cujo código começa com
1210091ou1212são PIS/PASEP — desde que não estejam nas fontes do servidor ou da seguridade (para não invadir as deduções 11 e 12). - Pela fonte: receitas na fonte do PIS/PASEP (
040/041) que, por algum motivo, não tenham aquela natureza — mesmo assim são PIS/PASEP e entram.
É a clássica situação de “A ou B” — se cair em qualquer um dos dois casos, é PIS/PASEP. Foi provavelmente este o critério mais difícil de entender no código original; o objetivo aqui é deixá-lo explícito.
fontes_pis_pasep <- c("040", "041")
# Caso A: tem a NATUREZA de PIS/PASEP e NÃO está nas fontes servidor/seguridade
eh_pis_por_natureza <-
str_detect(receita$natureza, "^1210091|^1212") &
!receita$fonte %in% c(fontes_servidor, fonte_seguridade)
# Caso B: está na FONTE de PIS/PASEP mas NÃO tem a natureza acima
eh_pis_por_fonte <-
!str_detect(receita$natureza, "^1210091|^1212") &
receita$fonte %in% fontes_pis_pasep
deducao_15 <- somar_se(
receita$cat_economica == 1 & (eh_pis_por_natureza | eh_pis_por_fonte)
)
cat("(-) 15 PIS/PASEP: R$", em_mil(deducao_15), "mil\n")(-) 15 PIS/PASEP: R$ 105.896.291 mil
Dedução — Transferências Constitucionais e Legais
Esta é a única dedução medida pelo lado da despesa. São os repasses obrigatórios da União a estados e municípios (FPE, FPM, IPI-Exportação, etc.). Como são despesas de repasse — dinheiro que a União arrecada mas é obrigada a distribuir — reduzem a receita “líquida” disponível.
A conta tem dois cuidados:
- Identificar as ações de transferência (lista de códigos do MDF), confirmando que pertencem ao programa de transferências (
0903) e usam modalidade de repasse a outro ente (30 a 46). Duas ações (0E36e00SB) entram diretamente, sem essas condições. - Subtrair os Restos a Pagar cancelados: valores que foram empenhados em anos anteriores mas cancelados — como nunca serão pagos, não podem contar como transferência.
despesa <- ler_csv_gz(caminho_dado("despesa_unificada.csv.gz"))
despesa <- data.frame(
acao = as.character(coluna(despesa, "Ação (Cod) DESP")),
programa = str_pad(as.character(coluna(despesa, "Programa (Cod) DESP")), 4, pad = "0"),
modalidade = as.character(coluna(despesa, "Modalidade Aplicação (Cod) DESP")),
empenhado = as.numeric(coluna(despesa, "Empenhado (R$)")),
# Soma os dois tipos de Restos a Pagar cancelados numa coluna só
rp_cancelado = as.numeric(coluna(despesa, "RP Cancelado NProc (R$)")) +
as.numeric(coluna(despesa, "RP Proc Cancelado (R$)")),
stringsAsFactors = FALSE
)
# Ações de transferência constitucional/legal (lista do MDF-STN)
acoes_transferencia <- c(
"0044","0045","0046","0050","0051","00H6","006M","00G6","0169","0223",
"0369","0546","0547","0999","099B","0A53","0C03","0C33","0E25","0E36",
"00PX","00QR","00S3","00S7","00S8","00SE","00RX","00UH"
)
modalidades_repasse <- c("30","31","32","35","36","40","41","42","45","46")
# Uma linha de despesa é "transferência" se:
# - é uma ação da lista, no programa 0903, com modalidade de repasse
# OU
# - é uma das duas ações que entram diretamente (0E36, 00SB)
eh_transferencia <-
(despesa$acao %in% acoes_transferencia &
despesa$modalidade %in% modalidades_repasse &
despesa$programa == "0903") |
despesa$acao %in% c("0E36", "00SB")
# Transferência líquida = empenhado - restos a pagar cancelados
transferencias <-
sum(despesa$empenhado[eh_transferencia], na.rm = TRUE) -
sum(despesa$rp_cancelado[eh_transferencia], na.rm = TRUE)
cat("(-) Transferências Constitucionais: R$", em_mil(transferencias), "mil\n")(-) Transferências Constitucionais: R$ 620.657.272 mil
Total das deduções (II)
deducoes <- deducao_11 + deducao_12 + deducao_13 +
deducao_14 + deducao_15 + transferencias
cat("= DEDUÇÕES (II): R$", em_mil(deducoes), "mil\n")= DEDUÇÕES (II): R$ 1.464.063.320 mil
Passo 3 — Receita Corrente Líquida (III)
rcl <- receita_corrente - deducoes
cat("= RCL (III): R$", em_mil(rcl), "mil\n")= RCL (III): R$ 1.517.735.497 mil
Demonstrativo completo e validação
Reunimos todas as linhas no formato do demonstrativo oficial e comparamos com o valor publicado no Diário Oficial (RREO de Dezembro/2025).
demonstrativo <- data.frame(
Item = c(
"Receita Corrente (I)",
"(-) 11 Contribuições Seguridade",
"(-) 12 Contribuição Servidor",
"(-) 13 Compensação RGPS/RPPS",
"(-) 14 Pensões Militares",
"(-) 15 PIS/PASEP",
"(-) Transferências Constitucionais",
"= Deduções (II)",
"= RCL (III)"
),
`R$ mil` = c(
em_mil(receita_corrente),
em_mil(deducao_11), em_mil(deducao_12), em_mil(deducao_13),
em_mil(deducao_14), em_mil(deducao_15), em_mil(transferencias),
em_mil(deducoes), em_mil(rcl)
),
check.names = FALSE
)
kable(demonstrativo, align = c("l", "r"))| Item | R$ mil |
|---|---|
| Receita Corrente (I) | 2.981.798.817 |
| (-) 11 Contribuições Seguridade | 708.773.374 |
| (-) 12 Contribuição Servidor | 18.982.523 |
| (-) 13 Compensação RGPS/RPPS | 183.866 |
| (-) 14 Pensões Militares | 9.569.993 |
| (-) 15 PIS/PASEP | 105.896.291 |
| (-) Transferências Constitucionais | 620.657.272 |
| = Deduções (II) | 1.464.063.320 |
| = RCL (III) | 1.517.735.497 |
rcl_oficial_mil <- 1517735497 # valor publicado no DOU (Dez/2025)
nosso_rcl_mil <- round(rcl / 1000)
diferenca <- nosso_rcl_mil - rcl_oficial_mil
cat("Nossa RCL: R$", format(nosso_rcl_mil, big.mark=".", decimal.mark=","), "mil\n")Nossa RCL: R$ 1.517.735.497 mil
cat("RCL oficial: R$", format(rcl_oficial_mil, big.mark=".", decimal.mark=","), "mil\n")RCL oficial: R$ 1.517.735.497 mil
cat("Diferença: R$", format(diferenca, big.mark=".", decimal.mark=","), "mil\n\n")Diferença: R$ 0 mil
if (diferenca == 0) {
cat("VALIDADO: coincide com o valor publicado no Diário Oficial (R$ mil).\n")
} else {
cat("Diferença encontrada — investigar.\n")
}VALIDADO: coincide com o valor publicado no Diário Oficial (R$ mil).
Conclusão
A RCL de 2025 foi reproduzida a partir de dados exclusivamente públicos do Siga Brasil, seguindo os critérios do Manual de Demonstrativos Fiscais. Cada dedução foi calculada e explicada isoladamente, e o resultado final coincide com o valor oficial publicado no Diário Oficial.
O ponto central para a área de contabilidade: cada número deste demonstrativo pode ser rastreado até uma regra explícita, e cada regra está escrita aqui em linguagem natural ao lado do código que a executa. Qualquer pessoa pode conferir, questionar ou adaptar um critério — que é justamente o que o literate programming busca oferecer à transparência fiscal.