Transformando Dados em Informações

Usando R nas Ciências Sociais

Dr Robson Oliveira

IFPB

Encontre esses slides em:

https://robsonol.github.io/workshop_r_ciencias_sociais/

Contando Histórias com Dados

Contando Histórias com Dados

Fonte: Allison Horst

  1. Planejar
  2. Adquirir dados
  3. Explorar:
    • Transformar

    • Visualizar

    • Modelar

  4. Comunicar

Contando Histórias com Dados

Pré-Requisitos

R

R

  1. Baixar e instalar R em https://cloud.r-project.org

RStudio

  1. Instalar o RStudio: https://www.rstudio.com

Pacotes

Conceitos Básicos

Banco de dados: data.frame

Um tipo especial de objeto é o data.frame:

# mtcars é um banco de dados com informações de veículos:
dados_carros <- mtcars

# podemos inspecionar o data frame:
dados_carros

Banco de dados: data.frame

Um tipo especial de objeto é o data.frame:

# mtcars é um banco de dados com informações de veículos:
dados_carros <- mtcars

# podemos inspecionar o data frame:
dados_carros
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

Banco de dados: data.frame

Banco de dados: data.frame

Fonte: Allison Horst

Fonte: Allison Horst

Banco de dados: data.frame

Vamos trabalhar com dados no R no formato tidy:

Banco de dados: data.frame

Fonte: Allison Horst

1. Adquirindo Dados

Importando dados

Sugestão de fontes de dados:

Importando dados

Importando dados de consumo de energia usando a função read_csv():

# importar o pacote
library(tidyverse)

# salvar o arquivo csv como o objeto "despesas"
consumo_energia <- read_csv(file = "dados/consumo_energia_brasil.csv")

# mostrar apenas as primeiras linhas do banco de dados:
consumo_energia

Importando dados

Importando dados de consumo de energia usando a função read_csv():

# importar o pacote
library(tidyverse)

# salvar o arquivo csv como o objeto "consumo_energia"
consumo_energia <- read_csv(file = "dados/consumo_energia_brasil.csv")

# mostrar apenas as primeiras linhas do banco de dados:
consumo_energia

Importando dados

Importando dados de consumo de energia usando a função read_csv():

# importar o pacote
library(tidyverse)

# salvar o arquivo csv como o objeto "consumo_energia"
consumo_energia <- read_csv(file = "dados/consumo_energia_brasil.csv")

# mostrar apenas as primeiras linhas do banco de dados:
consumo_energia
# A tibble: 34,992 × 6
     ano   mes sigla_uf tipo_consumo numero_consumidores  consumo
   <dbl> <dbl> <chr>    <chr>                      <dbl>    <dbl>
 1  2004     1 RO       Total                         NA  112812 
 2  2004     1 AC       Total                         NA   34840.
 3  2004     1 AM       Total                         NA  274773 
 4  2004     1 RR       Total                         NA   31696.
 5  2004     1 PA       Total                         NA 1011353.
 6  2004     1 AP       Total                         NA   43084 
 7  2004     1 TO       Total                         NA   65877.
 8  2004     1 MA       Total                         NA  737033.
 9  2004     1 PI       Total                         NA  131052 
10  2004     1 CE       Total                         NA  518714 
# … with 34,982 more rows

Importando dados

2. Transformação de dados

Funções do dplyr

  1. filter() filtra apenas observações com valores específicos

  2. arrange() reordena as linhas da base

  3. select() seleciona apenas variáveis de interesse

  4. mutate() cria novas variáveis como função das demais

  5. summarise() cria estatísticas descritivas

A. Função filter

B. Função select()

C. Função mutate()

D. Função arrange()

E. Função summarise()

F. Função group_by()

Exemplo de Transformação

Exemplo de Transformação

Exemplo de Transformação

3. Visualização

“Apresentar dados com gráficos pode ajudar você a comunicar informações com clareza.”

Pacote ggplot2

Pacote ggplot2

Vamos criar nosso primeiro gráfico:

# camada de dados
energia_residencial_pb |> 
  # camada estética (mapeamento)
  ggplot(aes(x = data, y = consumo)) +
  # camada de geometria
  geom_point()

Pacote ggplot2

Vamos criar nosso primeiro gráfico:

# camada de dados
energia_residencial_pb |> 
  # camada estética (mapeamento)
  ggplot(aes(x = data, y = consumo)) +
  # camada de geometria
  geom_point()

Pacote ggplot2

Vamos criar nosso primeiro gráfico:

# camada de dados
energia_residencial_pb |> 
  # camada estética (mapeamento)
  ggplot(aes(x = data, y = consumo)) +
  # camada de geometria
  geom_point()

Pacote ggplot2

Geometrias

Geometrias

  • geom é o objeto geométrico que um gráfico usa para representar dados.

  • Gráficos de barras são construídos com geom_bar.

  • Gráficos de linhas são construídos com geom_line.

  • Assim, para mudar a geometria, só alterar o termo geom_*.

geom_point()

energia_residencial_pb |> 
  ggplot(mapping = aes(x = data, y = consumo)) +
  geom_point()

geom_line()

energia_residencial_pb |> 
  ggplot(mapping = aes(x = data, y = consumo)) +
  geom_line()

geom_smooth()

energia_residencial_pb |> 
  ggplot(mapping = aes(x = data, y = consumo)) +
  geom_smooth()

geom_hist

energia_residencial_pb |> 
  ggplot(aes(x = consumo)) +
  geom_histogram()

geom_boxplot

energia_residencial_pb |> 
  ggplot(aes(y = consumo)) +
  geom_boxplot()

geom_qq

energia_residencial_pb |> 
  ggplot(aes(sample = consumo)) +
  geom_qq() +
  geom_qq_line()

Múltiplos geom_*

energia_residencial_pb |> 
  ggplot(aes(x = data, y = consumo)) +
  geom_point() +
  geom_line()

Dplyr + ggplot

energia_residencial_pb |> 
  group_by(ano) |> 
  summarise(consumo_total = sum(consumo)) |> 
  ggplot(aes(x = ano, y = consumo_total)) + 
  geom_col()

Múltiplas faces com facet_wrap

energia_residencial_pb |> 
  filter(ano > 2012) |> 
  ggplot(aes(x = mes, y = consumo)) + 
  geom_line() + 
  facet_wrap(~ano)

Mais Informações

4. Modelar

Modelar

Uma lista (não exaustiva) de modelagem de dados que podem ser desenvolvidos nas ciências sociais:

  1. Estatística Básica
  2. Previsão de séries temporais
  3. Regressão
  4. Segmentação de clientes com clusterização
  5. Análise de Churn
  6. Análise financeira (portfólios)
  7. Análise fatorial

Estatística Básica: Estatísticas Descritivas

salario_pb <- read_rds("dados/salario-pb-Rais2013.rds")

salario_pb |> head()
# A tibble: 6 × 9
  id    salario idade mun_trab mun_res escolaridade  sexo meso_trab      semia…¹
  <chr>   <dbl> <dbl>    <int>   <int>        <dbl> <dbl> <chr>          <chr>  
1 1        678     49   250375  250375            1     1 Sertão Paraib… S      
2 2       1352.    36   251030  251030            1     1 Borborema      S      
3 3       2859.    39   251140  251140            1     1 Borborema      S      
4 4       1800.    46   251140  251140            1     1 Borborema      S      
5 5        712.    36   251140  251140            1     1 Borborema      S      
6 6        960.    41   251140  251140            1     1 Borborema      S      
# … with abbreviated variable name ¹​semiarido_trab

Estatística: Estatísticas Descritivas

Estatística: Estatísticas Descritivas

summary(salario_pb)
      id               salario            idade          mun_trab     
 Length:865841      Min.   :  203.4   Min.   : 0.00   Min.   :240810  
 Class :character   1st Qu.:  731.7   1st Qu.:27.00   1st Qu.:250400  
 Mode  :character   Median :  881.4   Median :34.00   Median :250750  
                    Mean   : 1422.8   Mean   :36.37   Mean   :250730  
                    3rd Qu.: 1328.3   3rd Qu.:45.00   3rd Qu.:250750  
                    Max.   :81597.3   Max.   :98.00   Max.   :251740  
    mun_res        escolaridade         sexo        meso_trab        
 Min.   :250010   Min.   : 1.000   Min.   :1.000   Length:865841     
 1st Qu.:250400   1st Qu.: 5.000   1st Qu.:1.000   Class :character  
 Median :250750   Median : 7.000   Median :1.000   Mode  :character  
 Mean   :250731   Mean   : 6.286   Mean   :1.395                     
 3rd Qu.:250750   3rd Qu.: 7.000   3rd Qu.:2.000                     
 Max.   :251740   Max.   :11.000   Max.   :2.000                     
 semiarido_trab    
 Length:865841     
 Class :character  
 Mode  :character  
                   
                   
                   

Estatística: Estatísticas Descritivas

salario_pb |> 
  summarise(across(c(salario, idade, escolaridade),
                   list(media = ~ mean(., na.rm = TRUE),
                        mediana = ~ median(., na.rm = TRUE),
                        dp = ~ sd(., na.rm = TRUE)))) |> 
  pivot_longer(cols = everything(),
               names_to = c("Variável", ".value"), 
               names_sep = "_") |> 
  rename("Média" = media,
         "Mediana" = mediana,
         "Desvio-Padrão" = dp) |> 
  knitr::kable()
Variável Média Mediana Desvio-Padrão
salario 1422.765775 881.4 1823.80258
idade 36.374189 34.0 11.49324
escolaridade 6.285835 7.0 1.99408

Estatística: Correlação

Calcular correlação pode ser executada com a função cor():

matriz_corr <- salario_pb |> 
  # selecionar variáveis numéricas
  select(salario, escolaridade, sexo) |> 
  cor()

matriz_corr
                 salario escolaridade        sexo
salario       1.00000000    0.2440811 -0.00844732
escolaridade  0.24408111    1.0000000  0.26036466
sexo         -0.00844732    0.2603647  1.00000000

Estatística: Correlação

# install.packages("ggcorrplot")
library(ggcorrplot)

matriz_corr |> 
  ggcorrplot()

Estatística: Correlação

# install.packages("ggcorrplot")
library(ggcorrplot)

matriz_corr |> 
  ggcorrplot(ggtheme = theme_grey, 
             lab = TRUE, 
             colors = c("#6D9EC1", "white", "#E46726"), 
             title = "Matriz de Correlação")

Estatística: Distribuição Normal

salario_pb |> 
  ggplot(aes(x = salario)) + 
  geom_histogram(breaks = seq(0,10000, by = 100),
                 fill = "red",
                 alpha = 0.3) +
  labs(x = "Salário", y = "", 
       title = "Histograma do Salário Nominal na Paraíba (2013)",
       caption = "Fonte: Elaborado pelo autor a partir de dados da RAIS (2013)") +
  theme_light()

Estatística: Distribuição Normal

salario_pb |> 
  sample_n(size = 1000) |> 
  ggplot(aes(sample = salario)) + 
  geom_qq() +
  geom_qq_line() +
  labs(x = "Salário", y = "", title = "QQ-Plot do Salário Nominal na Paraíba (2013)",
       subtitle = "A distribuição de salário não parece seguir uma distribuição Normal",
       caption = "Fonte: Elaborado pelo autor a partir de dados da RAIS (2013)")

Estatística: Diferença de Médias

salario_pb |> 
  mutate(sexo = case_when(
    sexo == 2 ~ "Mulher",
    sexo == 1 ~ "Homem")) |> 
  filter(salario < 3000) |> 
  ggplot(aes(salario, fill = fct_rev(as.factor(sexo)))) +
  geom_density(position = 'identity', alpha = 0.5) +
  facet_wrap(~sexo) +
  guides(fill = "none") +
  labs(x = "Salário (R$)", y = "", 
       title = "Distribuição de Salários na Paraíba por Gênero, 2013",
       subtitle = "Salários abaixo de R$ 3000",
       caption = "Fonte: Elaboração do autor a partir de dados da RAIS (2013)")

Estatística: Diferença de Médias

# calcular salário das mulheres
salario_mulheres <- salario_pb |> 
  filter(sexo == 1) |> 
  pull(salario)

# salário dos homens
salario_homens <- salario_pb |> 
  filter(sexo == 2) |> 
  pull(salario)

# teste t para diferença de médias
t.test(salario_mulheres, salario_homens)

    Welch Two Sample t-test

data:  salario_mulheres and salario_homens
t = 8.0402, df = 783668, p-value = 8.984e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 23.83628 39.20365
sample estimates:
mean of x mean of y 
 1435.205  1403.685 

Regressão

Retornos salariais da educação segundo a equação de Mincer (1974):

\[ Y (\text{Salário}) = \beta_0 + \beta_1 \text{educação} + \beta_2 \text{exp} + \beta_3 \text{exp}^2 + u \]

Regressão

equacao <- "log(salario + 1) ~ sexo + idade + escolaridade + meso_trab + semiarido_trab"

modelo <- lm(equacao, data = salario_pb) 
modelo |> 
  broom::tidy()

Regressão

equacao <- "log(salario + 1) ~ sexo + idade + escolaridade + meso_trab + semiarido_trab"

modelo <- lm(equacao, data = salario_pb) 
modelo |> 
  broom::tidy()

Regressão

equacao <- "log(salario + 1) ~ sexo + idade + escolaridade + meso_trab + semiarido_trab"

modelo <- lm(equacao, data = salario_pb) 
modelo |> 
  broom::tidy()
# A tibble: 8 × 5
  term                      estimate std.error statistic   p.value
  <chr>                        <dbl>     <dbl>     <dbl>     <dbl>
1 (Intercept)                 5.79   0.00416      1391.  0        
2 sexo                       -0.137  0.00121      -113.  0        
3 idade                       0.0165 0.0000499     330.  0        
4 escolaridade                0.105  0.000297      352.  0        
5 meso_trabBorborema         -0.0743 0.00342       -21.7 2.07e-104
6 meso_trabMata Paraibana     0.197  0.00313        63.0 0        
7 meso_trabSertão Paraibano  -0.0889 0.00215       -41.4 0        
8 semiarido_trabS             0.0772 0.00329        23.5 1.36e-121

Regressão

\[ \log(\text{salário} ) = 5,78 - 0,13 \text{ Mulher} + 0,02 \text{ Idade} + 0.10 \text{ Escolaridade} \\[0.1in] - 0,07 \text{ Borborema} + 0.20 \text{ Zona Mata} - 0,09 \text{ Sertão} + 0,08 \text{Semiarido} \]

Regressão

pessoa_ficticia <- data.frame(
  idade = 25,
  escolaridade = 10,
  sexo = 2,
  meso_trab = "Mata Paraibana",
  semiarido_trab = "N"
)

Regressão

O modelo sugere que a renda dessa pessoa deve ser de R$ 1298,13:

modelo |> 
  predict(pessoa_ficticia) |> 
  exp()
       1 
1298.131 

Séries Temporais

Para análise de séries temporais no R vamos usar o pacote Modeltime

Séries Temporais

Vamos prever o valor futuro do consumo de energia residencial na Paraíba.

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

# Instalar pacote:
# install.packages("modeltime")
# install.packages("timetk")

# carregar pacote
library(tidymodels)
library(modeltime)
library(timetk)

# carregar dados
energia <- read_csv("dados/energia_residencial_paraiba.csv")

Séries Temporais

energia |> 
  ggplot(aes(x = data, y = consumo)) +
  geom_line(color = "red", size = 1, alpha = .4) + 
  labs(x = "Data", y = "Consumo", 
       title = "Consumo de Energia Residencial na Paraíba") +
  theme_bw()

Séries Temporais

energia |> 
  plot_time_series(data, 
                   consumo, 
                   .title = "Consumo de Energia Residencial na Paraíba"
                   )

Séries Temporais

Base de Treinamento e Base de Teste

Séries Temporais

set.seed(123)
# base de teste (20%) e treinamento (80%)
energia_treinamento_teste <- energia |> 
  initial_time_split(prop = 0.8)

tbl_energia_treinamento <- training(energia_treinamento_teste)
tbl_energia_teste <- testing(energia_treinamento_teste)

energia_treinamento_teste |> 
    tk_time_series_cv_plan() |> 
    plot_time_series_cv_plan(data, consumo)

Séries Temporais

set.seed(123)
# base de teste (20%) e treinamento (80%)
energia_treinamento_teste <- energia |> 
  initial_time_split(prop = 0.8)

tbl_energia_treinamento <- training(energia_treinamento_teste)
tbl_energia_teste <- testing(energia_treinamento_teste)

energia_treinamento_teste |> 
    tk_time_series_cv_plan() |> 
    plot_time_series_cv_plan(data, consumo)

Séries Temporais

set.seed(123)
# base de teste (20%) e treinamento (80%)
energia_treinamento_teste <- energia |> 
  initial_time_split(prop = 0.8)

tbl_energia_treinamento <- training(energia_treinamento_teste)
tbl_energia_teste <- testing(energia_treinamento_teste)

energia_treinamento_teste |> 
    tk_time_series_cv_plan() |> 
    plot_time_series_cv_plan(data, consumo)

Séries Temporais

set.seed(123)
# base de teste (20%) e treinamento (80%)
energia_treinamento_teste <- energia |> 
  initial_time_split(prop = 0.7)

tbl_energia_treinamento <- training(energia_treinamento_teste)
tbl_energia_teste <- testing(energia_treinamento_teste)

energia_treinamento_teste |> 
    tk_time_series_cv_plan() |> 
    plot_time_series_cv_plan(data, consumo)

Séries Temporais

Agora vamos informar quem são nossas variáveis explicativas: o consumo de energia residencial será explicado apenas pelos seus valores passados. Poderiamos incluir outras variáveis, como feriados, tarifa de energia, etc.

receita_energia <- recipe(consumo ~ data, tbl_energia_treinamento)

Séries Temporais

Por fim, definir o modelo, rodar e gerar previsões:

# definir o modelo a ser rodado (ARIMA)
modelo_arima <- arima_reg() %>% 
  set_engine("auto_arima")

# Rodar o modelo na base de treinamento
workflow_arima <- workflow() %>% 
  add_recipe(receita_energia) %>% 
  add_model(modelo_arima) %>% 
  fit(tbl_energia_treinamento)

# Gerar uma previsão e comparar com o que realmente 
# aconteceu no período de teste
tbl_energia_calibracao <- workflow_arima |> 
  modeltime_calibrate(new_data = tbl_energia_teste)

# gerar os valores previstos
tbl_energia_previsao <- tbl_energia_calibracao |> 
  modeltime_forecast(new_data = tbl_energia_teste,
                     actual_data = energia)

Séries Temporais

Por fim, definir o modelo, rodar e gerar previsões:

# definir o modelo a ser rodado (ARIMA)
modelo_arima <- arima_reg() %>% 
  set_engine("auto_arima")

# Rodar o modelo na base de treinamento
workflow_arima <- workflow() %>% 
  add_recipe(receita_energia) %>% 
  add_model(modelo_arima) %>% 
  fit(tbl_energia_treinamento)

# Gerar uma previsão e comparar com o que realmente 
# aconteceu no período de teste
tbl_energia_calibracao <- workflow_arima |> 
  modeltime_calibrate(new_data = tbl_energia_teste)

# gerar os valores previstos
tbl_energia_previsao <- tbl_energia_calibracao |> 
  modeltime_forecast(new_data = tbl_energia_teste,
                     actual_data = energia)

Séries Temporais

Por fim, definir o modelo, rodar e gerar previsões:

# definir o modelo a ser rodado (ARIMA)
modelo_arima <- arima_reg() %>% 
  set_engine("auto_arima")

# Rodar o modelo na base de treinamento
workflow_arima <- workflow() %>% 
  add_recipe(receita_energia) %>% 
  add_model(modelo_arima) %>% 
  fit(tbl_energia_treinamento)

# Gerar uma previsão e comparar com o que realmente 
# aconteceu no período de teste
tbl_energia_calibracao <- workflow_arima |> 
  modeltime_calibrate(new_data = tbl_energia_teste)

# gerar os valores previstos
tbl_energia_previsao <- tbl_energia_calibracao |> 
  modeltime_forecast(new_data = tbl_energia_teste,
                     actual_data = energia)

Séries Temporais

Por fim, definir o modelo, rodar e gerar previsões:

# definir o modelo a ser rodado (ARIMA)
modelo_arima <- arima_reg() %>% 
  set_engine("auto_arima")

# Rodar o modelo na base de treinamento
workflow_arima <- workflow() %>% 
  add_recipe(receita_energia) %>% 
  add_model(modelo_arima) %>% 
  fit(tbl_energia_treinamento)

# Gerar uma previsão e comparar com o que realmente 
# aconteceu no período de teste
tbl_energia_calibracao <- workflow_arima |> 
  modeltime_calibrate(new_data = tbl_energia_teste)

# gerar os valores previstos
tbl_energia_previsao <- tbl_energia_calibracao |> 
  modeltime_forecast(new_data = tbl_energia_teste,
                     actual_data = energia)

Séries Temporais

Gráfico da previsão comparada com o que ocorreu de fato:

tbl_energia_previsao |> 
  plot_modeltime_forecast()

Séries Temporais

É possível ainda criar uma série de medidas de performance. Elas são úteis para nos guiar sobre qual o melhor modelo:

tbl_energia_calibracao |> 
  modeltime_accuracy(new_data = tbl_energia_teste) |> 
  knitr::kable()
.model_id .model_desc .type mae mape mase smape rmse rsq
1 ARIMA(0,1,1)(0,1,1)[12] Test 7307.977 4.206429 0.9824635 4.254726 9406.222 0.8150693

Séries Temporais

Séries Temporais

# A tibble: 6 × 2
  .model_desc                                mape
  <chr>                                     <dbl>
1 SEASONAL DECOMP: ETS(M,A,N)                3.95
2 ARIMA(0,1,2)(0,1,1)[12] W/ XGBOOST ERRORS  4.17
3 ARIMA(0,1,1)(0,1,1)[12]                    4.21
4 REGRESSION WITH ARIMA(0,1,0) ERRORS        4.71
5 PROPHET W/ REGRESSORS                      4.91
6 TBATS(0, {0,0}, 1, {<12,5>})               6.32

Séries Temporais

Para mais informações sobre séries temporais:

Análise de Churn

Análise de Churn

A partir de informações dos clientes, podemos prever a probabilidade que um cliente abandone (churn) a empresa, nos permitindo desenvolver programas focados em retenção de clientes.

Análise de Churn

data(wa_churn, package = "modeldata")

Análise de Churn

Análise de Churn

wa_churn |> 
  ggplot(aes(x = monthly_charges)) +
  geom_histogram(aes(y = ..density..)) + 
  geom_density(fill = "blue", alpha = .2) +
  labs(x = "Gasto Mensal", y = "", 
       title = "Distribuição de Gastos Mensais dos Clientes") +
  theme_light()

wa_churn |> 
  mutate(female = case_when(female == 1 ~ "Mulher",
                            female == 0 ~ "Homem")) |> 
  ggplot(aes(x = female, fill = female)) +
  geom_bar() + 
  labs(x = "", y = "Total de Clientes",
       title = "Clientes por Sexo") +
  guides(fill = "none") +
  theme_light()

wa_churn |> 
  ggplot(aes(x = tenure)) + 
  geom_histogram(aes(y = ..density..)) +
  geom_density(fill = "blue", alpha = 0.2) +
  labs(x = "Tempo como cliente (meses)", y = "",
       title = "Distribuição de Tempo como Cliente") +
  theme_light()

wa_churn |> 
  ggplot(aes(x = churn)) +
  geom_bar() +
  labs(x = "Churn?", y = "", title = "") +
  theme_light()

Análise de Churn

# Criar a base de treinamento e teste
churn_treinamento_teste <- wa_churn |> 
  initial_split(prop = 0.8)

tbl_treinamento <- churn_treinamento_teste |> training()
tbl_teste <- churn_treinamento_teste |> testing()

churn_treinamento_teste
<Training/Testing/Total>
<5634/1409/7043>

Análise de Churn

# Transformações dos dados
receita_churn <- recipe(churn ~ ., data = tbl_treinamento) %>% 
  step_impute_linear(all_numeric()) %>% 
  step_dummy(all_nominal(), -all_outcomes()) %>% 
  step_normalize(all_numeric())

Análise de Churn

# Definir o modelo
modelo_floresta_aleatoria <- 
  rand_forest(
    mtry = 3, 
    trees = 200, 
    min_n = 30) |> 
  set_mode("classification") |> 
  set_engine("ranger")

Análise de Churn

workflow_churn <- workflow() |> 
  add_model(modelo_floresta_aleatoria) |> 
  add_recipe(receita_churn) |>  
  fit(tbl_treinamento)

Análise de Churn

A matriz de confusão:

# Matriz de Confusão
matriz_confusao_churn <- workflow_churn |> 
  predict(tbl_teste) |> 
  bind_cols(tbl_teste |> select(churn)) |>
  mutate_all(as.factor) |> 
  conf_mat(churn, .pred_class)

matriz_confusao_churn |> 
  autoplot(type = "heatmap")

Figure 1: Matriz de Confusão

Análise de Churn

matriz_confusao_churn |> 
  summary() |> 
  select(-.estimator) %>% 
  filter(.metric %in% c('precision', 'recall', 'f_meas',
                        'accuracy', 'spec', 'sens')) %>% 
  rename(Medida = 1, Estimativa = 2)
# A tibble: 6 × 2
  Medida    Estimativa
  <chr>          <dbl>
1 accuracy       0.807
2 sens           0.469
3 spec           0.929
4 precision      0.707
5 recall         0.469
6 f_meas         0.564

Análise de Churn

cliente_ficticio <- data.frame(
  female = 1, # mulher
  senior_citizen = 0, # não idosa
  partner = 1, # com parceiro(a)
  dependents = 0, # sem dependentes
  tenure = 2, # contrato a 2 anos
  phone_service = 0, # sem telefone
  multiple_lines = "No", # sem multiplas linhas
  internet_service = "DSL", # internet tipo DSL
  online_security = "No", # sem serviço de segurança online
  online_backup = "No", # sem serviço de backup online
  device_protection = "No", # sem serviço de seguro de roteador (?)
  tech_support = "No", # suporte técnico
  streaming_tv = "Yes", # usa streaming de tv
  streaming_movies = "Yes", # faz uso de streaming de filmes
  contract = "One year", # contrato anual
  paperless_billing = 1, # não recebe a conta fisicamente
  payment_method = "Bank transfer (automatic)", # débito automático
  monthly_charges = 70, # paga $70 por mes
  total_charges = 1680 # cobrança total 1400
)

Análise de Churn

O modelo nos informa que provavelmente este cliente não deve cancelar sua assinatura em breve.

# O modelo informa que provavelmente esta cliente não deve abandonar a empresa em breve
workflow_churn |> 
  predict(cliente_ficticio)
# A tibble: 1 × 1
  .pred_class
  <fct>      
1 No         

Análise de Churn

Para mais informações:

Segmentação de Clientes

Segmentação de Clientes

O objetivo da clusterização é agrupar pontos em subgrupos distintos. Uma das principais aplicações de clusterização é a segmentação de clientes. Com ela podemos separar certos grupos de clientes, para oferecer descontos, ofertas, códigos promocionais, etc.

Segmentação de Clientes

Segmentação de Clientes

https://shiny.rstudio.com/gallery/kmeans-example.html

Segmentação de Clientes

clientes_shopping <- read_csv("dados/clientes_shopping.csv")

clientes_shopping |> 
  head()
# A tibble: 6 × 5
  id_cliente genero    idade renda_anual_mil score_gastos
       <dbl> <chr>     <dbl>           <dbl>        <dbl>
1          1 Masculino    19              15           39
2          2 Masculino    21              15           81
3          3 Feminino     20              16            6
4          4 Feminino     23              16           77
5          5 Feminino     31              17           40
6          6 Feminino     22              17           76

Segmentação de Clientes

Segmentação de Clientes

clientes_shopping |>
  ggplot(aes(x = genero, fill = genero)) +
  geom_bar() + 
  labs(x = "", 
       y = "",
       title = "Distribuição dos Clientes por Gênero") +
  guides(fill = "none") +
  theme_light()

# Uma inspeção visual parece indicar 
# 5 grupos distintos de pontos.
clientes_shopping |> 
  ggplot(aes(renda_anual_mil, score_gastos, color = genero)) +
  geom_point() +
  labs(x = "Renda Anual (em mil R$)",
       y = "Score de Gastos",
       title = "Relação entre Gastos e Renda dos Clientes",
       color = "") +
  theme_light()

clientes_shopping |> 
  ggplot(aes(x = idade)) +
  geom_histogram(fill = "cadetblue") +
  labs(x = "Idade", y = "",
       title = "Distribuição dos Clientes por Idade",
       caption = "Fonte: Elaborado pelo autor") +
  theme_light()

Segmentação de Clientes

Vamos construir os clusters usando o score de gastos e renda anual. Para o número de clusters, vamos usar cinco:

clusters_clientes <- clientes_shopping |> 
  select(score_gastos, renda_anual_mil) |> 
  kmeans(centers = 5)

clusters_clientes |> 
  tidy()
# A tibble: 5 × 5
  score_gastos renda_anual_mil  size withinss cluster
         <dbl>           <dbl> <int>    <dbl> <fct>  
1         49.5            55.3    81    9875. 1      
2         79.4            25.7    22    3519. 2      
3         20.9            26.3    23    5099. 3      
4         82.1            86.5    39   13444. 4      
5         17.1            88.2    35   12511. 5      

Segmentação de Clientes

Podemos repetir o gráfico de dispersão renda por gastos, mas usando como cor a classificação produzida pelo K-means.

clusters_clientes |> 
  augment(clientes_shopping) |> 
  ggplot(aes(renda_anual_mil, score_gastos, color = .cluster)) +
  geom_point() +
  labs(x = "Renda Anual (em mil R$)", y = "Score de Gastos",
       title = "Relação entre Gastos e Renda dos Clientes", color = "Clusters") +
  theme_light()

Segmentação de Clientes

Escolhendo outros valores de K, rodando para vários valores de K e

kclusts <-
  tibble(k = 1:9) %>%
  mutate(
    kclust = map(k, ~ kmeans(select(clientes_shopping, score_gastos, renda_anual_mil), .x)),
    glanced = map(kclust, glance)
  )

kclusts %>%
  unnest(cols = c(glanced)) %>%
  ggplot(aes(k, tot.withinss)) +
  geom_line(alpha = 0.5, size = 1.2, color = "midnightblue") +
  geom_point(size = 2, color = "midnightblue")

Segmentação de Clientes

Clusterização:

Análise Financeira

Análise Financeira

O pacote tidyQuant permite realizar análise financeira no R.

Análise Financeira

# instalar o pacote tidyquant
# install.packages("tidyquant")

# carregar o pacote
library(tidyquant)

tickers <- c("ITSA3.SA", "PETR3.SA", "VALE3.SA", "ABEV3.SA",
             "BBAS3.SA", "JBSS3.SA")

preco_acoes <- tickers |> 
  tq_get(get  = "stock.prices",
         from = "2021-01-02",
         to   = "2022-10-11") 

Análise Financeira

Análise Financeira

preco_acoes |> 
  filter(symbol == "PETR3.SA") |> 
  filter(date > as.Date("2022-07-01")) |> 
  ggplot(aes(x = date, y = close)) +
  geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
  labs(x = "", y = "Preço de Fechamento") 

Análise Financeira

Ra <- preco_acoes %>% 
  select(date, symbol, close) %>% 
  group_by(symbol) %>% 
  tq_transmute(select = close,
               mutate_fun = periodReturn,
               period = "monthly",
               col_rename = "Ra")

Análise Financeira

Ra |> 
  ggplot(aes(x = date, y = Ra, color = symbol)) +
  geom_line(size = 1) + 
  facet_wrap(~symbol) + guides(color = "none") +
  labs(title = "Retorno Mensal de Ativos Selecionados, 2021 - 2022",
       y = "Retorno Mensal (%)", x = "")

Análise Financeira

Ra %>% 
  group_by(symbol) %>% 
  mutate(retorno_acumulado = cumsum(Ra)) %>% 
  ggplot(aes(x = date, y = retorno_acumulado, color = symbol)) +
  geom_line() + 
  geom_hline(yintercept = 0, linetype = 2) +
  scale_y_continuous(labels = scales::percent) +
  labs(x = "", 
       y = "Retorno acumulado", 
       title = "Retorno acumulado por empresa selecionada, 2021-2022",
       caption = "Fonte: Elaborado pelo autor.") +
  facet_wrap(~symbol, scales = "free_y", ncol = 2) +
  theme(legend.position = "none",
        axis.text.x = element_text(angle=45, size = 8))

Análise Financeira

# mean = retorno médio do ativo
Ra |> 
  tq_performance(
    Ra = Ra, 
    performance_fun = mean
    )
# A tibble: 6 × 2
# Groups:   symbol [6]
  symbol     mean.1
  <chr>       <dbl>
1 ITSA3.SA -0.00430
2 PETR3.SA  0.0151 
3 VALE3.SA -0.00525
4 ABEV3.SA  0.00153
5 BBAS3.SA  0.00685
6 JBSS3.SA  0.00757

Análise Financeira

# sd = desvio-padrão (medida de volatilidade)
Ra |> 
  tq_performance(
    Ra = Ra, 
    performance_fun = sd
    )
# A tibble: 6 × 2
# Groups:   symbol [6]
  symbol     sd.1
  <chr>     <dbl>
1 ITSA3.SA 0.0562
2 PETR3.SA 0.0996
3 VALE3.SA 0.0935
4 ABEV3.SA 0.0721
5 BBAS3.SA 0.0911
6 JBSS3.SA 0.0846

Análise Financeira

# VaR indica a percentagem máxima esperada com 95% de confiança
Ra |> 
  tq_performance(
    Ra = Ra, 
    performance_fun = VaR
    )
# A tibble: 6 × 2
# Groups:   symbol [6]
  symbol       VaR
  <chr>      <dbl>
1 ITSA3.SA -0.0967
2 PETR3.SA -0.143 
3 VALE3.SA -0.166 
4 ABEV3.SA -0.0878
5 BBAS3.SA -0.140 
6 JBSS3.SA -0.121 

Análise Financeira

A Razão de Sharpe é comumente utilizada como uma medida de retorno por unidade de risco, e tem a seguinte fórmula:

\[ \text{Sharpe} = \frac{r_P - r_F}{\sigma_P} \]

Uma razão de Sharpe maior, indica uma melhor combinação risco-retorno.

Análise Financeira

Ra |> 
  tq_performance(
    Ra = Ra, 
    Rb = NULL, 
    Rf = 0,
    p = 0.95,
    performance_fun = SharpeRatio
    )
# A tibble: 6 × 4
# Groups:   symbol [6]
  symbol   `ESSharpe(Rf=0%,p=95%)` `StdDevSharpe(Rf=0%,p=95%)` VaRSharpe(Rf=0%…¹
  <chr>                      <dbl>                       <dbl>             <dbl>
1 ITSA3.SA                 -0.0376                     -0.0765           -0.0445
2 PETR3.SA                  0.0879                      0.152             0.106 
3 VALE3.SA                 -0.0260                     -0.0562           -0.0316
4 ABEV3.SA                  0.0122                      0.0213            0.0175
5 BBAS3.SA                  0.0428                      0.0752            0.0490
6 JBSS3.SA                  0.0515                      0.0896            0.0625
# … with abbreviated variable name ¹​`VaRSharpe(Rf=0%,p=95%)`

Análise Financeira

Podemos estimar o modelo CAPM para as ações. No modelo CAPM podemos fatorar a taxa livre de risco e calcular a seguinte equação:

\[ r_p - r_F = \alpha + \beta(b - r_F) + \epsilon\]

onde o \(\beta\) representa a volatilidade de uma ação comparada com o risco sistêmico do mercado:

  • \(\beta = 1: \text{ação relacionada com o mercado}\)

  • \(\beta < 1: \text{ação menos volátil que a média do mercado}\)

  • \(\beta<1: \text{ativo mais volátil que o mercado}\)

  • \(\beta <0: \text{ativo tende a aumentar de preço quando o mercado cai}\)

Análise Financeira

Rb <- "^BVSP" |> 
  tq_get(get = "stock.prices", 
         from = "2021-01-02", 
         to   = "2022-10-11") |> 
  tq_transmute(adjusted, periodReturn, 
               period = "monthly", 
               col_rename = "Rb")

Rb |> 
  ggplot(aes(x = date, y = Rb)) +
  geom_line(size = 1) + 
  labs(title = "Retorno Mensal da Bovespa, 2021 - 2022",
       y = "Retorno Mensal (%)", x = "")

Análise Financeira

Ra |> 
  left_join(Rb) |> 
  tq_performance(
    Ra = Ra, 
    Rb = Rb, 
    Rf = 0,
    performance_fun = CAPM.beta
    )
# A tibble: 6 × 2
# Groups:   symbol [6]
  symbol   CAPM.beta.1
  <chr>          <dbl>
1 ITSA3.SA       0.852
2 PETR3.SA       1.04 
3 VALE3.SA       0.875
4 ABEV3.SA       0.563
5 BBAS3.SA       1.02 
6 JBSS3.SA      -0.112

Análise Financeira

Podemos otimizar portfólios com pacote PortfolioAnalytics

Análise Financeira

Análise Financeira

Para mais informações

https://robsonolima.com.br/post/analise-de-portfolio-com-r/

https://robsonolima.com.br/post/tidyquant-analise-financeira-no-r/

https://business-science.github.io/tidyquant/

Análise Fatorial

Análise Fatorial

Var Descrição Fator 1 (Dem60) Fator 2 (Dem65) Ind60
y1 Score dado por experts em liberdade de imprensa (1960) x
y2 Liberdade dos partidos políticos (1960) x
y3 Eleições livres e justas (1960) x
y4 Efetividade do congresso eleito (1960) x
y5 Score dado por experts em liberdade de imprensa (1965) x
y6 Liberdade dos partidos políticos (1965) x

Análise Fatorial

Var Descrição Fator 1 (Dem60) Fator 2 (Dem65) Ind60
y7 Eleições livres e justas (1965) x
y8 Eleições livres e justas (1965) x
x1 PIB per capita (1960) x
x2 Consumo de energia per capita (1960) x
x3 % da força de trabalho na industrial (1960) x

Análise Fatorial

Análise Fatorial

# Instalar pacote lavaan
# install.packages("lavaan")

# carregar pacote lavaan
library(lavaan)

# importar dados
dados <- PoliticalDemocracy

Análise Fatorial

Análise Fatorial

# Podemos especificar o modelo como:
LVdata.model <-'# Modelo de medidas
                  ind60 =~ x1 + x2 + x3 
                  dem60 =~ y1 + y2 + y3 + y4
                  dem65 =~ y5 + y6 + y7 + y8
                # Regressão
                  dem60 ~ ind60
                  dem65 ~ ind60 + dem60
                # Resíduos
                  y1 ~~ y5
                  y2 ~~ y4 + y6
                  y3 ~~ y7
                  y4 ~~ y8
                  y6 ~~ y8'

Análise Fatorial

# Especificar o modelo lavaan
fit <- sem(LVdata.model, data = dados)

# Mostrar o resultado
fit |> tidy()
# A tibble: 34 × 9
   term        op    estimate std.error stati…¹   p.value std.lv std.all std.nox
   <chr>       <chr>    <dbl>     <dbl>   <dbl>     <dbl>  <dbl>   <dbl>   <dbl>
 1 ind60 =~ x1 =~        1        0       NA    NA         0.670   0.920   0.920
 2 ind60 =~ x2 =~        2.18     0.139   15.7   0         1.46    0.973   0.973
 3 ind60 =~ x3 =~        1.82     0.152   12.0   0         1.22    0.872   0.872
 4 dem60 =~ y1 =~        1        0       NA    NA         2.22    0.850   0.850
 5 dem60 =~ y2 =~        1.26     0.182    6.89  5.64e-12  2.79    0.717   0.717
 6 dem60 =~ y3 =~        1.06     0.151    6.99  2.81e-12  2.35    0.722   0.722
 7 dem60 =~ y4 =~        1.26     0.145    8.72  0         2.81    0.846   0.846
 8 dem65 =~ y5 =~        1        0       NA    NA         2.10    0.808   0.808
 9 dem65 =~ y6 =~        1.19     0.169    7.02  2.16e-12  2.49    0.746   0.746
10 dem65 =~ y7 =~        1.28     0.160    8.00  1.33e-15  2.69    0.824   0.824
# … with 24 more rows, and abbreviated variable name ¹​statistic

Análise Fatorial

Análise Fatorial

# Instalar lavaanPlot
# install.packages("lavaanPlot")

# carregar pacote lavaanPlot
library(lavaanPlot)

# Exibir gráfico
lavaanPlot(model = fit)

Análise Fatorial

# Instalar lavaanPlot
# install.packages("lavaanPlot")

# carregar pacote lavaanPlot
library(lavaanPlot)

# Exibir gráfico
lavaanPlot(model = fit, 
           node_options = list(style = "filled",color = "YellowGreen"), coefs = TRUE, stars = c("regress"))

5. Comunicar

Comunicação

Conclusão

Onde Estudar?

https://www.escolavirtual.gov.br/curso/325

https://livro.curso-r.com/index.html

https://www.bigbookofr.com/index.html