Diabetes melitus (DM) merupakan satu masalah kesehatan yang besar. Menurut International Diabetes Federation (IDF) tahun 2015, penderita diabetes melitus tertinggi terdapat di Cina dengan jumlah penderita sebanyak 109,6 juta jiwa, diikuti India dan USA dengan masing-masing jumlah penderita diabetes sebanyak 69,2 juta jiwa dan 29,3 juta jiwa. Indonesia menduduki urutan ke 7 tertinggi dengan jumlah populasi yang terkena diabetes mencapai 10 juta jiwa dan diperkirakan akan meningkat menjadi16,2 juta jiwa pada tahun 2040.
Penyempitan pembuluh darah
Bisa menyebabkan kerusakan pada mata
Menimbulkan hiperglikemia dan hipoglikemia
Kerusakan pada saraf
Kerusakan pada ginjal
Masalah pada kaki
Secara umum, diabetes mellitus bisa dibedakan menjadi dua jenis, yaitu diabetes tipe 1 dan tipe 2.
Diabetes tipe 1 terjadi karena adanya kondisi autoimun, di mana sistem kekebalan tubuh pengidap sendiri yang menyerang dan menghancurkan sel-sel pankreas yang memproduksi insulin. Hal ini mengakibatkan kadar gula darah jadi meningkat, sehingga memicu terjadinya kerusakan pada organ-organ tubuh. Masih belum diketahui apa penyebab kondisi autoimun ini. Namun, dugaan paling kuat adalah karena adanya faktor genetik yang dimiliki pengidap dan ditambah lagi dengan faktor lingkungan.
Diabetes tipe 2 merupakan jenis diabetes yang lebih sering terjadi. Diabetes ini disebabkan karena sel-sel tubuh kurang sensitif terhadap insulin, sehingga insulin yang dihasilkan tidak bisa dipergunakan dengan baik (resistensi sel tubuh terhadap insulin). Hampir sebagian besar pengidap diabetes di dunia mengalami diabetes tipe 2.
Berikut ini faktor-faktor risiko diabetes tipe 1:
Memiliki anggota keluarga yang mengidap diabetes tipe 1
Terkena infeksi virus
Orang berkulit putih dipercaya lebih berisiko mengalami diabetes tipe 1 dibandingkan ras lain
Bepergian ke daerah yang jauh dari khatulistiwa (ekuator)
Usia. Meskipun diabetes tipe 1 bisa muncul pada usia berapapun, tapi penyakit ini banyak dialami oleh anak-anak berumur 4–7 tahun dan 10–14 tahun.
Sedangkan faktor risiko diabetes mellitus tipe 2 adalah sebagai berikut:
Mengalami obesitas atau kelebihan berat badan.
Memiliki riwayat keluarga dengan diabetes tipe 2.
Kurang aktif bergerak. Aktivitas fisik bisa membantu seseorang untuk mengontrol berat badan, membakar glukosa sebagai energi, dan membuat sel tubuh lebih sensitif terhadap insulin. Itulah mengapa, orang yang kurang beraktivitas fisik akan lebih mudah terkena diabetes tipe 2.
Usia. Risiko terkena diabetes tipe 2 akan meningkat seiring bertambahnya usia.
5.Mengidap tekanan darah tinggi atau hipertensi.
Memiliki kadar kolesterol dan trigliserida yang tidak normal. Orang yang memiliki kadar kolesterol baik atau HDL (high-density lipoprotein) yang rendah, tapi kadar trigliseridanya tinggi lebih berisiko mengalami diabetes tipe 2.
Mengidap polycystic ovarian syndrome (PCOS). Khusus pada wanita, memiliki riwayat penyakit PCOS membuat seorang wanita berisiko tinggi mengalami diabetes tipe 2.
Sedangkan pada ibu hamil, risiko mengalami diabetes gestasional semakin besar bila ibu mengidap diabetes tipe 2.
Setelah mengetahui tentang Diabetes Militus kita akan menggunakan Dataset yang berasal dari National Institute of Diabetes and Digestive and Ginjal Diseases. Tujuan dari Analisis ini adalah membangun model untuk memprediksi secara diagnostik apakah pasien memiliki diabetes atau tidak.
# package yang diperlukan
library(readr)
library(tidyverse)
library(gtools)
library(ggplot2)
library(readr)
library(ggcorrplot)
library(corrplot)
library(PerformanceAnalytics)
library(ROCR)
library(tidyverse)
library(psych)
library(GGally)
library(caret)#Load dataset
db = read.csv('diabetes.csv', header=TRUE)
head(db,3)Datase ini terdiri dari beberapa variabel :
Pregnancies = Jumlah kehamilan
Glucose = konsentrasi glukosa 2 jam dalam tes toleransi glukosa oral
BloodPressure = Tekanan darah diastolik (mm Hg)
SkinThickness = Ketebalan lipatan kulit (mm)
Insulin = 2-Jam serum insulin (mu U / ml)
BMI = Indeks massa tubuh (berat dalam kg / (tinggi dalam m) ^ 2)
DiabetesPedigreeFunction = Riwayat keturunan diabetes
Age = Umur (tahun)
Variabel Outcome = Class (0 atau 1) 268 dari 768 adalah 1, yang lain adalah 0
#cek type Data
str(db)> 'data.frame': 768 obs. of 9 variables:
> $ Pregnancies : int 6 1 8 1 0 5 3 10 2 8 ...
> $ Glucose : int 148 85 183 89 137 116 78 115 197 125 ...
> $ BloodPressure : int 72 66 64 66 40 74 50 0 70 96 ...
> $ SkinThickness : int 35 29 0 23 35 0 32 0 45 0 ...
> $ Insulin : int 0 0 0 94 168 0 88 0 543 0 ...
> $ BMI : num 33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
> $ DiabetesPedigreeFunction: num 0.627 0.351 0.672 0.167 2.288 ...
> $ Age : int 50 31 32 21 33 30 26 29 53 54 ...
> $ Outcome : int 1 0 1 0 1 0 1 0 1 1 ...
summary(db)> 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.: 62.00 1st Qu.: 0.00
> Median : 3.000 Median :117.0 Median : 72.00 Median :23.00
> Mean : 3.845 Mean :120.9 Mean : 69.11 Mean :20.54
> 3rd Qu.: 6.000 3rd Qu.:140.2 3rd Qu.: 80.00 3rd Qu.:32.00
> Max. :17.000 Max. :199.0 Max. :122.00 Max. :99.00
> Insulin BMI DiabetesPedigreeFunction Age
> Min. : 0.0 Min. : 0.00 Min. :0.0780 Min. :21.00
> 1st Qu.: 0.0 1st Qu.:27.30 1st Qu.:0.2437 1st Qu.:24.00
> Median : 30.5 Median :32.00 Median :0.3725 Median :29.00
> Mean : 79.8 Mean :31.99 Mean :0.4719 Mean :33.24
> 3rd Qu.:127.2 3rd Qu.:36.60 3rd Qu.:0.6262 3rd Qu.:41.00
> Max. :846.0 Max. :67.10 Max. :2.4200 Max. :81.00
> Outcome
> Min. :0.000
> 1st Qu.:0.000
> Median :0.000
> Mean :0.349
> 3rd Qu.:1.000
> Max. :1.000
#cek dimensi
dim(db)> [1] 768 9
#cek missing value
db %>%
is.na() %>%
colSums()> Pregnancies Glucose BloodPressure
> 0 0 0
> SkinThickness Insulin BMI
> 0 0 0
> DiabetesPedigreeFunction Age Outcome
> 0 0 0
#Konversikan Outcome pada db : 0 = No & 1 = Yes
db$Outcome <- as.factor(db$Outcome)
levels(db$Outcome) <- c("No","Yes")ggplot(aes(x = Age), data=db) +
geom_histogram(binwidth=1, color='white', fill = "#FF00FF") +
scale_x_continuous(limits=c(20,90), breaks=seq(20,90,5)) +
xlab("Usia") +
ylab("Jumlah Orang Berdasarkan Usia")# Membuat kolom kategori usia
db$Age_Cat <- ifelse(db$Age < 21, "<21",
ifelse((db$Age>=21) & (db$Age<=25), "21-25",
ifelse((db$Age>25) & (db$Age<=30), "25-30",
ifelse((db$Age>30) & (db$Age<=35), "30-35",
ifelse((db$Age>35) & (db$Age<=40), "35-40",
ifelse((db$Age>40) & (db$Age<=50), "40-50",
ifelse((db$Age>50) & (db$Age<=60), "50-60",">60")))))))
db$Age_Cat <- factor(db$Age_Cat, levels = c('<21','21-25','25-30','30-35','35-40','40-50','50-60','>60'))# Barplot by Age_Cat
ggplot(aes(x = Age_Cat), data = db) +
geom_bar(fill='#FF00FF')Sebagian besar subjek berada diantara umur 21 - 30
db_cor <- round(cor(db[1:8]),1)
ggcorrplot(db_cor)corrplot.mixed(corr = cor(db[1:8]))ggcorr(db[,-9], name = "corr", label = TRUE) + theme(legend.position="none")+
labs(title="Korelasi Variansi ") + theme(plot.title=element_text(face='bold',color='black',hjust=0.5,size=12))Tidak ada korelasi kuat antar variabel, jadi tidak ada yang perlu dihilangkan dari variabel- variabel tersebut
RNGkind(sample.kind = "Rounding")
set.seed(417)
index_db <- sample(x = nrow(db) , size = nrow(db)*0.75)
train <- db[index_db , ]
test <- db[-index_db, ] # tanda - berarti negasi# cek spliting data train dan test
nrow(train)> [1] 576
nrow(test)> [1] 192
# re-check class imbalance
train$Outcome %>%
table() %>%
prop.table()> .
> No Yes
> 0.6579861 0.3420139
proporsi kelas yang balance penting untuk data train karena kita akan melatih model menggunakan data train.
#fitting model dengan semua variabel independen
model <- glm(Outcome ~ ., data = train, family = binomial)
summary(model)>
> Call:
> glm(formula = Outcome ~ ., family = binomial, data = train)
>
> Deviance Residuals:
> Min 1Q Median 3Q Max
> -2.9840 -0.6773 -0.3777 0.6768 3.0355
>
> Coefficients:
> Estimate Std. Error z value Pr(>|z|)
> (Intercept) -7.5033789 1.5481132 -4.847 1.25e-06 ***
> Pregnancies 0.0483106 0.0396768 1.218 0.22337
> Glucose 0.0380749 0.0044887 8.482 < 2e-16 ***
> BloodPressure -0.0089633 0.0060536 -1.481 0.13870
> SkinThickness -0.0043738 0.0080374 -0.544 0.58631
> Insulin -0.0009301 0.0010123 -0.919 0.35820
> BMI 0.0885507 0.0183439 4.827 1.38e-06 ***
> DiabetesPedigreeFunction 1.0955133 0.3639698 3.010 0.00261 **
> Age -0.0577335 0.0565531 -1.021 0.30731
> Age_Cat25-30 0.4993353 0.4417268 1.130 0.25830
> Age_Cat30-35 1.7282904 0.6819322 2.534 0.01126 *
> Age_Cat35-40 1.6482267 0.9433394 1.747 0.08060 .
> Age_Cat40-50 2.3472893 1.2709452 1.847 0.06476 .
> Age_Cat50-60 2.4660464 1.8691410 1.319 0.18705
> Age_Cat>60 1.9010668 2.4512114 0.776 0.43801
> ---
> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
>
> (Dispersion parameter for binomial family taken to be 1)
>
> Null deviance: 740.00 on 575 degrees of freedom
> Residual deviance: 517.29 on 561 degrees of freedom
> AIC: 547.29
>
> Number of Fisher Scoring iterations: 5
Lakukan feature selection menggunakan stepwise yang berfungsi untuk menghilangkan predictor satu persatu sampai mendapatkan nilai AIC Terendah
model2 <- step(object = model, direction="backward", trace = 0)
summary(model2)>
> Call:
> glm(formula = Outcome ~ Glucose + BloodPressure + BMI + DiabetesPedigreeFunction +
> Age_Cat, family = binomial, data = train)
>
> Deviance Residuals:
> Min 1Q Median 3Q Max
> -3.0603 -0.6912 -0.3712 0.6827 2.9678
>
> Coefficients:
> Estimate Std. Error z value Pr(>|z|)
> (Intercept) -8.423954 0.825604 -10.203 < 2e-16 ***
> Glucose 0.036091 0.004156 8.685 < 2e-16 ***
> BloodPressure -0.009652 0.005929 -1.628 0.103571
> BMI 0.082832 0.017043 4.860 1.17e-06 ***
> DiabetesPedigreeFunction 0.975840 0.352484 2.768 0.005632 **
> Age_Cat25-30 0.300968 0.334728 0.899 0.368577
> Age_Cat30-35 1.350286 0.369192 3.657 0.000255 ***
> Age_Cat35-40 1.070794 0.381820 2.804 0.005040 **
> Age_Cat40-50 1.450773 0.341591 4.247 2.17e-05 ***
> Age_Cat50-60 0.953620 0.457424 2.085 0.037091 *
> Age_Cat>60 -0.190051 0.636899 -0.298 0.765397
> ---
> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
>
> (Dispersion parameter for binomial family taken to be 1)
>
> Null deviance: 740.00 on 575 degrees of freedom
> Residual deviance: 521.91 on 565 degrees of freedom
> AIC: 543.91
>
> Number of Fisher Scoring iterations: 5
exp(coef(model2))> (Intercept) Glucose BloodPressure
> 0.0002195447 1.0367505821 0.9903948793
> BMI DiabetesPedigreeFunction Age_Cat25-30
> 1.0863595163 2.6533954738 1.3511666735
> Age_Cat30-35 Age_Cat35-40 Age_Cat40-50
> 3.8585299013 2.9176965649 4.2664127801
> Age_Cat50-60 Age_Cat>60
> 2.5950879825 0.8269166880
Interpretasi untuk parameter:
Glucose: Kemungkinan seseorang dengan glukosa yang tinggi 1.03 KALI lebih mungkin untuk terindikasi diabetes dengan catatan variabel lainnya memiliki nilai yang sama.
# prediksikan outcome pada data train
pred_train <- predict(model2, type = "response")
tapply(pred_train, train$Outcome, mean)> No Yes
> 0.2218039 0.5732809
TP (True Positive) = Ketika kita memprediksi kelas positive, dan itu benar
TN (True Negative) = Ketika kita memprediksi kelas negative, dan itu benar
FP (False Positive) = Ketika kita memprediksi kelas positive, dan itu salah
FN (False Negative) = Ketika kita memprediksi kelas negative, dan itu salah
Accuracy: seberapa tepat model kita memprediksi kelas target (secara global)
Sensitivity/ Recall: ukuran kebaikan model terhadap kelas positif (rujukannya adalah data actual)
Specificity: ukuran kebaikan model terhadap kelas negatif
Treshold:
Hasil dari model regresi logistik adalah probabilitas. Kita dapat melakukan ini dengan menggunakan nilai ambang t
Jika P(y=1) >= t, prediksi 1 Jika P(y=1) < t, prediksi 0
TH_0.3 <- table(train$Outcome, pred_train > 0.3)
TH_0.3>
> FALSE TRUE
> No 279 100
> Yes 33 164
acc_0.3 <- round(sum(diag(TH_0.3))/sum(TH_0.3),2)
sensitivity0.3 <- round(161/(40+161),2)
specificity0.3 <- round(270/(270+105),2)
sprintf("Nilai Akurasi sebesar %s", acc_0.3)> [1] "Nilai Akurasi sebesar 0.77"
sprintf("Nilai Sensitivitas sebesar %s", sensitivity0.3)> [1] "Nilai Sensitivitas sebesar 0.8"
sprintf("Nilai Spesifikasi sebesar %s", specificity0.3)> [1] "Nilai Spesifikasi sebesar 0.72"
TH_0.5 <- table(train$Outcome, pred_train > 0.5)
TH_0.5>
> FALSE TRUE
> No 338 41
> Yes 81 116
acc_0.5 <- round(sum(diag(TH_0.5))/sum(TH_0.5),2)
sensitivity0.5 <- round(180/(21+180),2)
specificity0.5 <- round(215/(215+160),2)
sprintf("Nilai Akurasi sebesar %s", acc_0.5)> [1] "Nilai Akurasi sebesar 0.79"
sprintf("Nilai Sensitivitas sebesar %s", sensitivity0.5)> [1] "Nilai Sensitivitas sebesar 0.9"
sprintf("Nilai Spesifikasi sebesar %s", specificity0.5)> [1] "Nilai Spesifikasi sebesar 0.57"
Untuk melihat kebaikan model dalam mendiagnosis penyakit Diabetes dapat dilihat dari Sensitivity/Recall yang menggunakan treshold 0.5 karena menghasilkan nilai sensitivitas sebesar 0.9 dibandingkan dengan menggunakan treshold 0.3 yang hanya menghasilkan sensitivitas sebesar 0.8. Nilai Sensitivity/Recall sendiri artinya, nilai proporsi kasus positif (Diabetes) yang sebenarnya yang diprediksi positif secara benar.
ROCRprediction = prediction(pred_train, train$Outcome)
ROCRperfomance = performance(ROCRprediction, "tpr", "fpr")
# Adding threshold labels
plot(ROCRperfomance, colorize=TRUE, print.cutoffs.at = seq(0,1,0.1), text.adj = c(-0.2, 1.7))
abline(a=0, b=1)
auc_train <- round(as.numeric(performance(ROCRprediction, "auc")@y.values),2)
legend(.8, .2, auc_train, title = "AUC", cex=1)Pada area di bawah kurva ROC atau nilai AUC sebesar 86% artinya, menunjukkan model cukup memuaskan.
pred_test <- predict(model2, type = "response", newdata = test)
# Berdasarkan kurva ROC di atas, dipilih ambang batas 0,5
test_tab <- table(test$Outcome, pred_test > 0.5)
test_tab>
> FALSE TRUE
> No 113 8
> Yes 34 37
acc_test <- round(sum(diag(test_tab))/sum(test_tab),2)
sprintf("Nilai Akurasi pada Data Test sebesar %s", acc_test)> [1] "Nilai Akurasi pada Data Test sebesar 0.78"
# ROC pada Data Test
ROCRPredTest = prediction(pred_test, test$Outcome)
auc = round(as.numeric(performance(ROCRPredTest, "auc")@y.values),2)
sprintf("Nilai AUC pada Data Test sebesar %s", auc)> [1] "Nilai AUC pada Data Test sebesar 0.84"
AUC pada data test menunjukkan bahwa kemampuan prediksi model baik
Semua variabel yang dipilih setelah proses eliminasi menggunakan stepwise menunjukkan P-values lebih rendah dari 0.05 artinya, model signifikan dalam memprediksi penyakit Diabetes.
Model dengan ambang batas yang lebih tinggi memiliki Sensitivitas yang lebih rendah tetapi spesifisitas yang lebih tinggi.
Model dengan ambang batas yang lebih rendah memiliki Sensitivitas yang lebih tinggi tetapi spesifisitas yang lebih rendah.
BMI yang tinggi memiliki resiko 1.07 kali terkena penyakit Diabetes.
Kehamilan, glukosa, tekanan darah, dan Riwayat Keturunan juga berpengaruh dengan terjadinya penyakit Diabetes.
Model diprediksi dengan akurasi 79%. Model ini lebih spesifik daripada sensitif.
Area di bawah kurva ROC adalah 86% yang menunjukkan model cukup memuaskan.
Model yang lebih baik dapat ditingkatkan dengan lebih banyak data.