Introdução

Este tutorial apresenta um passo a passo para visualizar os valores de honorários advocatícios pagos no âmbito do Poder Executivo Federal, a partir de microdados extraídos do Portal da Transparência (CGU) utilizando o software/linguagem R.

O objetivo é:

O código foi estruturado para ser reprodutível, auditável e adaptável para outros recortes institucionais.


Pacotes utilizados

Começamos carregando os pacotes necessários para manipulação de dados, visualização e apresentação de tabelas.

# Manipulação de dados
library(tidyverse)
library(readr)
library(dplyr)

# Gráficos e tabelas
library(ggplot2)
library(ggrepel)
library(scales)
library(knitr)
library(kableExtra)

Leitura e consolidação dos arquivos de honorários

Os dados de honorários advocatícios constam no Portal da Transparência da Controladoria-Geral da União (CGU) e estão disponíveis no endereço: https://portaldatransparencia.gov.br/download-de-dados/servidores

Para reproduzir os resultados, selecione o Exercício Disponível (no caso dos honorários, de 2018 a 2026), o mês de interesse e o tipo de planilha (Honorarios_Advocaticios), faça o download de cada mês individualmente e coloque todas em uma mesma pasta.

É conveniente definir um filtro por nome de arquivo, usando uma expressão regular como HonorariosAdvocaticios ou outra expressão de preferência, além de definir a extensão do arquivo com \\.csv e a terminação $, que garante que o nome do arquivo termina exatamente em .csv. Com isso, apenas os arquivos corretos são selecionados, mesmo que existam outros CSVs na mesma pasta.

# Caminho da pasta com os arquivos, altere com o seu diretório
pasta_honorarios <- "C:/COINT 2023/Supersalarios/Honorarios"

# Listar arquivos de honorários
arquivos_honorarios <- list.files(
  path = pasta_honorarios,
  pattern = "HonorariosAdvocaticios\\.csv$",
  full.names = TRUE
)

Função de leitura padronizada

Para garantir consistência no tratamento dos dados, definimos uma função que:

  • Lê os arquivos com separador ;
  • Converte corretamente valores monetários
  • Ajusta os tipos das variáveis temporais

A função ler_honorarios() foi criada para padronizar a leitura e o tratamento inicial dos arquivos mensais de honorários advocatícios extraídos do Portal da Transparência.

Ela garante que todos os arquivos: i) sejam lidos corretamente no padrão brasileiro; ii) tenham tipos de variáveis consistentes; iii) estejam prontos para consolidação em uma única base.

A função recebe como argumento o caminho de um arquivo CSV (arquivo) e devolve um data frame já tratado.

ler_honorarios <- function(arquivo) {
  df <- read_delim(
    arquivo,
    delim = ";",
    locale = locale(decimal_mark = ","),
    show_col_types = FALSE,
    col_types = cols(.default = col_character())
  )
  
  df %>%
    mutate(
      across(
        matches("VALOR|HONOR", ignore.case = TRUE),
        ~ as.numeric(str_replace_all(.x, ",", "."))
      ),
      MES = as.integer(MES),
      ANO = as.integer(ANO)
    )
}

A função read_delim() lê arquivos separados por delimitadores personalizados (no caso, ;). O argumento arquivo permite aplicar a função a qualquer arquivo da pasta, mês a mês.

Na segunda metade do bloco acima são definidas os tipos de variáveis. Em particular, para valores monetários são selecionadas automaticamente todas as colunas cujo nome contenha VALOR ou HONOR, substitui a vírgula decimal por ponto (padrão do R) e converte para formato numérico.

Consolidação da base

Com a função definida, lemos os arquivos e empilhamos todos em um único data frame.

honorarios <- arquivos_honorarios %>%
  map_dfr(ler_honorarios)

Seleção de variáveis e tratamento inicial

Mantemos apenas as variáveis essenciais para a análise e criamos um identificador temporal no formato ano_mes.

honorarios <- honorarios %>%
  select(
    ANO, MES, Id_SERVIDOR_PORTAL, VALOR
  ) %>%
  mutate(
    ano_mes = sprintf("%d%02d", ANO, MES)
  )

Observações sem identificador

Alguns registros não possuem identificação de servidor. Avaliamos a magnitude desses valores antes de excluí-los da análise principal. Primeiro, uma contagem do número de observações sem ID e , em seguida, a soma do valor em R$ do total sem identificação ao longo de toda série.

# Número de registros sem ID
sum(is.na(honorarios$Id_SERVIDOR_PORTAL))
## [1] 1603
# Valor total não identificado
honorarios %>%
  filter(is.na(Id_SERVIDOR_PORTAL)) %>%
  summarise(total_na = sum(VALOR, na.rm = TRUE))
## # A tibble: 1 × 1
##   total_na
##      <dbl>
## 1 4378392.

Após essa verificação, removemos esses registros para garantir consistência nas agregações por servidor, guardando as observações sem ID em um dataframe separado.

# Excluindo
honorarios <- honorarios %>%
  filter(!is.na(Id_SERVIDOR_PORTAL))

# Separando NAs
honorarios_sem_id <- honorarios %>%
  filter(is.na(Id_SERVIDOR_PORTAL))

Consolidação mensal por servidor

Um mesmo servidor pode aparecer mais de uma vez no mesmo ano-mês, com diferentes valores a receber. Para evitar dupla contagem, agregamos esses valores mensalmente a nível individual.

honorarios_mensal <- honorarios %>%
  group_by(
    Id_SERVIDOR_PORTAL,
    ANO,
    MES,
    ano_mes
  ) %>%
  summarise(
    VALOR_HONORARIOS = sum(VALOR, na.rm = TRUE),
    .groups = "drop"
  )

A seguir, podemos verificar a unicidade de id/ano_mes com um filtro simples. Para cada combinação de ID e ano-mês, vamos filtrar as observações maiores que 1. Portanto, se o filtro gerar um tibble sem linhas, temos apenas 1 de cada.

honorarios_mensal %>%
  count(Id_SERVIDOR_PORTAL, ano_mes) %>%
  filter(n > 1)
## # A tibble: 0 × 3
## # ℹ 3 variables: Id_SERVIDOR_PORTAL <chr>, ano_mes <chr>, n <int>

Agregações mensais

Agora vamos transformar o microdado original em séries de tempo, criando as variáveis de:

Adicionalmente, também vamos criar uma variável de data, para maior conveniência no trabalho com séries de tempo.

honorarios_evolucao <- honorarios_mensal %>%
  group_by(ano_mes) %>%
  summarise(
    total_honorarios = sum(VALOR_HONORARIOS, na.rm = TRUE),
    servidores = n_distinct(Id_SERVIDOR_PORTAL),
    media_por_servidor = total_honorarios / servidores,
    .groups = "drop"
  ) %>%
  mutate(
    ano_mes_date = as.Date(paste0(ano_mes, "01"), format = "%Y%m%d")
  )

Evolução do valor total de honorários

Indicadores simples

O bloco a seguir calcula crescimento mensal da série computando a variação percentual mensal. Depois computa-se a média dessa variação percentual e o total de honorários pagos durante todo o período da série. Essas informações erão incluídas no gráfico seguinte.

dados_crescimento <- honorarios_evolucao %>%
  arrange(ano_mes_date) %>%
  mutate(
    crescimento_mensal = total_honorarios / lag(total_honorarios) - 1
  ) %>%
  filter(!is.na(crescimento_mensal))

g_mensal <- mean(dados_crescimento$crescimento_mensal, na.rm = TRUE)
total_periodo <- sum(honorarios_evolucao$total_honorarios, na.rm = TRUE)

Série completa

O bloco a seguir traz o gráfico do total mensal pago em honorários advocatícios, incluindo as informações calculadas anteriormente no canto superior esquerdo da imagem.

texto_anotacao <- paste0(
  "Total gasto no período: R$ ",
  label_number(big.mark = ".", decimal.mark = ",", scale = 1e-9, suffix = " bi")(total_periodo),
  "\nCrescimento médio mensal: ",
  percent(g_mensal, accuracy = 0.1)
)

ggplot(honorarios_evolucao,
       aes(x = ano_mes_date, y = total_honorarios)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  scale_y_continuous(
    labels = label_number(
      big.mark = ".", decimal.mark = ",", scale = 1e-6, suffix = " mi"
    )
  ) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m") +
  labs(
    title = "Total mensal pago em honorários advocatícios - dez/2017 a dez/2025",
    subtitle = "Poder Executivo — valores nominais",
    x = "Ano-mês",
    y = "Total mensal (R$ milhões)",
    caption = "Fonte: Portal da Transparência (CGU)"
  ) +
  annotate(
    "text",
    x = min(honorarios_evolucao$ano_mes_date),
    y = max(honorarios_evolucao$total_honorarios),
    label = texto_anotacao,
    hjust = 0,
    vjust = 1,
    size = 3.5
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


Note que os picos nos meses de dez/2024 e jun/2025 atrapalham muito a visualização do gráfico pois altera a escala do eixo vertical. Para contornar isso, podemos plotar a série apenas até o período de nov/2024 para avaliar melhor a parte inicial dos dados.

# Gráfico 2 — Total mensal (dez/2017 a nov/2024), antes dos grandes picos

# Separando período inicial
honorarios_total_pre_pico <- honorarios_evolucao %>%
  filter(ano_mes_date <= as.Date("2024-11-01"))

# Definindo rótulo inicial
rotulo_inicial <- honorarios_total_pre_pico %>%
  arrange(ano_mes_date) %>%
  slice(1) %>%
  mutate(
    label = scales::label_number(
      big.mark = ".", decimal.mark = ",",
      scale = 1e-6, suffix = " mi"
    )(total_honorarios)
  )

ggplot(honorarios_total_pre_pico,
       aes(x = ano_mes_date, y = total_honorarios)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  
  # Rótulo apenas no primeiro mês
  geom_text_repel(
    data = rotulo_inicial,
    aes(label = label),
    size = 3.5,
    fontface = "bold",
    nudge_y = max(honorarios_total_pre_pico$total_honorarios) * 0.05,
    direction = "y",
    segment.size = 0.4
  ) +
  
  scale_y_continuous(
    labels = scales::label_number(
      big.mark = ".", decimal.mark = ",",
      scale = 1e-6, suffix = " mi"
    )
  ) +
  scale_x_date(
    date_breaks = "3 months",
    date_labels = "%Y-%m"
  ) +
  labs(
    title = "Total mensal pago em honorários advocatícios",
    subtitle = "Período inicial da série (dez/2017–nov/2024)",
    x = "Ano-mês",
    y = "Total mensal (R$ milhões)",
    caption = "Fonte: Portal da Transparência (CGU)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )


Em vez de separar apenas o período inicial da série, também podemos colocar rótulo de valores nos 6 valores mais altos e no valor mais baixo, o que facilita a visualização.

# Gráfico 3 - Incluir rótulo de dados nos 5 maiores valores e no menor

# Identificando pontos
rotulos_extremos <- honorarios_evolucao %>%
  arrange(desc(total_honorarios)) %>%
  slice_head(n = 7) %>%
  bind_rows(
    honorarios_evolucao %>%
      arrange(total_honorarios) %>%
      slice_head(n = 1)
  ) %>%
  distinct(ano_mes_date, .keep_all = TRUE)

# Alterando o limite do eixo y
 limite_y <- max(honorarios_evolucao$total_honorarios, na.rm = TRUE) * 1.15

# Gráfico
ggplot(honorarios_evolucao,
       aes(x = ano_mes_date, y = total_honorarios)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  
  # Rótulos apenas nos extremos
  geom_text_repel(
    data = rotulos_extremos,
    aes(label = scales::label_number(
      big.mark = ".", decimal.mark = ",",
      scale = 1e-6, suffix = " mi"
    )(total_honorarios)),
    size = 3.5,
    fontface = "bold",
    segment.size = 0.4,
    min.segment.length = 0,
    nudge_y = limite_y * 0.02,
    direction = "y"
  ) +
  
  scale_y_continuous(
    limits = c(0, limite_y),
    breaks = scales::pretty_breaks(n = 7),
    labels = scales::label_number(
      big.mark = ".", decimal.mark = ",",
      scale = 1e-6, suffix = " mi"
    ),
    expand = expansion(mult = c(0, 0))
  ) +
  scale_x_date(
    date_breaks = "3 months",
    date_labels = "%Y-%m"
  ) +
  labs(
    title = "Total mensal pago em honorários advocatícios - dez/2017 a dez/2025",
    subtitle = "Poder Executivo — valores nominais",
    x = "Ano-mês",
    y = "Total mensal (R$ milhões)",
    caption = "Fonte: Portal da Transparência (CGU)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Evolução do valor médio por servidor

Por fim, analisamos a trajetória do valor médio mensal de honorários pagos por servidor. Note que, como o número de servidores permanece relativamente estável no período, o padrão da série é semelhante ao padrão da série de valor total mensal, também com picos em jun/2025 e dez/2024 que atrapalham a visualização da série. Por isso, vamos colocar rótulo de dados em algumas observações ao longo de toda série para melhorar a visualização.

Queremos rotular apenas os picos locais. Assim, para cada mês, o código verifica se o valor médio é maior que o mês anterior e maior que o mês seguinte. Se sim, então é um pico local.

honorarios_rotulos <- honorarios_evolucao %>%
  arrange(ano_mes_date) %>%
  mutate(
    pico = media_por_servidor > lag(media_por_servidor) &
      media_por_servidor > lead(media_por_servidor)
  ) %>%
  filter(pico | row_number() == 1)

ggplot(honorarios_evolucao, aes(x = ano_mes_date, y = media_por_servidor)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  geom_text_repel(
    data = honorarios_rotulos,
    aes(label = label_number(big.mark = ".", decimal.mark = ",")(media_por_servidor)),
    size = 3.5,
    fontface = "bold",
    segment.size = 0.4
  ) +
  scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m") +
  labs(
    title = "Evolução do valor médio de honorários por servidor",
    subtitle = "Série completa - dez/2017 a dez/2025",
    x = "Ano-mês",
    y = "Valor médio por servidor (R$)",
    caption = "Fonte: Portal da Transparência (CGU)"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


Tabela: Top 10 Maiores Valores

Podemos também fazer uma tabela para visualizar os dados disponíveis nos 10 meses em que foram distribuídos mais honorários aos servidores.

# Criando tabela
top_10_meses <- honorarios_evolucao %>%
  arrange(desc(total_honorarios)) %>%
  slice_head(n = 10) %>%
  mutate(
    `Ano-mês` = format(ano_mes_date, "%Y-%m"),
    `Total mensal (R$ milhões)` = scales::number(
      total_honorarios / 1e6,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 0.01
    ),
    `Média por servidor (R$)` = scales::number(
      media_por_servidor,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 0.01
    ),
    Servidores = scales::number(
      servidores,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 1
    )
  ) %>%
  select(
    `Ano-mês`,
    `Total mensal (R$ milhões)`,
    Servidores,
    `Média por servidor (R$)`
  )


# Formatação da tabela
kable(
  top_10_meses,
  format = "html",
  caption = "Top 10 meses com maior gasto em honorários advocatícios – Poder Executivo",
  align = c("c", "r", "r", "r"),
  escape = FALSE
) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
  column_spec(2, bold = TRUE) %>%
  row_spec(0, bold = TRUE) %>%
  footnote(
    general = "Fonte: Portal da Transparência (CGU)",
    general_title = "",
    footnote_as_chunk = TRUE,
    escape = FALSE
  )
Top 10 meses com maior gasto em honorários advocatícios – Poder Executivo
Ano-mês Total mensal (R$ milhões) Servidores Média por servidor (R$)
2025-06 2.342,48 12.189 192.180,03
2024-12 1.680,77 12.805 131.258,51
2025-10 331,59 12.202 27.175,45
2024-10 311,12 12.153 25.600,52
2023-10 273,32 11.719 23.322,65
2024-03 242,11 11.761 20.585,78
2022-10 223,58 11.889 18.805,89
2025-04 212,79 12.186 17.461,69
2025-01 209,34 12.141 17.242,10
2025-02 201,03 12.144 16.553,88
Fonte: Portal da Transparência (CGU)

Por fim, podemos incluir ainda a tabela com a série completa de microdados agregados em ordem cronológica.

# Tabela Completa - Dados mensais

# Criando tabela – Série completa (todos os meses)
tabela_meses_completa <- honorarios_evolucao %>%
  arrange(ano_mes_date) %>%
  mutate(
    `Ano-mês` = format(ano_mes_date, "%Y-%m"),
    `Total mensal (R$ milhões)` = scales::number(
      total_honorarios / 1e6,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 0.01
    ),
    `Média por servidor (R$)` = scales::number(
      media_por_servidor,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 0.01
    ),
    Servidores = scales::number(
      servidores,
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 1
    )
  ) %>%
  select(
    `Ano-mês`,
    `Total mensal (R$ milhões)`,
    Servidores,
    `Média por servidor (R$)`
  )

# Formatação
kable(
  tabela_meses_completa,
  format = "html",
  caption = "Gasto mensal com honorários advocatícios – Poder Executivo (série completa)",
  align = c("c", "r", "r", "r"),
  escape = FALSE
) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
  column_spec(2, bold = TRUE) %>%
  row_spec(0, bold = TRUE) %>%
  footnote(
    general = "Fonte: Portal da Transparência (CGU)",
    general_title = "",
    footnote_as_chunk = TRUE,
    escape = FALSE
  )
Gasto mensal com honorários advocatícios – Poder Executivo (série completa)
Ano-mês Total mensal (R$ milhões) Servidores Média por servidor (R$)
2017-12 59,11 12.138 4.869,45
2018-01 65,60 12.273 5.345,09
2018-02 62,44 12.429 5.023,66
2018-03 64,19 12.445 5.157,89
2018-04 62,45 12.447 5.017,45
2018-05 61,31 12.438 4.929,22
2018-06 66,24 12.431 5.328,93
2018-07 68,09 12.442 5.472,20
2018-08 68,73 12.454 5.519,04
2018-09 72,84 12.439 5.855,82
2018-10 71,00 12.453 5.701,33
2018-11 71,00 12.452 5.701,64
2018-12 76,92 12.440 6.183,20
2019-01 72,95 12.494 5.838,84
2019-02 72,40 12.501 5.791,69
2019-03 69,44 12.440 5.581,62
2019-04 74,58 12.475 5.978,35
2019-05 74,91 12.468 6.008,11
2019-06 72,99 12.457 5.859,22
2019-07 77,64 12.440 6.241,20
2019-08 78,39 12.433 6.304,64
2019-09 78,23 12.438 6.289,48
2019-10 78,18 12.427 6.290,95
2019-11 78,25 12.423 6.298,49
2019-12 78,49 12.414 6.322,59
2020-01 78,49 12.411 6.324,60
2020-02 78,67 12.395 6.346,85
2020-03 66,96 12.387 5.405,93
2020-04 64,26 12.369 5.195,14
2020-05 74,38 12.341 6.026,99
2020-06 77,66 12.323 6.302,15
2020-07 86,46 12.310 7.023,28
2020-08 80,16 12.302 6.515,77
2020-09 81,12 12.284 6.603,69
2020-10 89,20 12.271 7.269,49
2020-11 89,33 12.257 7.288,30
2020-12 104,12 12.254 8.496,73
2021-01 95,34 12.237 7.791,13
2021-02 95,73 12.215 7.837,13
2021-03 98,65 12.202 8.085,12
2021-04 98,55 12.182 8.089,86
2021-05 96,75 12.164 7.953,54
2021-06 98,46 12.143 8.108,45
2021-07 102,99 12.121 8.496,43
2021-08 105,30 12.100 8.702,07
2021-09 107,91 12.087 8.927,74
2021-10 107,53 12.063 8.914,05
2021-11 111,45 12.051 9.248,61
2021-12 112,88 12.038 9.377,16
2022-01 111,69 12.016 9.295,13
2022-02 110,55 12.015 9.200,67
2022-03 111,59 11.986 9.309,92
2022-04 110,46 11.971 9.227,70
2022-05 112,47 11.966 9.398,98
2022-06 111,92 11.929 9.382,37
2022-07 111,49 11.919 9.354,22
2022-08 111,87 11.904 9.397,48
2022-09 112,93 11.889 9.499,01
2022-10 223,58 11.889 18.805,89
2022-11 112,76 11.877 9.493,73
2022-12 119,68 11.870 10.082,52
2023-01 119,38 11.854 10.070,72
2023-02 119,24 11.839 10.072,06
2023-03 140,35 11.824 11.869,53
2023-04 119,50 11.807 10.120,76
2023-05 119,28 11.793 10.114,09
2023-06 119,26 11.784 10.120,66
2023-07 122,33 11.765 10.397,64
2023-08 126,63 11.743 10.783,30
2023-09 155,05 11.727 13.221,58
2023-10 273,32 11.719 23.322,65
2023-11 156,02 11.703 13.331,93
2023-12 165,53 11.694 14.155,02
2024-01 159,46 11.765 13.553,36
2024-02 165,11 11.758 14.042,42
2024-03 242,11 11.761 20.585,78
2024-04 166,40 11.741 14.172,95
2024-05 147,56 11.727 12.583,23
2024-06 146,61 11.713 12.517,04
2024-07 146,08 11.697 12.488,40
2024-08 143,03 11.669 12.257,23
2024-09 161,09 11.656 13.820,73
2024-10 311,12 12.153 25.600,52
2024-11 185,67 12.168 15.258,67
2024-12 1.680,77 12.805 131.258,51
2025-01 209,34 12.141 17.242,10
2025-02 201,03 12.144 16.553,88
2025-03 200,08 12.185 16.420,41
2025-04 212,79 12.186 17.461,69
2025-05 187,18 12.164 15.388,00
2025-06 2.342,48 12.189 192.180,03
2025-07 193,42 12.147 15.923,53
2025-08 194,23 12.139 16.000,78
2025-09 191,89 12.119 15.833,42
2025-10 331,59 12.202 27.175,45
2025-11 196,58 12.193 16.122,27
2025-12 190,95 12.175 15.683,50
Fonte: Portal da Transparência (CGU)