Introdução

De posse de dados sobre os candidatos a deputado nas eleições de 2014, buscamos nesta análise, prever aqueles que foram ou não eleitos.

1. Há desbalanceamento das classes (isto é, uma classe tem muito mais instâncias que outra)? Em que proporção?

Inicialmente, podemos observar que a variável de interesse define duas classes desbalanceadas, pois existem muito mais candidatos não eleitos, do que candidatos eleitos. Tal desbalanceamento pode causar problemas pois nosso modelo pode ficar enviesado.

table(data$situacao_final, useNA = "always")
## 
##     eleito nao_eleito       <NA> 
##        416       3719          0

Vamos então, tratar os dados

data_filtered <- data %>% 
  select(-nome, -UF, -numero_cadidato, -setor_economico_receita, -setor_economico_despesa, -descricao_ocupacao)

data_filtered$situacao_final <- as.factor(data_filtered$situacao_final)
#data_filtered$descricao_cor_raca <- as.factor(data_filtered$descricao_cor_raca)
#data_filtered$descricao_ocupacao <- as.factor(data_filtered$descricao_ocupacao)
#data_filtered$estado_civil <- as.factor(data_filtered$estado_civil)
#data_filtered$grau <- as.factor(data_filtered$grau)
#data_filtered$situacao_final <- as.factor(data_filtered$situacao_final)
#data_filtered$sexo <- as.factor(data_filtered$sexo)
#data_filtered$partido <- as.factor(data_filtered$partido)

any(is.na(data_filtered))
## [1] FALSE

Percebemos também, que não há valores faltando, prosseguimos então com a análise.

Como mencionado, os dados estão desbalanceados, então é importante que a variável alvo seja um factor, desta forma, a função createDataPartition separa partições de uma forma mais balanceada.

Faremos predições para diferentes modelos

Regressão Logística

dataPartition <- createDataPartition(y = data_filtered$situacao_final, p=0.75, list=FALSE)

train <- data_filtered[dataPartition, ]
test <- data_filtered[-dataPartition, ]

formula <- as.formula(situacao_final ~ .)

modelLogistic <- train(formula,
                 data = train,
                 method="glm",
                 family="binomial",      # se a variável for binária
                 na.action = na.omit)
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
test$predictionLogistic <- predict(modelLogistic, test)

confusionMatrix(test$predictionLogistic, test$situacao_final)
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   eleito nao_eleito
##   eleito         52         17
##   nao_eleito     52        912
##                                           
##                Accuracy : 0.9332          
##                  95% CI : (0.9162, 0.9477)
##     No Information Rate : 0.8993          
##     P-Value [Acc > NIR] : 8.542e-05       
##                                           
##                   Kappa : 0.5663          
##  Mcnemar's Test P-Value : 4.256e-05       
##                                           
##             Sensitivity : 0.50000         
##             Specificity : 0.98170         
##          Pos Pred Value : 0.75362         
##          Neg Pred Value : 0.94606         
##              Prevalence : 0.10068         
##          Detection Rate : 0.05034         
##    Detection Prevalence : 0.06680         
##       Balanced Accuracy : 0.74085         
##                                           
##        'Positive' Class : eleito          
## 

Árvore de Decisão

modelDecisionTree <- train(formula,
                 data=train,
                 method = "rpart",
                 cp=0.001,  # parâmetro de complexidade
                 maxdepth=20)


test$predictionDecisionTree <- predict(modelDecisionTree, test)

confusionMatrix(test$predictionDecisionTree, test$situacao_final)
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   eleito nao_eleito
##   eleito         76         41
##   nao_eleito     28        888
##                                           
##                Accuracy : 0.9332          
##                  95% CI : (0.9162, 0.9477)
##     No Information Rate : 0.8993          
##     P-Value [Acc > NIR] : 8.542e-05       
##                                           
##                   Kappa : 0.6505          
##  Mcnemar's Test P-Value : 0.1486          
##                                           
##             Sensitivity : 0.73077         
##             Specificity : 0.95587         
##          Pos Pred Value : 0.64957         
##          Neg Pred Value : 0.96943         
##              Prevalence : 0.10068         
##          Detection Rate : 0.07357         
##    Detection Prevalence : 0.11326         
##       Balanced Accuracy : 0.84332         
##                                           
##        'Positive' Class : eleito          
## 
#Não consegui rodar

#modelAdaboost <- train(formula,
#                data=train,
#                method = "adaboost")

#predictionAdaboost <- predict(modelAdaboost, test)

#confusionMatrix(predictionAdaboost, test$situacao_final)

A Matriz de confusão, é uma ferramenta que apresenta diversas métricas muito úteis para a análise da performance dos nossos modelos, através das matrizes dos modelos testados acima, percebemos que todos apresentaram um ótimo nível de acurácia, entretanto, tal métrica pode falhar na captura de casos importantes. Duas métricas importantes que podemos observar na matriz de confusão, são Especificidade e Sensitividade, as considerando, percebemos que o modelo utilizando árvores de decisão teve melhor sensitividade, ou seja, conseguiu predizer corretamente, uma maior porcentagem dos deputados eleitos.

Dada a nossa tarefa (predizer os deputados eleitos), a sensitividade (também conhecida como revocação) parece ser uma boa métrica.