Pacotes usados

library(corrplot)
## corrplot 0.92 loaded
library(readr)
library(caret)
## Carregando pacotes exigidos: ggplot2
## Carregando pacotes exigidos: lattice
library(rpart)
library(rpart.plot)
library(ROSE)
## Loaded ROSE 0.0-4
library(caTools)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

Carregamento do dataset e prévia

Fonte do dataset: https://data.mendeley.com/datasets/wj9rwkp9c2/1

Cada observação do dataset é uma paciente, com dados extraídos por meio de exames clínicos.

Traduzi os nomes das variáveis para fins de melhor entendimento do nosso estudo.

Removi as predições já existentes no dataset original, para trabalhar somente com os diagnósticos confirmados e simplificar o modelo para o binarismo.

diabetes <- read_csv("diabetes_dataset.csv", show_col_types = FALSE)

summary(diabetes)
##   id_paciente           sexo               idade          ureia        
##  Min.   :     123   Length:947         Min.   :20.0   Min.   :   0.50  
##  1st Qu.:   24064   Class :character   1st Qu.:51.0   1st Qu.:   3.70  
##  Median :   34390   Mode  :character   Median :55.0   Median :   4.60  
##  Mean   :  282095                      Mean   :54.1   Mean   :  12.37  
##  3rd Qu.:   45370                      3rd Qu.:59.0   3rd Qu.:   5.70  
##  Max.   :75435657                      Max.   :79.0   Max.   :6833.00  
##  nivel_creatinina glicose_sangue     colesterol     triglicerideos  
##  Min.   :  6.0    Min.   : 0.900   Min.   : 0.000   Min.   : 0.300  
##  1st Qu.: 48.0    1st Qu.: 6.800   1st Qu.: 4.000   1st Qu.: 1.500  
##  Median : 60.0    Median : 8.100   Median : 4.800   Median : 2.000  
##  Mean   : 69.1    Mean   : 8.409   Mean   : 4.879   Mean   : 2.362  
##  3rd Qu.: 73.0    3rd Qu.:10.200   3rd Qu.: 5.600   3rd Qu.: 2.900  
##  Max.   :800.0    Max.   :16.000   Max.   :10.300   Max.   :13.800  
##  colesterol_hdl  colesterol_ldl  colesterol_vldl       imc       
##  Min.   :0.200   Min.   :0.300   Min.   : 0.100   Min.   :19.00  
##  1st Qu.:0.900   1st Qu.:1.800   1st Qu.: 0.700   1st Qu.:27.00  
##  Median :1.100   Median :2.500   Median : 1.000   Median :30.00  
##  Mean   :1.209   Mean   :2.616   Mean   : 1.903   Mean   :29.89  
##  3rd Qu.:1.300   3rd Qu.:3.300   3rd Qu.: 1.500   3rd Qu.:33.00  
##  Max.   :9.900   Max.   :9.900   Max.   :35.000   Max.   :47.75  
##   diagnostico    
##  Min.   :0.0000  
##  1st Qu.:1.0000  
##  Median :1.0000  
##  Mean   :0.8912  
##  3rd Qu.:1.0000  
##  Max.   :1.0000

Ausência de NAs e nenhuma irregularidade nos dados, algo positivo para criação dos modelos.

Para inclusão do sexo do paciente no plot, vamos codificar os pacientes masculinos como 0 e as pacientes femininas como 1.

diabetes$sexo[diabetes$sexo == 'F'] <- 1
diabetes$sexo[diabetes$sexo == 'M'] <- 0
diabetes$sexo <- as.numeric(diabetes$sexo)

Plot de correlação entre os dados e distribuições

matriz_correlacao <- diabetes %>% 
  select(c(2:13)) %>% as.matrix()

corrplot(cor(matriz_correlacao), 
         type = "lower", 
         diag = FALSE)

Como podemos observar, existem correlações diretamente proporcionais entre o diagnóstico positivo de diabetes e:

Usaremos essas variáveis para o nosso modelo preditivo, excluindo as demais pela correlação muito próxima de 0 apresentada.

Balanceamento do dataset

Não é necessário, pois os diagnósticos positivos são maioria no dataset original. Caso fossem minoria, seria necessário fazer um oversample visando o balanceamento do dataset

prop.table(table(diabetes$diagnostico))
## 
##         0         1 
## 0.1087645 0.8912355

Dataset de treino e teste

Criação dos datasets de treino do modelo e teste.

split <- sample.split(diabetes$idade, SplitRatio = 0.7)

dataset_treino <- subset(diabetes, split == TRUE)
dataset_treino <- dataset_treino %>%
  select(glicose_sangue, imc, idade, colesterol, triglicerideos, diagnostico)

dataset_teste <- subset(diabetes, split == FALSE)
dataset_teste <- dataset_teste %>% 
  select(glicose_sangue, imc, idade, colesterol, triglicerideos)

Modelos escolhidos

Optaremos pela regressão logística e árvore de decisões, apropriadas para criação de modelos preditivos visando a descoberta de variáveis binárias.

Regressão Logística

modelo_diabetes_rl <- glm(diagnostico ~ glicose_sangue + imc + idade + colesterol + triglicerideos, 
                       data = dataset_treino, 
                       family = "binomial")

Árvore de Decisões

modelo_diabetes_rpart <- rpart(diagnostico ~ glicose_sangue + imc + idade + colesterol + triglicerideos, 
                               data = dataset_treino)

Resultados

Obtenção de predições usando predict e criação dos datasets de resultados

Regressão Logística

resultados_rl <- cbind(dataset_teste, 
                    diagnostico = ifelse(predict(modelo_diabetes_rl, newdata = dataset_teste, type = "response") > 0.5, 1, 0))

resultados_rl <- resultados_rl %>% as_tibble()

print(resultados_rl)
## # A tibble: 282 × 6
##    glicose_sangue   imc idade colesterol triglicerideos diagnostico
##             <dbl> <dbl> <dbl>      <dbl>          <dbl>       <dbl>
##  1            4.9    23    26        3.7            1.4           0
##  2            4      24    50        3.6            1.3           0
##  3            4      24    48        2.9            0.8           0
##  4            4      21    43        3.8            0.9           0
##  5            4      21    33        4              1.1           0
##  6            5.4    21    50        5.3            0.8           0
##  7            4      23    49        4.4            0.9           0
##  8            5      21    39        4.6            1.3           0
##  9            5.5    19    30        5.5            1.8           0
## 10            5.4    22    33        3.7            1.3           0
## # … with 272 more rows

Árvore de Decisões

resultados_rpart <- cbind(dataset_teste, 
                    diagnostico = ifelse(predict(modelo_diabetes_rpart, newdata = dataset_teste, type = "matrix") > 0.5, 1, 0))

resultados_rpart <- resultados_rpart %>% as_tibble()

print(resultados_rpart)
## # A tibble: 282 × 6
##    glicose_sangue   imc idade colesterol triglicerideos diagnostico
##             <dbl> <dbl> <dbl>      <dbl>          <dbl>       <dbl>
##  1            4.9    23    26        3.7            1.4           0
##  2            4      24    50        3.6            1.3           0
##  3            4      24    48        2.9            0.8           0
##  4            4      21    43        3.8            0.9           0
##  5            4      21    33        4              1.1           0
##  6            5.4    21    50        5.3            0.8           1
##  7            4      23    49        4.4            0.9           0
##  8            5      21    39        4.6            1.3           0
##  9            5.5    19    30        5.5            1.8           1
## 10            5.4    22    33        3.7            1.3           0
## # … with 272 more rows

Teste de precisão

Criação da matriz para validação da precisão dos modelos.

Regressão Logística

matriz_precisao_rl <- table(real = dataset_treino$diagnostico[sample(x = nrow(dataset_treino), size = nrow(dataset_teste))],
                         predicao = resultados_rl$diagnostico)

validacao_rl <- confusionMatrix(matriz_precisao_rl)

print(validacao_rl)
## Confusion Matrix and Statistics
## 
##     predicao
## real   0   1
##    0   4  33
##    1  27 218
##                                           
##                Accuracy : 0.7872          
##                  95% CI : (0.7348, 0.8335)
##     No Information Rate : 0.8901          
##     P-Value [Acc > NIR] : 1.0000          
##                                           
##                   Kappa : -0.0023         
##                                           
##  Mcnemar's Test P-Value : 0.5186          
##                                           
##             Sensitivity : 0.12903         
##             Specificity : 0.86853         
##          Pos Pred Value : 0.10811         
##          Neg Pred Value : 0.88980         
##              Prevalence : 0.10993         
##          Detection Rate : 0.01418         
##    Detection Prevalence : 0.13121         
##       Balanced Accuracy : 0.49878         
##                                           
##        'Positive' Class : 0               
## 

Árvore de Decisões

matriz_precisao_rpart <- table(real = dataset_treino$diagnostico[sample(x = nrow(dataset_treino), size = nrow(dataset_teste))],
                         predicao = resultados_rpart$diagnostico)

validacao_rpart <- confusionMatrix(matriz_precisao_rpart)

print(validacao_rpart)
## Confusion Matrix and Statistics
## 
##     predicao
## real   0   1
##    0   3  30
##    1  23 226
##                                           
##                Accuracy : 0.8121          
##                  95% CI : (0.7615, 0.8559)
##     No Information Rate : 0.9078          
##     P-Value [Acc > NIR] : 1.0000          
##                                           
##                   Kappa : -0.0016         
##                                           
##  Mcnemar's Test P-Value : 0.4098          
##                                           
##             Sensitivity : 0.11538         
##             Specificity : 0.88281         
##          Pos Pred Value : 0.09091         
##          Neg Pred Value : 0.90763         
##              Prevalence : 0.09220         
##          Detection Rate : 0.01064         
##    Detection Prevalence : 0.11702         
##       Balanced Accuracy : 0.49910         
##                                           
##        'Positive' Class : 0               
## 

A precisão de ambos os modelos está acima de 70%, significando uma maioria de predições corretas.

Plot da árvore de decisões do modelo

rpart.plot(modelo_diabetes_rpart, type = 4, extra = 1)