Linear Regression

Nesta análise iremos explorar dados sobre as votações que candidatos à Câmara Federal de Deputados receberam nos anos de 2006 e 2010. A nossa tarefa é usar Regressão Linear para explicar essas votações. Esses dados foram extraídos do TSE, pré-processados e contemplam informações sobre aproximadamente 7.300 candidatos.

Importando dados

library(here)
library(dplyr)
library(readr)

here::set_here()

elections_2006_2010 = readr::read_csv(
  here::here("../data/tse/eleicoes_2006_e_2010.csv"),
  local=readr::locale("br"),
  col_types = cols(
    ano = col_integer(),
    sequencial_candidato = col_integer(),
    quantidade_doacoes = col_integer(),
    quantidade_doadores = col_integer(),
    total_receita = col_double(),
    media_receita = col_double(),
    recursos_de_outros_candidatos.comites = col_double(),
    recursos_de_pessoas_fisicas = col_double(),
    recursos_de_pessoas_juridicas = col_double(),
    recursos_proprios = col_double(),
    `recursos_de_partido_politico` = col_double(),
    quantidade_despesas = col_integer(),
    quantidade_fornecedores = col_integer(),
    total_despesa = col_double(),
    media_despesa = col_double(),
    votos = col_integer(),
    .default = col_character())
  )

Conhecendo os dados

elections_2006_2010 %>%
  glimpse()
## Observations: 7,476
## Variables: 24
## $ ano                                   <int> 2006, 2006, 2006, 2006, ...
## $ sequencial_candidato                  <int> 10001, 10002, 10002, 100...
## $ nome                                  <chr> "JOSÉ LUIZ NOGUEIRA DE S...
## $ uf                                    <chr> "AP", "RO", "AP", "MS", ...
## $ partido                               <chr> "PT", "PT", "PT", "PRONA...
## $ quantidade_doacoes                    <int> 6, 13, 17, 6, 48, 6, 14,...
## $ quantidade_doadores                   <int> 6, 13, 16, 6, 48, 6, 7, ...
## $ total_receita                         <dbl> 16600.00, 22826.00, 1581...
## $ media_receita                         <dbl> 2766.67, 1755.85, 9301.2...
## $ recursos_de_outros_candidatos.comites <dbl> 0.00, 6625.00, 2250.00, ...
## $ recursos_de_pessoas_fisicas           <dbl> 9000.00, 15000.00, 34150...
## $ recursos_de_pessoas_juridicas         <dbl> 6300.00, 1000.00, 62220....
## $ recursos_proprios                     <dbl> 1300.00, 201.00, 59500.0...
## $ recursos_de_partido_politico          <dbl> 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ quantidade_despesas                   <int> 14, 24, 123, 8, 133, 9, ...
## $ quantidade_fornecedores               <int> 14, 23, 108, 8, 120, 9, ...
## $ total_despesa                         <dbl> 16583.60, 20325.99, 1460...
## $ media_despesa                         <dbl> 1184.54, 846.92, 1187.09...
## $ cargo                                 <chr> "DEPUTADO FEDERAL", "DEP...
## $ sexo                                  <chr> "MASCULINO", "FEMININO",...
## $ grau                                  <chr> "ENSINO MÉDIO COMPLETO",...
## $ estado_civil                          <chr> "CASADO(A)", "SOLTEIRO(A...
## $ ocupacao                              <chr> "VEREADOR", "SERVIDOR PÚ...
## $ votos                                 <int> 8579, 2757, 17428, 1193,...

Existem 26 variáveis no nosso data frame e o seus significados são:

  • “Sequencial_candidato”: (character) id do candidato
  • “Nome”:
  • “Numero_cadidato”: (character)
  • “UF”: (character)
  • “Partido”: (character)
  • “Setor_economico_receita” : (character) setor econômico que mais doou (em quantidade de vezes) para o candidato;
  • “Quantidade_doacoes”: (integer)
  • “Quantidade_doadores”: (integer) número de doadores diferentes
  • “Total_receita”: (double) soma em R$ das doações
  • “Media_receita”: (double) média das doações
  • “recursos_de_outros_candidatos/comites”: (double) quantia em R$ das doações provenientes de outros candidatos ou comite partidário
  • “Recursos_de_partidos”: (double) quantia em R$ das doações provenientes de outros candidatos ou partidos
  • “Recursos_de_pessoas_físicas”: (double) quantia em R$ das doações provenientes de outros CPFs
  • “Recursos_de_pessoas_juridicas”: (double) quantia em R$ das doações provenientes de outros CNPJ
  • “Recursos_proprios”: (double) quantia em R$ das doações provenientes do próprio candidato
  • “Votos”: (integer) variável alvo. Se refere ao número de votos na campanha de 2014
  • “Quantidade_despesas”: (integer)
  • “Quantidade_fornecedores”: (integer) número de fornecedores/despesas diferentes
  • “Total_despesa”: (double) soma em R$ das despesas de campanha
  • “Media_despesa”: (double) média das despesas de campanha
  • “Setor_economico_despesa”: (character) setor econômico que o candidato mais gastou na campanha (em quantidade de vezes);
  • “Cargo”: (character)
  • “Idade”: (int)
  • “Sexo”: (character)
  • “Grau”: (character)
  • “Estado_civil”: (character)

Pela descrição, esperamos que algumas variáveis, como nome e sequencial_candidato, não influenciem na quantidade de votos. A var cargo também não influencia, pois todos as obersações tratam de deputados federais. No nosso primeiro modelo, não iremos utilizar tais variáveis, dado que já esperamos nenhum relacionamento entre elas e a variável voto.

Vamos plotar a distribuição das variáveis, desconsiderando as variáveis categóricas.

library(reshape2)
library(ggplot2)
library(scales)

remove_categorical_vars_converted = function(data) {
  return(
    data %>%
      select(-c(nome, uf, partido, cargo, sexo, grau, estado_civil, ocupacao))
  )
}

reshaped_data = 
  reshape2::melt(
    elections_2006_2010 %>%
      remove_categorical_vars_converted)

ggplot2::ggplot(reshaped_data, aes(x = value)) + 
  facet_wrap(~variable) + 
  geom_histogram() +
  scale_y_continuous(label = scales::unit_format(unit = "k", scale = 1e-3))  +
  scale_x_continuous(label = scales::unit_format(unit = "k", scale = 1e-3), limits = c(-1000, 10000))  +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

No geral a maioria dos valores das variáveis se concentram ao redor de 0. Esse não é o caso de votos. Votos tem um comportamento mais parecido com total_despesa, media_despesa, total_receita e media_receita.

Pré-processando

Convertendo vars categóricas em numéricas

categorics_to_numerics = function(dataframe) {
  converted_cols = dataframe %>%
    dplyr::mutate(
    uf = as.numeric(as.factor(uf)),
    nome = as.numeric(as.factor(nome)),
    partido = as.numeric(as.factor(partido)),
    grau = as.numeric(as.factor(grau)),
    estado_civil = as.numeric(as.factor(estado_civil)),
    ocupacao = as.numeric(as.factor(ocupacao)),
    cargo = as.numeric(as.factor(cargo)),
    sexo = as.numeric(as.factor(sexo)),
    sequencial_candidato = as.numeric(as.factor(sequencial_candidato)))
  return(converted_cols)
}

elections_2006_2010 = elections_2006_2010 %>% categorics_to_numerics

Filtrando para gerar dois datasets, um para cada ano (2006 e 2010).

elections_2006 = elections_2006_2010 %>% filter(ano == 2006)
elections_2010 = elections_2006_2010 %>% filter(ano == 2010)

Treino, Validação e Teste

Criando uma função auxiliar para dividir um dataset de entrada em três de saída (treino, validação e teste).

# create a train, validation and tests from the original data frame 
create_train_validate_test = function(dataframe) {
  assignment = sample(
    1:3, size = nrow(elections_2010), 
    prob = c(0.6, 0.2, 0.2), replace = TRUE)

  smp_train = dataframe[assignment == 1, ]
  smp_valid = dataframe[assignment == 2, ]
  smp_test = dataframe[assignment == 3, ]
  
  return(list(smp_train, smp_valid, smp_test))
}

1. Um modelo de regressão múltipla com todas as variáveis é plausível para explicar a variação em y (número de votos)?

De certo modo já respondemos a essa pergunta. Mais acima, avaliamos que as variáveis abaixo não seriam significantes para a predição:

  • sequencial_candidato
  • nome
  • cargo

Ainda pode haver outras variáveis que também não são boas preditoras. Para poder identificá-las, iremos gerar o modelo e posteriormente avaliá-lo.

Construindo o modelo

1.1 Em 2006

Dividindo os dados e criando o set para treino do modelo:

## set seed to make partition reproducible
set.seed(123)

splitted = create_train_validate_test(elections_2006)
train_2006 = splitted[[1]]
valid_2006 = splitted[[2]]
test_2006 = splitted[[3]]

Função para não usar as variáveis que já julgamos como ruins preditoras.

remove_non_related_vars = function(data) {
    return(
    data %>%
      select(-c(ano, nome, sequencial_candidato, cargo))
  )
}

Instanciando o modelo:

regression_linear_model_all_vars = function(train_data) {
  filtered_traind_data = train_data %>% remove_non_related_vars
  model_all_vars_2006 = lm(data = filtered_traind_data, votos ~ .)
  return(model_all_vars_2006)
}

model_all_vars_2006 = regression_linear_model_all_vars(train_2006)

1.2 Para eleições de 2010.

Dividindo os dados e criando o set para treino do modelo:

splitted = create_train_validate_test(elections_2010)
train_2010 = splitted[[1]]
valid_2010 = splitted[[2]]
test_2010  = splitted[[3]]

model_all_vars_2010 = regression_linear_model_all_vars(train_2010)

2. Comparando e avaliando regressões

2.1 Para eleições de 2006

Analisando predição

  predictions = predict.lm(model_all_vars_2006, valid_2006)
  votos = valid_2006$votos
  
  predictions_plot = extendrange(c(votos, predictions)) +
    plot(votos, predictions, main="Resíduos vs. Predições") +
    abline(0, 1, col="blue", lty=2, lwd=2)

A linha azul representa o modelo e os pontos são as predições feitas com o set de dados de validação (diferente do set usado para treinar o modelo). A ideia aqui é que quanto mais próximos os pontos da linha azul, melhor o modelo. Como há pontos bastante distantes, então o modelo parece não descrever bem os dados.

Analisando resíduos

residuos = valid_2006$votos - predictions

residuos_plot = plot(predictions, residuos, main="Análise de Resíduos") +
  abline(h=0,col="blue",lty=2,lwd=2)

É possível perceber que os resíduos não são simétricos e possuem um padrão de comportamento (o ideal é que fossem aleatórios). Isso indica que o modelo ainda precisa de aprimoramentos e transformações.

residuos_fit_plot = plot(model_all_vars_2006, which = 1)

O objetivo deste gráfico é verificar a não existência de padrão no comportamento dos erros, já que esses erros devem ser aleatórios. Aqui novamente identifica-se padrão nos erros.

O próximo gráfico procura identificar se os resíduos têm distribuição normal:

normal_plot = qqnorm(model_all_vars_2006$residuals)
qqline(model_all_vars_2006$residuals, col = 2,lwd=2,lty=2)

Aqui vemos que os pontos estão muito desajustados à linha reta, o que não é a situação ideal. Perceba que os pontos se curvam nas extremidades. Isso pode significar que nossos dados possuem mais valores extremos do que esperado caso tivessem uma distribuição normal.

Sumarizando o modelo:

summary(model_all_vars_2006)
## 
## Call:
## lm(formula = votos ~ ., data = filtered_traind_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -213282   -8682   -4457     738  629746 
## 
## Coefficients: (1 not defined because of singularities)
##                                         Estimate Std. Error t value
## (Intercept)                            114.33034 6183.31607   0.018
## uf                                     -92.27640  105.07241  -0.878
## partido                               -181.35374   94.95068  -1.910
## quantidade_doacoes                     -36.36633  168.96426  -0.215
## quantidade_doadores                    333.79963  184.88470   1.805
## total_receita                           -0.16358    0.03049  -5.365
## media_receita                            1.26002    0.14945   8.431
## recursos_de_outros_candidatos.comites    0.06860    0.03222   2.129
## recursos_de_pessoas_fisicas              0.20945    0.03244   6.458
## recursos_de_pessoas_juridicas            0.14312    0.02591   5.524
## recursos_proprios                        0.07568    0.02722   2.780
## recursos_de_partido_politico                  NA         NA      NA
## quantidade_despesas                    -34.29644   18.69085  -1.835
## quantidade_fornecedores                 -2.77541   22.98789  -0.121
## total_despesa                            0.13985    0.01777   7.870
## media_despesa                            0.04180    0.53900   0.078
## sexo                                  4811.78126 2428.41033   1.981
## grau                                   734.54909  465.12736   1.579
## estado_civil                          -446.26966  652.52800  -0.684
## ocupacao                               -32.69496   15.71190  -2.081
##                                       Pr(>|t|)    
## (Intercept)                            0.98525    
## uf                                     0.37993    
## partido                                0.05628 .  
## quantidade_doacoes                     0.82961    
## quantidade_doadores                    0.07115 .  
## total_receita                         9.02e-08 ***
## media_receita                          < 2e-16 ***
## recursos_de_outros_candidatos.comites  0.03335 *  
## recursos_de_pessoas_fisicas           1.33e-10 ***
## recursos_de_pessoas_juridicas         3.74e-08 ***
## recursos_proprios                      0.00549 ** 
## recursos_de_partido_politico                NA    
## quantidade_despesas                    0.06666 .  
## quantidade_fornecedores                0.90391    
## total_despesa                         5.71e-15 ***
## media_despesa                          0.93819    
## sexo                                   0.04767 *  
## grau                                   0.11444    
## estado_civil                           0.49411    
## ocupacao                               0.03757 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 35390 on 2043 degrees of freedom
##   (352 observations deleted due to missingness)
## Multiple R-squared:  0.4861, Adjusted R-squared:  0.4815 
## F-statistic: 107.3 on 18 and 2043 DF,  p-value: < 2.2e-16

Este sumário trás dois importantes índices: o RSE (residual standard error) e o R² (R-squared). O primeiro fornece uma medida absoluta de falta de ajuste do modelo aos dados. Já o R² indica a proporção da variabilidade da variável alvo explicada pelo modelo. No caso do modelo acima, por exemplo, ele explica 48% dos dados, assim podemos afirmar que este modelo é razoável para explicar a quantidade de votos de um candidato.

2.2 Para eleições de 2010

Plotando os gráficos de diagnóstico:

diagnostic_plots = function(model, valid_set) {
  
  Predictions = predict.lm(model, valid_set)
  Votos = valid_set$votos
  predictions_plot = extendrange(c(Votos, Predictions)) +
    plot(Votos, Predictions, main="Resíduos vs Predição") +
    abline(0, 1, col="blue", lty=2, lwd=2)
  predictions_plot
  
  Residuos = Votos - Predictions
  residuos_plot = plot(Predictions, Residuos, main="Análise de Resíduos") +
    abline(h=0,col="blue",lty=2,lwd=2)
  residuos_plot
  
  residuos_fit_plot = plot(model, which = 1)
  
  normal_plot = qqnorm(model$residuals)
  qqline(model$residuals, col = 2,lwd=2,lty=2)
}
diagnostic_plots(model_all_vars_2010, valid_2006)

Percebe-se que os mesmos problemas enfrentados para o modelo do ano de 2006 são encontrados para este modelo também (assimetria e padronização dos resíduos, comportamento foge da distribuição normal, etc).

Sumarizando:

summary(model_all_vars_2010)
## 
## Call:
## lm(formula = votos ~ ., data = filtered_traind_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -240420   -8884   -5136    -607 1303183 
## 
## Coefficients: (1 not defined because of singularities)
##                                         Estimate Std. Error t value
## (Intercept)                            9.154e+03  5.992e+03   1.528
## uf                                    -1.659e+02  1.113e+02  -1.490
## partido                               -1.661e+02  9.693e+01  -1.714
## quantidade_doacoes                    -9.354e+01  8.059e+01  -1.161
## quantidade_doadores                    1.422e+02  9.626e+01   1.477
## total_receita                         -3.152e-02  1.364e-02  -2.311
## media_receita                         -2.696e-01  6.927e-02  -3.892
## recursos_de_outros_candidatos.comites  2.831e-02  8.358e-03   3.387
## recursos_de_pessoas_fisicas            5.303e-02  1.322e-02   4.011
## recursos_de_pessoas_juridicas          1.364e-03  7.807e-03   0.175
## recursos_proprios                     -2.315e-02  6.767e-03  -3.421
## recursos_de_partido_politico                  NA         NA      NA
## quantidade_despesas                    2.010e+01  1.362e+01   1.476
## quantidade_fornecedores               -3.881e+01  1.614e+01  -2.404
## total_despesa                          1.065e-01  1.353e-02   7.866
## media_despesa                          1.747e-01  1.044e-01   1.673
## sexo                                   3.752e+03  2.268e+03   1.654
## grau                                   6.504e+02  4.737e+02   1.373
## estado_civil                          -1.259e+03  6.383e+02  -1.973
## ocupacao                              -4.145e+01  1.712e+01  -2.421
##                                       Pr(>|t|)    
## (Intercept)                           0.126693    
## uf                                    0.136226    
## partido                               0.086714 .  
## quantidade_doacoes                    0.245887    
## quantidade_doadores                   0.139807    
## total_receita                         0.020922 *  
## media_receita                         0.000102 ***
## recursos_de_outros_candidatos.comites 0.000718 ***
## recursos_de_pessoas_fisicas           6.23e-05 ***
## recursos_de_pessoas_juridicas         0.861330    
## recursos_proprios                     0.000635 ***
## recursos_de_partido_politico                NA    
## quantidade_despesas                   0.139987    
## quantidade_fornecedores               0.016285 *  
## total_despesa                         5.45e-15 ***
## media_despesa                         0.094459 .  
## sexo                                  0.098240 .  
## grau                                  0.169827    
## estado_civil                          0.048637 *  
## ocupacao                              0.015557 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 40780 on 2447 degrees of freedom
## Multiple R-squared:  0.4172, Adjusted R-squared:  0.4129 
## F-statistic: 97.33 on 18 and 2447 DF,  p-value: < 2.2e-16

O R² para os dados de 2010 é menor que aquele para os dados de 2006.

Quais variáveis conseguem explicar melhor o número de votos?

Se retornarmos ao sumário dos modelos, perceberemos que muitas variáveis têm um p-valor maior que 0.05. Para essas variáveis, suas chances de estarem relacionadas à variável voto por aleatoriedade é muito alta. Desse modo, poderíamos ter um modelo com mesma significância porém mais simples se removêssemos essas variáveis com o p-valor maior que 0.05. Se assim procedermos, para 2006 ficaremos com:

  • total_receita
  • media_receita
  • recursos_de_outros_candidatos.comites
  • recursos_de_pessoas_fisicas
  • recursos_de_pessoas_juridicas
  • recursos_proprios
  • total_despesa
  • sexo
  • ocupacao

Para 2010, fazendo a mesmo análise, obtemos o seguinte conjunto:

  • uf
  • partido
  • quantidade_doacoes
  • quantidade_doadores
  • total_receita
  • media_receita
  • recursos_de_outros_candidatos.comites
  • recursos_de_pessoas_fisicas
  • quantidade_fornecedores
  • total_despesa
  • media_despesa
  • sexo
  • grau

Para responder à pergunta, é também interessante olhar a correlação entre a feature/variável independente e a variável alvo/dependent (nesse caos, votos). Faremos isso a seguir.

3. Todas as variáveis são úteis para os modelos de regressão? Há variáveis redudantes?

Para identificar se há variáveis redundantes, podemos avaliar a correlação entre elas. Se duas variáveis forem fortemente correlacioandas, então uma delas é redundante.

Para 2006:

library(GGally)

corr_plot = function(data) {
  corr = data %>% remove_non_related_vars %>% cor() %>% round(2)
  corr %>%
    GGally::ggcorr(label_size = 3, label = TRUE, label_color = "black", hjust = 0.925, size = 3.5, angle = -45)
}

corr_plot(elections_2006)

Olhando para a linha de total_receita, percebemos que está consideralvemente correlacionadas com muitas outras variáveis, por exemplo:

  • media_receita (0.8)
  • recursos_de_pessoas_fisicas (0.7)
  • recursos_de_pessoas_juridicas (1)
  • recursos_proprios (0.7)
  • quantidade_despesas (0.9)
  • quantidade_fornecedores (0.9)
  • total_depesa (1)

Estamos usando o limite 0.7 para identificar redundância. Acima ou igual a esse valor estaremos classificando uma correlação como forte e portanto identificando uma relaçaõ redudante no contexto de nosso modelo.

Há muitas outras áreas em vermelho no gráfico, sugerindo que outras variáveis também possuem considerável correlaçaõ entre si, a exemplo de quantidade_despesas e quantidade_fornecedores (1).
Se muitas variáveis independentes são redundantes, não podemos avaliar bem a participação de cada uma delas para explicar a variável alvo (no nosso caso, votos), pois diferentes variáveis têm o mesmo efeito na mesma parcela de dados da variável dependente (voto).

Vamos agora avaliar considerando os dados de 2010:

corr_plot(elections_2010)

A situação é bastante parecida com o caso de 2006.

4. Construindo um novo modelo sem as variáveis redudantes

Existem alguns algortimos amplamente usados para realizar seleção de features para modelos, a exemplo de LASSO e Elastic Net. Para este relatório, contudo, por simplicidade, utilizamos algumas abordagens de caráter mais força bruta. Para decidir quais features redundantes não usar no nosso modelo, consideramos também o p-valor e a correlação da variável e com a variável alvo.

Modelo para os dados de 2006

input = train_2006 %>% 
  remove_non_related_vars %>%
  select(votos, recursos_proprios, total_despesa, quantidade_doadores, recursos_de_pessoas_fisicas)

final_model_2006 = lm(data = input, formula = votos ~ .)

Avaliando RSE e R2:

summary(final_model_2006)
## 
## Call:
## lm(formula = votos ~ ., data = input)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -174667   -8659   -7423   -1635  651975 
## 
## Coefficients:
##                               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                  8.007e+03  9.401e+02   8.517  < 2e-16 ***
## recursos_proprios           -4.197e-02  1.059e-02  -3.962 7.67e-05 ***
## total_despesa                1.172e-01  4.702e-03  24.932  < 2e-16 ***
## quantidade_doadores          1.734e+02  2.504e+01   6.924 5.87e-12 ***
## recursos_de_pessoas_fisicas  3.497e-02  1.876e-02   1.864   0.0624 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 37200 on 2057 degrees of freedom
##   (352 observations deleted due to missingness)
## Multiple R-squared:  0.4281, Adjusted R-squared:  0.427 
## F-statistic:   385 on 4 and 2057 DF,  p-value: < 2.2e-16

Em comparação ao modelo anterior para 2006, com todas mais variáveis, o RSE aumentou e o R² diminui aproximadamente 0.06. O modelo tornou-se um pouco menos significativo sem as variáveis redundantes.

Modelo sem variáveis redundantes para os dados de 2010

input = train_2010 %>% 
  remove_non_related_vars %>%
  select(votos, total_despesa, recursos_de_outros_candidatos.comites, recursos_proprios, media_receita)

final_model_2010 = lm(data = input, formula = votos ~ .)

Avaliando RSE e R²:

summary(final_model_2010)
## 
## Call:
## lm(formula = votos ~ ., data = input)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -242487   -8225   -7353   -3347 1298929 
## 
## Coefficients:
##                                         Estimate Std. Error t value
## (Intercept)                            8.528e+03  9.090e+02   9.382
## total_despesa                          7.380e-02  2.392e-03  30.849
## recursos_de_outros_candidatos.comites  2.703e-02  6.570e-03   4.113
## recursos_proprios                     -3.597e-02  4.957e-03  -7.257
## media_receita                         -2.183e-01  5.014e-02  -4.354
##                                       Pr(>|t|)    
## (Intercept)                            < 2e-16 ***
## total_despesa                          < 2e-16 ***
## recursos_de_outros_candidatos.comites 4.03e-05 ***
## recursos_proprios                     5.27e-13 ***
## media_receita                         1.39e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 41350 on 2461 degrees of freedom
## Multiple R-squared:  0.3976, Adjusted R-squared:  0.3966 
## F-statistic: 406.1 on 4 and 2461 DF,  p-value: < 2.2e-16

Para 2010, o impacto de tirar as variáveis redundantes foi muito insignificativo. O RSE aumentou pouco e o R² diminui pouquíssimo. Dado que o modelo tornou-se muito mais simples, retirar as variáveis redundantes foi bom.

5. Construindo uma regressão considerando os anos 2006 e 2010 em conjunto, que diferenças/semelhanças você percebe em relação aos modelos individuais por ano?

Separando entre dados de treino, validação e teste:

set.seed(123)

splitted = create_train_validate_test(elections_2006_2010)
train_set = splitted[[1]]
valid_set = splitted[[2]]
test_set = splitted[[3]]

Construindo o modelo:

linear_regression_model = lm(data = train_set, 
                             formula = 
                               votos ~ 
                               total_despesa + 
                               sqrt(total_despesa) +
                               quantidade_doadores + 
                               recursos_proprios + 
                               total_despesa * quantidade_doadores + 
                               total_despesa * recursos_proprios)

Avaliando o modelo:

diagnostic_plots(linear_regression_model, valid_set)

summary(linear_regression_model)
## 
## Call:
## lm(formula = votos ~ total_despesa + sqrt(total_despesa) + quantidade_doadores + 
##     recursos_proprios + total_despesa * quantidade_doadores + 
##     total_despesa * recursos_proprios, data = train_set)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -119755   -8759    -254    4828 1265715 
## 
## Coefficients:
##                                     Estimate Std. Error t value Pr(>|t|)
## (Intercept)                       -8.043e+03  8.487e+02  -9.477  < 2e-16
## total_despesa                     -2.304e-02  4.126e-03  -5.584 2.49e-08
## sqrt(total_despesa)                1.374e+02  5.384e+00  25.514  < 2e-16
## quantidade_doadores                8.089e+01  1.566e+01   5.165 2.51e-07
## recursos_proprios                 -4.853e-02  7.670e-03  -6.327 2.74e-10
## total_despesa:quantidade_doadores -2.689e-05  5.292e-06  -5.081 3.90e-07
## total_despesa:recursos_proprios    6.051e-09  2.233e-09   2.710  0.00675
##                                      
## (Intercept)                       ***
## total_despesa                     ***
## sqrt(total_despesa)               ***
## quantidade_doadores               ***
## recursos_proprios                 ***
## total_despesa:quantidade_doadores ***
## total_despesa:recursos_proprios   ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 35960 on 4469 degrees of freedom
## Multiple R-squared:  0.479,  Adjusted R-squared:  0.4783 
## F-statistic: 684.7 on 6 and 4469 DF,  p-value: < 2.2e-16

A análise dos resíduos indica que o modelo não teve melhoras significantes. A distribuíção dos resíduos ainda foge da distribuição normal nas extremidades. Mas os índices RSE e R² indicam que o modelo pode obter resultados melhores.

Italo Batista

7 de outubro de 2018