Library

Package yang perlu di install untuk membantu pemodelan : ggplot2,dplyr,gmodels,plotrix,MASS,caret,tidyr,gtools,DT,PerformanceAnalytics,tidyverse,plyr.

library(ggplot2)
library(dplyr)
library(gmodels)
library(plotrix)
library(MASS)
library(caret)
library(tidyr)
library(gtools)
library(DT)
library(PerformanceAnalytics)
library(tidyverse)
library(corrplot)
library(plyr)

Input Data

Dataset yang digunakan merupakan data sekunder yang di dapat dari website Kaggle.

Dataset berasal dari hasil tes diabetes di rumah sakit Frankfurt, Jerman yang berisi variabel sebagai berikut :

  1. Pregnancies : jumlah kehamilan.
  2. Glucose : konsentrasi plasma glukosa 2 jam terakhir setelah tes toleransi glukosa oral.
  3. BloodPressure : tekanan darah diastolik(mm/Hg).
  4. SkinThickness : ketebalan lipatan kulit(mm).
  5. Insulin : Tes serum insulin 2 jam sebelumnya.
  6. BMI : indeks massa tubuh.
  7. DiabetesPedigreeFunction : fungsi turunan/silsilah diabetes.
  8. Age : umur.
  9. Outcome : hasil yang berupa variabel 0 atau 1.
diabetes <- read.csv("C:/Users/Anto/Documents/diabetes.csv")

Struktur Data

str(diabetes)
## 'data.frame':    2000 obs. of  9 variables:
##  $ Pregnancies             : int  2 0 0 0 1 0 4 8 2 2 ...
##  $ Glucose                 : int  138 84 145 135 139 173 99 194 83 89 ...
##  $ BloodPressure           : int  62 82 0 68 62 78 72 80 65 90 ...
##  $ SkinThickness           : int  35 31 0 42 41 32 17 0 28 30 ...
##  $ Insulin                 : int  0 125 0 250 480 265 0 0 66 0 ...
##  $ BMI                     : num  33.6 38.2 44.2 42.3 40.7 46.5 25.6 26.1 36.8 33.5 ...
##  $ DiabetesPedigreeFunction: num  0.127 0.233 0.63 0.365 0.536 ...
##  $ Age                     : int  47 23 31 24 21 58 28 67 24 42 ...
##  $ Outcome                 : int  1 0 1 1 0 0 0 0 0 0 ...
# create Outcome as factor
diabetes$Outcome <- as.character(diabetes$Outcome)
diabetes$Outcome[diabetes$Outcome == "0"] <- "No"
diabetes$Outcome[diabetes$Outcome == "1"] <- "Yes"
diabetes$Outcome <- as.factor(diabetes$Outcome)

summary(diabetes)
##   Pregnancies        Glucose      BloodPressure    SkinThickness   
##  Min.   : 0.000   Min.   :  0.0   Min.   :  0.00   Min.   :  0.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 63.50   1st Qu.:  0.00  
##  Median : 3.000   Median :117.0   Median : 72.00   Median : 23.00  
##  Mean   : 3.704   Mean   :121.2   Mean   : 69.15   Mean   : 20.93  
##  3rd Qu.: 6.000   3rd Qu.:141.0   3rd Qu.: 80.00   3rd Qu.: 32.00  
##  Max.   :17.000   Max.   :199.0   Max.   :122.00   Max.   :110.00  
##     Insulin            BMI        DiabetesPedigreeFunction      Age       
##  Min.   :  0.00   Min.   : 0.00   Min.   :0.0780           Min.   :21.00  
##  1st Qu.:  0.00   1st Qu.:27.38   1st Qu.:0.2440           1st Qu.:24.00  
##  Median : 40.00   Median :32.30   Median :0.3760           Median :29.00  
##  Mean   : 80.25   Mean   :32.19   Mean   :0.4709           Mean   :33.09  
##  3rd Qu.:130.00   3rd Qu.:36.80   3rd Qu.:0.6240           3rd Qu.:40.00  
##  Max.   :744.00   Max.   :80.60   Max.   :2.4200           Max.   :81.00  
##  Outcome   
##  No :1316  
##  Yes: 684  
##            
##            
##            
## 

View Data

Cek Missing Value

colSums(is.na(diabetes))
##              Pregnancies                  Glucose            BloodPressure 
##                        0                        0                        0 
##            SkinThickness                  Insulin                      BMI 
##                        0                        0                        0 
## DiabetesPedigreeFunction                      Age                  Outcome 
##                        0                        0                        0

Edit dataset

# create Na for Glucose
diabetes$Glucose <- as.character(diabetes$Glucose)
diabetes$Glucose[diabetes$Glucose == "0"] <- "Na" 
diabetes$Glucose <- as.integer(diabetes$Glucose)

# create Na for BloodPressure
diabetes$BloodPressure <- as.character(diabetes$BloodPressure)
diabetes$BloodPressure[diabetes$BloodPressure == "0"] <- "Na"
diabetes$BloodPressure <- as.integer(diabetes$BloodPressure)

# create Na for SkinThickness
diabetes$SkinThickness <- as.character(diabetes$SkinThickness)
diabetes$SkinThickness[diabetes$SkinThickness == "0"] <- "Na"
diabetes$SkinThickness <- as.integer(diabetes$SkinThickness)

# create Na for Insulin
diabetes$Insulin <- as.character(diabetes$Insulin)
diabetes$Insulin[diabetes$Insulin == "0"] <- "Na"
diabetes$Insulin <- as.integer(diabetes$Insulin)

# create Na for BMI
diabetes$BMI <- as.character(diabetes$BMI)
diabetes$BMI[diabetes$BMI == "0"] <- "Na"
diabetes$BMI <- as.integer(diabetes$BMI)


colSums(is.na(diabetes))
##              Pregnancies                  Glucose            BloodPressure 
##                        0                       13                       90 
##            SkinThickness                  Insulin                      BMI 
##                      573                      956                       28 
## DiabetesPedigreeFunction                      Age                  Outcome 
##                        0                        0                        0

Menghapus Na

diabetes_omit <- na.omit(diabetes)
str(diabetes_omit)
## 'data.frame':    1035 obs. of  9 variables:
##  $ Pregnancies             : int  0 0 1 0 2 4 2 7 6 2 ...
##  $ Glucose                 : int  84 135 139 173 83 125 81 195 154 117 ...
##  $ BloodPressure           : int  82 68 62 78 65 70 72 70 74 90 ...
##  $ SkinThickness           : int  31 42 41 32 28 18 15 33 32 19 ...
##  $ Insulin                 : int  125 250 480 265 66 122 76 145 193 71 ...
##  $ BMI                     : int  38 42 40 46 36 28 30 25 29 25 ...
##  $ DiabetesPedigreeFunction: num  0.233 0.365 0.536 1.159 0.629 ...
##  $ Age                     : int  23 24 21 58 24 45 25 55 39 21 ...
##  $ Outcome                 : Factor w/ 2 levels "No","Yes": 1 2 1 1 1 2 1 2 1 1 ...
##  - attr(*, "na.action")= 'omit' Named int [1:965] 1 3 7 8 10 11 13 14 15 20 ...
##   ..- attr(*, "names")= chr [1:965] "1" "3" "7" "8" ...
summary(diabetes_omit)
##   Pregnancies        Glucose      BloodPressure   SkinThickness  
##  Min.   : 0.000   Min.   : 56.0   Min.   : 24.0   Min.   : 7.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 62.0   1st Qu.:21.00  
##  Median : 2.000   Median :120.0   Median : 70.0   Median :29.00  
##  Mean   : 3.186   Mean   :122.8   Mean   : 70.8   Mean   :29.26  
##  3rd Qu.: 5.000   3rd Qu.:143.0   3rd Qu.: 78.0   3rd Qu.:37.00  
##  Max.   :17.000   Max.   :198.0   Max.   :110.0   Max.   :63.00  
##     Insulin           BMI        DiabetesPedigreeFunction      Age       
##  Min.   : 14.0   Min.   :18.00   Min.   :0.0850           Min.   :21.00  
##  1st Qu.: 76.5   1st Qu.:28.00   1st Qu.:0.2820           1st Qu.:23.00  
##  Median :126.0   Median :33.00   Median :0.4520           Median :27.00  
##  Mean   :153.9   Mean   :32.85   Mean   :0.5228           Mean   :30.67  
##  3rd Qu.:190.0   3rd Qu.:37.00   3rd Qu.:0.6845           3rd Qu.:36.00  
##  Max.   :744.0   Max.   :67.00   Max.   :2.4200           Max.   :81.00  
##  Outcome  
##  No :698  
##  Yes:337  
##           
##           
##           
## 

Proposi dari Hasil Tes

Visualisasi

Korelasi

chart.Correlation(diabetes_omit[,1:8], histogram=TRUE, pch=19)

Spliting Train Test

set.seed(308)
intrain <- sample(nrow(diabetes_omit), nrow(diabetes_omit)*0.7)
diabetes_train <- diabetes_omit[intrain,]
diabetes_test <- diabetes_omit[-intrain,]

Modeling

log_model <- glm(formula = Outcome~Pregnancies+Glucose+BloodPressure+SkinThickness+Insulin+BMI+DiabetesPedigreeFunction+Age, family = "binomial", data = diabetes_train)
summary(log_model)
## 
## Call:
## glm(formula = Outcome ~ Pregnancies + Glucose + BloodPressure + 
##     SkinThickness + Insulin + BMI + DiabetesPedigreeFunction + 
##     Age, family = "binomial", data = diabetes_train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.6913  -0.6563  -0.3803   0.5719   2.3236  
## 
## Coefficients:
##                           Estimate Std. Error z value Pr(>|z|)    
## (Intercept)              -9.878688   0.883339 -11.183  < 2e-16 ***
## Pregnancies               0.106995   0.041554   2.575 0.010029 *  
## Glucose                   0.041057   0.004239   9.687  < 2e-16 ***
## BloodPressure             0.005313   0.008762   0.606 0.544290    
## SkinThickness             0.025523   0.012016   2.124 0.033666 *  
## Insulin                  -0.001602   0.001059  -1.513 0.130378    
## BMI                       0.045158   0.018294   2.468 0.013569 *  
## DiabetesPedigreeFunction  1.155501   0.320731   3.603 0.000315 ***
## Age                       0.015000   0.013437   1.116 0.264295    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 906.68  on 723  degrees of freedom
## Residual deviance: 631.61  on 715  degrees of freedom
## AIC: 649.61
## 
## Number of Fisher Scoring iterations: 5

Metode Stepwise

log_model2 <- stepAIC(log_model, direction = "backward")
## Start:  AIC=649.61
## Outcome ~ Pregnancies + Glucose + BloodPressure + SkinThickness + 
##     Insulin + BMI + DiabetesPedigreeFunction + Age
## 
##                            Df Deviance    AIC
## - BloodPressure             1   631.98 647.98
## - Age                       1   632.86 648.86
## <none>                          631.61 649.61
## - Insulin                   1   633.92 649.92
## - SkinThickness             1   636.12 652.12
## - BMI                       1   637.83 653.83
## - Pregnancies               1   638.33 654.33
## - DiabetesPedigreeFunction  1   645.11 661.11
## - Glucose                   1   748.06 764.06
## 
## Step:  AIC=647.98
## Outcome ~ Pregnancies + Glucose + SkinThickness + Insulin + BMI + 
##     DiabetesPedigreeFunction + Age
## 
##                            Df Deviance    AIC
## - Age                       1   633.54 647.54
## <none>                          631.98 647.98
## - Insulin                   1   634.34 648.34
## - SkinThickness             1   636.51 650.51
## - Pregnancies               1   638.76 652.76
## - BMI                       1   639.59 653.59
## - DiabetesPedigreeFunction  1   645.21 659.21
## - Glucose                   1   749.60 763.60
## 
## Step:  AIC=647.54
## Outcome ~ Pregnancies + Glucose + SkinThickness + Insulin + BMI + 
##     DiabetesPedigreeFunction
## 
##                            Df Deviance    AIC
## <none>                          633.54 647.54
## - Insulin                   1   636.24 648.24
## - SkinThickness             1   639.62 651.62
## - BMI                       1   640.74 652.74
## - DiabetesPedigreeFunction  1   647.83 659.83
## - Pregnancies               1   654.11 666.11
## - Glucose                   1   763.19 775.19
summary(log_model2)
## 
## Call:
## glm(formula = Outcome ~ Pregnancies + Glucose + SkinThickness + 
##     Insulin + BMI + DiabetesPedigreeFunction, family = "binomial", 
##     data = diabetes_train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.7377  -0.6387  -0.3863   0.5563   2.4566  
## 
## Coefficients:
##                           Estimate Std. Error z value Pr(>|z|)    
## (Intercept)              -9.439455   0.772186 -12.224  < 2e-16 ***
## Pregnancies               0.141608   0.031456   4.502 6.74e-06 ***
## Glucose                   0.042298   0.004165  10.155  < 2e-16 ***
## SkinThickness             0.028880   0.011711   2.466 0.013659 *  
## Insulin                  -0.001734   0.001058  -1.639 0.101196    
## BMI                       0.046483   0.017570   2.646 0.008155 ** 
## DiabetesPedigreeFunction  1.182510   0.317536   3.724 0.000196 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 906.68  on 723  degrees of freedom
## Residual deviance: 633.54  on 717  degrees of freedom
## AIC: 647.54
## 
## Number of Fisher Scoring iterations: 5

Metode Stepwise akan menyeleksi variabel-variabel yang memilki pengaruh signifikan terhadap prediktor. Lihat bagian Step: AIC=647,54. Semakin kecil nilai AIC, maka semakin disarankan variabel prediktor yang dipilih dan nilai AIC paling kecil berada dibagian paling bawah tampilan.

diabetes_test$prob_diabetes<-predict(log_model2, type = "response", newdata = diabetes_test)

Hasil Prediksi

diabetes_test$pred_diabetes <- factor(ifelse(diabetes_test$prob_diabetes > 0.5, "Yes","No"))
diabetes_test[1:10, c("pred_diabetes", "Outcome")]
##     pred_diabetes Outcome
## 9              No      No
## 12             No     Yes
## 19             No      No
## 26             No      No
## 53             No      No
## 69             No      No
## 71             No     Yes
## 88             No      No
## 89            Yes     Yes
## 100            No     Yes
log_conf <- confusionMatrix(diabetes_test$pred_diabetes, diabetes_test$Outcome, positive = "Yes")
log_conf
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  No Yes
##        No  183  49
##        Yes  22  57
##                                          
##                Accuracy : 0.7717         
##                  95% CI : (0.721, 0.8172)
##     No Information Rate : 0.6592         
##     P-Value [Acc > NIR] : 1.029e-05      
##                                          
##                   Kappa : 0.4586         
##                                          
##  Mcnemar's Test P-Value : 0.002031       
##                                          
##             Sensitivity : 0.5377         
##             Specificity : 0.8927         
##          Pos Pred Value : 0.7215         
##          Neg Pred Value : 0.7888         
##              Prevalence : 0.3408         
##          Detection Rate : 0.1833         
##    Detection Prevalence : 0.2540         
##       Balanced Accuracy : 0.7152         
##                                          
##        'Positive' Class : Yes            
## 

Selanjutnya untuk mengetahui hasil prediksi dan tingkat akurasi dari data yang telah diprediksi dapat dilihat dengan menggunakan Confusion Matrix. Dimana confusion matrix adalah alat yang digunakan untuk menganalisis seberapa baik classifier dapat mengenali tuple dari kelas yang berbeda dimana kelas yang diprediksi, maka didapatkan hasil confusion matrix sebagai berikut:

Frekuensi prediksi pasien yang didiagnosa tidak memiliki penyakit diabetes dan sesuai dengan data actual pasien yang didiagnosa tidak memiliki penyakit diabetes sebanyak 183 orang maka disebut sebagai "True Positive".

Frekuensi prediksi pasien yang didiagnosa tidak memiliki penyakit diabetes namun pada data actual menunjukan pasien yang didiagnosa memiliki penyakit diabetes sebanyak 22 orang maka disebut sebagai "False Positive".