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.
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
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
##
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.