Hackeando o R: gerando gráficos de modo interativo com o esquisse

By | Hackeando o R

No Hackeando o R de hoje, vamos apresentar o pacote esquisse, que facilita a geração de gráficos interativos no R. A principal funcionalidade do pacote é o add-in que ele adiciona ao R, que permite gerar gráficos de modo intuitivo e sem olhar diretamente para o código, sendo uma boa ferramenta para trabalhos rápidos. Após instalar o pacote, podemos acessar suas ferramentas no RStudio:

Vamos então carregar alguns dados para trabalhar dentro da ferramenta. Para o exemplo, utilizaremos 4 das principais variáveis reportadas pelo Boletim FOCUS.

library(rbcb)
library(tidyverse)

dados = get_annual_market_expectations(c('PIB Total', 'IPCA', 
'Taxa de câmbio', 
'Meta para taxa over-selic'
),
start_date = '2019-01-01') %>%
replace_na(replace = list(indic_detail = 'Média'))

dados$indic = ifelse(dados$indic == 'Taxa de câmbio', 'Taxa de Câmbio', 
dados$indic)

dados = dados %>% filter(reference_year == '2021' & base == 0 & 
indic_detail %in% c('Média', 'Fim do ano') & 
indic %in% c('IPCA', 'Meta para taxa over-selic',
'PIB Total', 'Taxa de Câmbio') & 
date > '2020-06-01')

Ao abrir o add-in, iremos selecionar os dados a serem utilizados:

Dentro da ferramenta, teremos então todas as colunas do dataframe, e diversas opções do ggplot2. Abaixo, colocamos a data no eixo x, a expectativa média no eixo y, e separamos os dados pela variável. É importante notar que os dados já foram transformados no formato tall, como fazemos em gráficos de múltiplas linhas normalmente.

Podemos personalizar diversas configurações, como adicionar título, mudar coordenadas, e alterar o layout. Após isso, podemos salvar o gráfico localmente. Outra opção é salvá-lo diretamente em um slide de PowerPoint. Isso pode ser feito tanto diretamente no add-in, como para objetos do tipo ggplot que você já possui localmente.



Explicando o juro neutro da economia brasileira

By | Comentário de Conjuntura

No Comentário de Conjuntura da semana passada, falei sobre os dilemas aos quais está submetido o Banco Central. A inflação tem se mostrado mais resistente do que o inicialmente diagnosticado pela autoridade monetária, o que exigiu uma mudança na comunicação. Sai a tal normalização parcial para uma normalização até o juro neutro. E aqui, temos uma questão bastante relevante: o juro neutro da economia é uma variável não observável, que deve ser estimada. Mais do que isso, quais seriam as variáveis que afetam o juro de equilíbrio? Nesse Comentário de Conjuntura apresentamos um modelo explicativo para o juro de equilíbrio da economia brasileira.

O juro neutro é aquele que equilibra poupança e investimento em uma economia com `hiato do produto` nulo e inflação igual à meta. Em uma pequena economia aberta sem restrições a mobilidade de capital e com ativos substitutos, a taxa de juros doméstica é igual a taxa internacional. Quando não é o caso, deve-se adicionar à taxa de juros internacional (r_t^{*}), o risco país (\gamma_t) e o risco cambial (\tau_t), de modo que:

(1)   \begin{align*} \bar{r_t} = r_t^{*} + \gamma_t + \tau_t  \end{align*}

Com base em 1, procuramos estimar um modelo descritivo para a taxa de juros de equilíbrio da economia brasileira. Para isso, vamos estimar o seguinte modelo:

(2)   \begin{align*} \bar{r_t} = \beta_0 + \beta_1 r_t^{*} + \beta_2 \gamma_t + \beta_3 \tau_t + \beta_4 D_{Teto} + \varepsilon_t,  \end{align*}

onde D_{Teto} é uma *dummy* que assume 1 a partir de dezembro de 2016 e 0 nos meses anteriores da amostra. \varepsilon_t é supostamente um *ruído branco*. Para estimar 2, vamos utilizar uma amostra entre janeiro de 2004 e maio de 2021, totalizando 209 observações. Vamos considerar como *proxy* para o juro neutro, o juro estrutural implícito nas expectativas do boletim Focus. O juro internacional será representado pela taxa de juros efetiva praticada nos Estados Unidos (**fed funds**), para o risco país vamos considerar o EMBI e para o risco cambial vamos considerar o **cupom cambial**, que leva em consideração a expectativa de desvalorização/valorização cambial dos agentes. Ademais, para estimar 2, vamos considerar o método de mínimos quadrados ordinários (OLS), mínimos quadrados em dois estágios (TSLS) e o método dos momentos generalizado (GMM).^[Os instrumentos utilizados são as quatro defasagens de cada uma das variáveis utilizadas.] O restante desse Comentário cuida da coleta/tratamento dos dados, bem como da construção dos modelos.

(*) Aprenda a fazer esse tipo de análise através dos nossos Cursos Aplicados de R.

A tabela a seguir resume a estimação do modelo pelos três métodos descritos acima. À exceção do risco cambial, todas as demais variáveis se mostraram estatisticamente significativa para explicar o juro de equilíbrio. Em particular, o modelo sugere que o risco país é relevante para explicar o juro neutro. Assim, quanto maior for a instabilidade do ambiente político econômico, maior será o risco país e, portanto, maior será o juro de equilíbrio da economia.

Explicando o juro neutro da economia brasileira
Variável Dependente: Juro Neutro
OLS TSLS GMM
(1) (2) (3)
Intercepto 3.11*** (0.19) 2.98*** (0.24) 3.64*** (0.45)
Juro Internacional 0.39*** (0.03) 0.39*** (0.04) 0.20* (0.10)
Risco País 0.01*** (0.001) 0.01*** (0.001) 0.005*** (0.001)
Risco Cambial 0.01 (0.01) 0.01 (0.02) 0.01 (0.01)
DTeto -1.89*** (0.13) -1.89*** (0.13) -1.29*** (0.25)
J-Test 14.04
J-Test (p-valor) 0.12
Observations 209 205 205
R2 0.73 0.72
Adjusted R2 0.72 0.71
Residual Std. Error 0.78 (df = 204) 0.78 (df = 200)
F Statistic 136.11*** (df = 4; 204) 128.73*** (df = 4; 200)
Nota: *p<0.1; **p<0.05; ***p<0.01

Outro resultado interessante que o modelo estimado sugere é que a dummy que representa o teto de gastos se mostrou igualmente relevante para explicar o juro de equilíbrio da economia.
____________________

(*) Para quem quiser ter acesso a todos os códigos desse e de todos os exercícios que publicamos ao longo da semana, visite o Clube AM.

Relatório AM #6 - Núcleos de inflação

By | Indicadores

Ao longo das últimas semanas, temos dado ênfase aqui no Relatório AM à discussão da inflação no cenário nacional. Na semana passada, a reunião do COPOM confirmou aquilo que esperávamos, com aumento da taxa básica de juros para 4.25% e nenhuma menção à normalização parcial. Isso é resultado da persistência da trajetória da inflação, de modo que seu nível atual não pode ser atribuído somente a choques. Para elucidar isso, vamos falar mais a fundo sobre como têm se comportados os núcleos da inflação nos últimos meses.

O monitoramento dos preços da economia através de núcleos de inflação é uma prática muito comum atualmente, pois facilita o isolamento dos fenômenos reais (os choques) e dá maior transparência para as decisões da política monetária, facilitando a convergência das expectativas no regime de metas de inflação. No Brasil, temos 7 núcleos: 4 de exclusão (IPCA-EX0, 1, 2 e 3), 2 de médias aparadas (MA e MS), e o núcleo de dupla ponderação (DP). Observando os resultados de cada núcleo separadamente, verificamos que o resultado geral da inflação não pode ser atribuído a setores específicos da economia, e não é resultado de choques em itens específicos de alta volatilidade:

Outra maneira de analisar o comportamento da inflação é através do índice de difusão. Esse valor é simplesmente o percentual de itens do IPCA que teve variação positiva nos seus preços no período. Como cada item possui o mesmo peso, valores altos do índice indicam que o aumento dos níveis de preços é realmente generalizado, configurando a inflação por definição, e sem a possibilidade de influência de choques exacerbados em itens específicos sobre o valor final. Abaixo, podemos ver que ao longo de 2020 o índice teve grande aumento, com a média móvel se mantendo em trajetória crescente até as últimas observações:

Análise das Atas do COPOM com text mining

By | Data Science, Política Monetária

Introdução

Mineração de texto, ou text mining, é um tópico muito interessante, pois há um potencial enorme de aplicações para obtenção de insights através dessa técnica envolvendo análise textual. Com a finalidade de demonstrar seu uso, neste post faremos uma breve e introdutória análise das atas do Comitê de Política Monetária - COPOM usando text mining com o auxílio do pacote tidytext.

As atas do COPOM são um caminho natural para qualquer economista em busca de uma fonte de dados para exercitar o text mining, já que a autoridade monetária realiza ajustes (mudanças) no texto a cada reunião, realizada a cada 45 dias. As atas são disponibilizadas publicamente neste link em arquivos PDFs (atualmente há 238 reuniões realizadas). Inicialmente vamos pegar o arquivo da última reunião publicada e importar os dados para o R, fazendo tratamentos e posterior análise. Por fim, vamos coletar os dados de todo o histórico de atas para refazer a análise de forma a incorporar o componente temporal.

Um ponto importante é que utilizaremos as versões em inglês das atas, apesar de o COPOM disponibilizar também em português. Isso se deve ao fato de que as ferramentas aqui utilizadas, para aplicar a técnica de text mining, funcionarem melhor com textos na língua inglesa.

Pacotes

Os pacotes utilizados neste exercício podem ser instalados/carregados com o gerenciador pacman, todos provenientes do CRAN:


# Instalar/carregar pacotes
if(!require("pacman")) install.packages("pacman")
pacman::p_load(
"tidytext",
"pdftools",
"stopwords",
"textdata",
"dplyr",
"tidyr",
"lubridate",
"magrittr",
"knitr",
"ggplot2",
"ggthemes",
"jsonlite",
"purrr",
"stringr",
"scales",
"forcats"
)

Text mining de uma ata do COPOM

Vamos importar a última ata do COPOM para o R. Primeiro criamos um objeto para armazenar o link para o arquivo e, na sequência, usamos a função pdf_text do pacote pdftools para ler cada página do arquivo PDF e transformar os dados em um vetor de caracteres de tamanho igual ao número de páginas.

# URL da última ata do COPOM
www <- "https://www.bcb.gov.br/content/copom/copomminutes/MINUTES%20238.pdf"
# Ler arquivo PDF convertendo para caracter
raw_copom_last <- pdftools::pdf_text(www)

Tratamento de dados

Um primeiro olhar sobre os dados mostrará que há uma série de caracteres especiais "\n" e "\r" que indicam quebras de linhas. Portanto, vamos tratar de forma a obter um objeto tibble com uma coluna (text) com os dados do texto de cada página da ata, outra coluna (meeting) indicando o mês da reunião e a última coluna (page) que informará a página referente ao texto.

# Tratamento de dados
copom_last_clean <- dplyr::tibble(
text = unlist(strsplit(raw_copom_last, "\r"))
) %>% 
dplyr::mutate(
meeting = "May 2021", 
page = dplyr::row_number(),
text = gsub("\n", "", text)
)

Text mining

Agora estamos com os dados quase prontos para uma análise! O que faremos agora é começar a aplicar algumas das técnicas de text mining provenientes do livro Text Mining with R escrito pela Julia Silge e David Robinson.

O primeiro passo é "tokenizar" nossos dados, de forma a obter "unidades do texto" que servirão para a análise. Isso facilitará para realizarmos a contagem de palavras frequentes, filtrar palavras em específico, etc. O processo de "tokenizar" é definido no livro como:

"A token is a meaningful unit of text, most often a word, that we are interested in using for further analysis, and tokenization is the process of splitting text into tokens."

Para utilizar a técnica, usamos a função unnest_tokens do pacote tidytext e na sequência realizamos a contagem das palavras encontradas:

# Text mining - Criar tokens
copom_last <- copom_last_clean %>% 
tidytext::unnest_tokens(word, text)
# Contar palavras
copom_last %>%
dplyr::count(word, sort = TRUE) %>% 
dplyr::slice_head(n = 6) %>% 
knitr::kable()


Como podemos observar, as palavras mais frequentes são palavras comuns como "the", "of", "in", etc. que não servirão muito para nossa análise. Essas palavras são chamadas de "stop words" no mundo do text mining. Vamos fazer uma tratativa para remover essas palavras usando como base o objeto stop_words proveniente do pacote tidytext e, antes, removemos também números que foram apontados como "palavras":

copom_last_sw <- copom_last %>%
# Remover palavras comuns (stop words)
dplyr::anti_join(stop_words)%>%
# Remover números
dplyr::mutate(word = gsub("[^A-Za-z ]", "", word)) %>%
# Contar palavras
dplyr::count(word, sort = TRUE) %>% 
dplyr::filter(word != "")
copom_last_sw %>% 
dplyr::slice_head(n = 6) %>% 
knitr::kable()

Agora sim temos os dados prontos para uma análise de sentimento!

Análise de sentimento

Nosso foco agora é usar ferramentas de análise para tirar informação desses dados, ou seja, queremos saber o que as palavras das atas do COPOM podem indicar com base na tentativa de apontarmos um "score" para cada uma delas, usando datasets e bibliotecas de "sentimento do texto" do tidytext para isso.

Vamos ver quais são as palavras negativas e positivas usadas com mais frequência. A função get_sentiments do tidytext fará isso pra gente, bastando apontar um lexicon, que pode ser "bing", "afinn", "loughran" ou "nrc".

# Obter análise de sentimento das palavras com base em uma biblioteca
copom_last_sw %>%
dplyr::inner_join(tidytext::get_sentiments("bing")) %>% 
dplyr::slice_head(n = 10) %>% 
knitr::kable()

Como resultado, "risks" é a palavra negativa que aparece mais vezes (13 no total) nessa ata do COPOM, e "recovery", uma palavra positiva, é usada 4 vezes no total. Um segundo olhar sobre esse resultado pode levantar uma suspeita, pois "recovery" é apontada como uma palavra positiva (recuperação), no entanto, é razoável supor que pode estar também associada com uma situação anterior negativa. Isso é um possível problema da análise que o leitor pode investigar.
Agora vamos explorar a análise graficamente:

# Análise de sentimento final da ata de Maio/2021
copom_sentiment <- copom_last %>%
dplyr::inner_join(tidytext::get_sentiments("bing")) %>%
dplyr::count(meeting, page, sentiment) %>%
tidyr::pivot_wider(
id_cols = c(meeting, page),
names_from = sentiment, 
values_from = n,
values_fill = 0
) %>%
dplyr::mutate(sentiment = positive - negative)
# Gerar gráfico
copom_sentiment %>% 
ggplot2::ggplot(ggplot2::aes(page, sentiment, fill = sentiment > 0)) +
ggplot2::geom_col(show.legend = FALSE) +
ggplot2::scale_fill_manual(values = c("#b22200", "#282f6b")) +
ggplot2::labs(
x = "Página da ata",
y = "Sentimento",
title = "Análise de sentimento da Ata do COPOM - Maio/2021",
subtitle = "Bing lexicon",
caption = paste0("Elaboração: analisemacro.com.br\nDados: ", www)
)

O gráfico conta uma história interessante. O texto começou negativo na página 3 (sobre atualização de conjuntura, cenário e riscos), mas depois foi "neutro" na página 4 (sentimento positivo - negativo = 0) - onde é discutido a condução da política monetária e -, por fim, na última página o texto fica positivo com a decisão da reunião do COPOM.

Vale enfatizar que a primeira página, referente a capa, não é considerada na análise. Já a página 2, da contracapa, possui igual número de palavras negativas e positivas.

Text mining com todas as atas do COPOM

Agora vamos aplicar a técnica apresentada acima para um conjunto maior de dados, desta vez vamos pegar todas as atas disponíveis no site do Banco Central do Brasil - BCB através deste link.

Vamos expandir nossa análise capturando o texto de cada Ata do COPOM desde sua 42ª reunião, totalizando 198 atas para nossa análise. Faremos a comparação da frequência relativa de palavras e tópicos e veremos como o sentimento (conforme explorado acima) varia entre os relatórios.

Dados

Infelizmente, os links para as atas em PDF seguem um padrão irregular, mas felizmente para você, preparei um web-scrapping que automatizará o processo de captura dos links e dados. O código a seguir coletará os arquivos PDF e os deixará prontos para a mineração com o tidytext.

# URL para página com JSON dos links das atas
www_all <- "https://www.bcb.gov.br/api/servico/sitebcb/copomminutes/ultimas?quantidade=2000&filtro="
# Raspagem de dados
raw_copom <- jsonlite::fromJSON(www_all)[["conteudo"]] %>% 
dplyr::as_tibble() %>% 
dplyr::select(meeting = "Titulo", url = "Url") %>% 
dplyr::mutate(url = paste0("https://www.bcb.gov.br", url)) %>% 
dplyr::mutate(text = purrr::map(url, pdftools::pdf_text))
# Tratamento de dados
copom_clean <- raw_copom %>% 
tidyr::unnest(text) %>% 
dplyr::filter(!meeting == "Changes in Copom meetings") %>% 
dplyr::group_by(meeting) %>%
dplyr::mutate(
page = dplyr::row_number(),
text = strsplit(text, "\r") %>% gsub("\n", "", .),
meeting = stringr::str_sub(meeting, 1, 3) %>% 
stringr::str_remove("[:alpha:]") %>% 
as.numeric()
) %>%
dplyr::ungroup() %>% 
tidyr::unnest(text) %>% 
dplyr::arrange(meeting)

Estatística básica dos dados

Vamos ver o que conseguimos obter calculando algumas estatísticas básicas dos textos.

Número de palavras por ata

# Frequência de palavras por ata
copom_words <- copom_clean %>%
tidytext::unnest_tokens(word, text) %>%
dplyr::count(meeting, word, sort = TRUE) %>%
dplyr::ungroup()
# Total de palavras por ata
total_words <- copom_words %>% 
dplyr::group_by(meeting) %>% 
dplyr::summarize(total = sum(n))
# Gerar gráfico
total_words %>% 
ggplot2::ggplot(ggplot2::aes(x = meeting, y = total)) +
ggplot2::geom_line(color = "#282f6b", size = 0.8)+
ggplot2::geom_point(
shape = 21, 
fill = "white", 
color = "#282f6b", 
size = 1.6, 
stroke = 1.1
) +
ggplot2::scale_y_continuous(labels = scales::number_format()) +
ggplot2::labs(
x = "Reunião (nº da ata)", 
y = "Número de palavras",
title = "Número de palavras nas atas do COPOM",
subtitle = "42ª até 238ª reunião",
caption = "Elaboração: analisemacro.com.br\nDados: BCB"
)

Percebe-se algumas mudanças ao longo do tempo, especialmente entre as reuniões número 180 e 181, onde houve remoção considerável de seções do comunicado na gestão Tombini. No mesmo sentido, de redução do total de palavras por comunicado, o início da gestão de Illan Goldfajn marcou mudança no layout e estrutura das seções da ata, alterações essas que permanecem em vigor até hoje.

A redução do tamanho dos comunicados, de forma geral, é certamente um ponto interessante que merece investigação em se tratando de qualidade de comunicação da política monetária.

Sobre o que os diretores discutiram nas reuniões?

Vamos compilar uma lista das palavras usadas com maior frequência em cada ata. Como antes, vamos omitir as "stop words".

# Palavras por ata
copom_text <- copom_clean %>% 
dplyr::select(meeting, page, text) %>%
tidytext::unnest_tokens(word, text)
# Gerar gráfico
copom_text %>% 
dplyr::mutate(word = gsub("[^A-Za-z ]", "", word)) %>%
dplyr::filter(word != "") %>%
dplyr::anti_join(stop_words) %>%
dplyr::group_by(meeting) %>%
dplyr::count(word, sort = TRUE) %>% 
dplyr::mutate(rank = dplyr::row_number()) %>%
dplyr::ungroup() %>% 
dplyr::arrange(rank, meeting) %>%
dplyr::filter(rank < 9, meeting > 230) %>% 
ggplot2::ggplot(ggplot2::aes(y = n, x = forcats::fct_reorder(word, n))) +
ggplot2::geom_col(fill = "#282f6b") +
ggplot2::facet_wrap(~meeting, scales = "free", ncol = 4) +
ggplot2::coord_flip() +
ggplot2::labs(
x = "",
y = "",
title = "Palavras mais frequentes nas atas do COPOM",
subtitle = "Excluídas palavras comuns (stop words) e números.",
caption = "Elaboração: analisemacro.com.br\nDados: BCB"
)


Como esperado, muitas discussões sobre inflação. Vamos tentar encontrar algo mais informativo com esses dados.

Conforme Silge e Robinson, podemos usar a função bind_tf_idf para juntar a frequência do termo (tf) e a frequência inversa do documento (idf) ao nosso conjunto de dados. Essa estatística diminuirá o peso em palavras muito comuns e aumentará o peso em palavras que só aparecem em algumas atas. Em essência, extrairemos o que há de especial em cada ata. As atas do COPOM sempre falarão muito sobre inflação e juros, e a estatística "tf-idf" pode nos dizer algo sobre o que é diferente em cada ata.

Também limparemos alguns termos adicionais que o pdftools captou (abreviações e palavras estranhas ou fragmentadas), aumentando nossa lista de "stop words".

# Stop words personalizadas
custom_stop_words <- dplyr::bind_rows(
dplyr::tibble(
word = c(
tolower(month.abb), 
tolower(month.name),
"one","two","three","four","five","six","seven","eight","nine","ten",
"eleven","twelve", "wkh", "ri", "lq", "month", "wr", "dqg",
"hdu", "jurzwk", "zlwk", "zlwk", "hfhpehu", "dqxdu", "kh", "sulfh", "dv",
"kh", "prqwk", "hdu", "shulrg", "dv", "jurzwk", "wkdw", "zdv", "iru", "dw",
"wkdw", "jrrgv", "xqh", "eloolrq", "eloolrq", "iluvw", "dq", "frqvxphu", 
"prqwk", "udwh", "sulo", "rq", "txduwhu", "vhfwru", "pandemic", 
"dffxpxodwhg", "hg", "kdyh", "sdqghg", "sulfhv", "rq", "sdqvlrq", 
"percent", "forvhg", "frpsduhg", "lqgh", "ryhpehu", "wklv", "kdv", "prqwkv",
"bcbgovbr", "banco", "head"
), 
lexicon = c("custom")
),
stop_words
)
# Palavras por ata
copom_text_refined <- copom_text %>% 
dplyr::mutate(word = gsub("[^A-Za-z ]", "", word)) %>%
dplyr::filter(word != "") %>%
dplyr::group_by(meeting) %>% 
dplyr::count(word, sort = TRUE) %>% 
tidytext::bind_tf_idf(word, meeting, n) %>% 
dplyr::arrange(desc(tf_idf))
# Gerar gráfico
copom_text_refined %>% 
dplyr::anti_join(custom_stop_words, by = "word") %>%
mutate(word = factor(word, levels = rev(unique(word)))) %>% 
dplyr::group_by(meeting) %>%
dplyr::mutate(id = dplyr::row_number()) %>%
dplyr::ungroup() %>% 
dplyr::filter(id < 9, meeting > 230) %>% 
ggplot2::ggplot(ggplot2::aes(y = tf_idf, x = word, fill = meeting)) +
ggplot2::geom_col(show.legend = FALSE) +
ggplot2::facet_wrap(~meeting, scales = "free", ncol = 4) +
ggplot2::coord_flip() +
ggplot2::labs(
x = "",
y = "tf-idf",
title = "Palavras mais distintas nas atas do COPOM",
subtitle = "Estatística tf-idf do tidytext",
caption = "Elaboração: analisemacro.com.br\nDados: BCB"
) +
ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 45, hjust = 1))

Esse gráfico já mostram uma história interessante dessa amostra que escolhemos. Podemos observar preocupações com o BREXIT, reformas e agenda econômica, o surgimento do termo "covid" a partir da ata nº 231 e subsequente adoção do forward guidance e, por fim, também como destaque, a mudança da política para uma "normalização parcial" (termos "partial" e "normalization").

Comparando o sentimento entre as atas
Como o sentimento variou entre as atas? Vamos usar a abordagem que usamos no início para a ata de maio/2021 e aplicá-la a cada ata.

# Análise de sentimento das atas
copom_sentiment_all <- copom_text %>%
dplyr::anti_join(stop_words) %>%
dplyr::inner_join(tidytext::get_sentiments("bing")) %>%
dplyr::count(meeting, page, sentiment) %>%
tidyr::pivot_wider(
id_cols = c(meeting, page),
names_from = sentiment, 
values_from = n,
values_fill = 0
) %>%
dplyr::mutate(sentiment = positive - negative)
# Gerar gráfico
copom_sentiment_all %>% 
dplyr::filter(meeting > 230) %>% 
ggplot2::ggplot(ggplot2::aes(page, sentiment, fill = sentiment > 0)) +
ggplot2::geom_col(show.legend = FALSE) +
ggplot2::scale_fill_manual(values = c("#b22200", "#282f6b")) +
ggplot2::facet_wrap(~meeting, ncol = 4, scales = "free_x") +
ggplot2::annotate("segment", x = -Inf, xend = Inf, y = -Inf, yend = -Inf)+
ggplot2::annotate("segment", x = -Inf, xend = -Inf, y = -Inf, yend = Inf) +
ggplot2::labs(
x = "Página da ata",
y = "Sentimento",
title = "Análise de sentimento das Ata do COPOM",
subtitle = "Bing lexicon, amostra das últimas 8 atas",
caption = "Elaboração: analisemacro.com.br\nDados: BCB"
)

O resultado mostra que o sentimento mudou consideravelmente no texto das atas da amostra das últimas 8 reuniões, com forte predominância "negativa" desde o advento da pandemia da Covid-19.

Conclusão

Isso é tudo por hoje. Essas técnicas são muito interessantes e promissoras, merecendo exploração aprofundada. Certamente o exercício aqui apresentado possui falhas e pontos de melhoria, mas serve como uma introdução ao tema. Espero que goste, caro leitor!

Possui interesse no tema de política monetária? A Análise Macro disponibiliza o curso de Teoria da Política Monetária dentro da temática de Central Banking. Aproveite!

_____________

Extraindo dados eleitorais no R

By | Notas

O pacote electionsbr oferece um conjunto de funções que possibilitam a extração de dados eleitorais diretamente da base de dados do Tribunal Superior Eleitoral (TSE). Com ele é possível obter dados de todas as eleições desde 1994 desagregados até por zona eleitoral. Além disso, é possível obter informações sobre filiação partidária, características dos eleitores de cada zona eleitoral e declaração patrimonial de todos os candidatos.

Para mostrar a funcionalidade do pacote, iremos utilizar os dados da última eleição federal, em 2018. Iremos separar apenas os votos para presidente e selecionar o partido - no caso a chapa - que recebeu mais votos em cada município.


elec_2018 = party_mun_zone_fed(2018, br_archive = TRUE) %>%
filter(DESCRICAO_CARGO == "Presidente" & NUM_TURNO == 1) %>%
group_by(CODIGO_MUNICIPIO) %>%
top_n(1, QTDE_VOTOS_NOMINAIS) %>%
mutate(CODIGO_MUNICIPIO = as.double(CODIGO_MUNICIPIO)) %>%
select(CODIGO_MUNICIPIO, SIGLA_PARTIDO)

O código utilizado como identificador de cada município é específico do TSE e é diferente do código IBGE padrão. Por isso, como iremos colocar em um mapa utilizando o pacote geobr, precisamos de uma tabela para conversão.

</pre>
tse_ibge_id <- read_csv("https://raw.githubusercontent.com/betafcc/Municipios-Brasileiros-TSE/master/municipios_brasileiros_tse.csv")

elec_2018 = left_join(elec_2018, tse_ibge_id, by = c("CODIGO_MUNICIPIO" = "codigo_tse"))
<pre>

 

Assim, fazemos o download dos mapas por município e estado e juntamos com a nossa base.

</pre>
mapa_muni = read_municipality(showProgress = FALSE)
mapa_state = read_state(showProgress = FALSE)

df <- left_join(mapa_muni, elec_2018, by = c("code_muni" = "codigo_ibge"))

Agora, podemos fazer o mapa com os dados, que mostram grande concentração espacial do voto.

 


ggplot() +
geom_sf(df, mapping = aes(fill = SIGLA_PARTIDO), colour = NA) +
geom_sf(mapa_state, mapping = aes(fill = NA)) +
scale_fill_manual(values=c( "#fff200", "#263272", "#c4122d")) +
theme_minimal() +
labs(title = "Eleição em 2018",
subtitle = "Partido mais votado por município na eleição presidencial em 2018")

Receba diretamente em seu e-mail gratuitamente nossas promoções especiais
e conteúdos exclusivos sobre Análise de Dados!

Assinar Gratuitamente
{"cart_token":"","hash":"","cart_data":""}