Linear Regression
Linear Regression
- Importando dados
- Conhecendo os dados
- Pré-processando
- Treino, Validação e Teste
- 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)?
- 2. Comparando e avaliando regressões
- 3. Todas as variáveis são úteis para os modelos de regressão? Há variáveis redudantes?
- 4. Construindo um novo modelo sem as variáveis redudantes
- 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?
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_numericsFiltrando 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.