PENDAHULUAN

Penyakit jantung merupakan salah satu penyebab utama kematian di dunia. Menurut World Health Organization, penyakit kardiovaskular menyumbang jutaan kematian setiap tahun. Oleh karena itu, diperlukan metode analisis yang dapat membantu memprediksi kemungkinan seseorang mengalami penyakit jantung berdasarkan data klinis. Salah satu metode yang umum digunakan untuk klasifikasi biner adalah Logistic Regression.

TUJUAN

Analisis ini bertujuan untuk:

  1. Membangun model prediksi penyakit jantung menggunakan Logistic Regression.

  2. Mengevaluasi performa model menggunakan ROC Curve dan nilai AUC.

  3. Mengidentifikasi variabel yang paling berpengaruh terhadap risiko penyakit jantung.

DESKRIPSI DATA

Dataset yang digunakan adalah Heart Failure Prediction Dataset dari Kaggle yang dipublikasikan oleh Federico Soriano. Dataset ini berisi sekitar 918 observasi dengan 11 variabel prediktor dan 1 variabel target (HeartDisease). Variabel dalam dataset mencakup sebagai berikut :

Variabel Deskripsi
Age Usia pasien (tahun)
Sex Jenis kelamin pasien (M = Male, F = Female)
ChestPainType Jenis nyeri dada (TA, ATA, NAP, ASY)
RestingBP Tekanan darah saat istirahat (mm Hg)
Cholesterol Kadar kolesterol serum (mg/dl)
FastingBS Gula darah puasa (>120 mg/dl = 1, lainnya = 0)
RestingECG Hasil elektrokardiogram saat istirahat
MaxHR Detak jantung maksimum yang dicapai
ExerciseAngina Angina akibat olahraga (Y/N)
Oldpeak Depresi ST yang diinduksi oleh olahraga
ST_Slope Kemiringan segmen ST pada puncak latihan
HeartDisease Variabel target (0 = tidak ada penyakit jantung, 1 = ada penyakit jantung)

HASIL ANALISIS DAN PEMBAHASAN

1.Load Library

# Logistic regression menggunakan fungsi bawaan R
# sehingga tidak memerlukan library tambahan

Logistic Regression merupakan metode klasifikasi yang digunakan untuk memprediksi probabilitas suatu kejadian biner. Pada analisis ini, metode logistic regression digunakan untuk memprediksi apakah seorang pasien memiliki penyakit jantung atau tidak.

2.Import Data & Preprocessing

data <- read.csv("heart.csv")

head(data)
##   Age Sex ChestPainType RestingBP Cholesterol FastingBS RestingECG MaxHR
## 1  40   M           ATA       140         289         0     Normal   172
## 2  49   F           NAP       160         180         0     Normal   156
## 3  37   M           ATA       130         283         0         ST    98
## 4  48   F           ASY       138         214         0     Normal   108
## 5  54   M           NAP       150         195         0     Normal   122
## 6  39   M           NAP       120         339         0     Normal   170
##   ExerciseAngina Oldpeak ST_Slope HeartDisease
## 1              N     0.0       Up            0
## 2              N     1.0     Flat            1
## 3              N     0.0       Up            0
## 4              Y     1.5     Flat            1
## 5              N     0.0       Up            0
## 6              N     0.0       Up            0
str(data)
## 'data.frame':    918 obs. of  12 variables:
##  $ Age           : int  40 49 37 48 54 39 45 54 37 48 ...
##  $ Sex           : chr  "M" "F" "M" "F" ...
##  $ ChestPainType : chr  "ATA" "NAP" "ATA" "ASY" ...
##  $ RestingBP     : int  140 160 130 138 150 120 130 110 140 120 ...
##  $ Cholesterol   : int  289 180 283 214 195 339 237 208 207 284 ...
##  $ FastingBS     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ RestingECG    : chr  "Normal" "Normal" "ST" "Normal" ...
##  $ MaxHR         : int  172 156 98 108 122 170 170 142 130 120 ...
##  $ ExerciseAngina: chr  "N" "N" "N" "Y" ...
##  $ Oldpeak       : num  0 1 0 1.5 0 0 0 0 1.5 0 ...
##  $ ST_Slope      : chr  "Up" "Flat" "Up" "Flat" ...
##  $ HeartDisease  : int  0 1 0 1 0 0 0 0 1 0 ...
summary(data)
##       Age            Sex            ChestPainType        RestingBP    
##  Min.   :28.00   Length:918         Length:918         Min.   :  0.0  
##  1st Qu.:47.00   Class :character   Class :character   1st Qu.:120.0  
##  Median :54.00   Mode  :character   Mode  :character   Median :130.0  
##  Mean   :53.51                                         Mean   :132.4  
##  3rd Qu.:60.00                                         3rd Qu.:140.0  
##  Max.   :77.00                                         Max.   :200.0  
##   Cholesterol      FastingBS       RestingECG            MaxHR      
##  Min.   :  0.0   Min.   :0.0000   Length:918         Min.   : 60.0  
##  1st Qu.:173.2   1st Qu.:0.0000   Class :character   1st Qu.:120.0  
##  Median :223.0   Median :0.0000   Mode  :character   Median :138.0  
##  Mean   :198.8   Mean   :0.2331                      Mean   :136.8  
##  3rd Qu.:267.0   3rd Qu.:0.0000                      3rd Qu.:156.0  
##  Max.   :603.0   Max.   :1.0000                      Max.   :202.0  
##  ExerciseAngina        Oldpeak          ST_Slope          HeartDisease   
##  Length:918         Min.   :-2.6000   Length:918         Min.   :0.0000  
##  Class :character   1st Qu.: 0.0000   Class :character   1st Qu.:0.0000  
##  Mode  :character   Median : 0.6000   Mode  :character   Median :1.0000  
##                     Mean   : 0.8874                      Mean   :0.5534  
##                     3rd Qu.: 1.5000                      3rd Qu.:1.0000  
##                     Max.   : 6.2000                      Max.   :1.0000

Dataset yang digunakan adalah Heart Disease Dataset yang berisi informasi karakteristik pasien dan status penyakit jantung.

Variabel target dalam dataset ini adalah:

HeartDisease

Dimana:

  • 0 = Tidak memiliki penyakit jantung
  • 1 = Memiliki penyakit jantung

3.Data Preparation

data$Sex <- as.factor(data$Sex)
data$ChestPainType <- as.factor(data$ChestPainType)
data$RestingECG <- as.factor(data$RestingECG)
data$ExerciseAngina <- as.factor(data$ExerciseAngina)
data$ST_Slope <- as.factor(data$ST_Slope)
data$HeartDisease <- as.factor(data$HeartDisease)

str(data)
## 'data.frame':    918 obs. of  12 variables:
##  $ Age           : int  40 49 37 48 54 39 45 54 37 48 ...
##  $ Sex           : Factor w/ 2 levels "F","M": 2 1 2 1 2 2 1 2 2 1 ...
##  $ ChestPainType : Factor w/ 4 levels "ASY","ATA","NAP",..: 2 3 2 1 3 3 2 2 1 2 ...
##  $ RestingBP     : int  140 160 130 138 150 120 130 110 140 120 ...
##  $ Cholesterol   : int  289 180 283 214 195 339 237 208 207 284 ...
##  $ FastingBS     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ RestingECG    : Factor w/ 3 levels "LVH","Normal",..: 2 2 3 2 2 2 2 2 2 2 ...
##  $ MaxHR         : int  172 156 98 108 122 170 170 142 130 120 ...
##  $ ExerciseAngina: Factor w/ 2 levels "N","Y": 1 1 1 2 1 1 1 1 2 1 ...
##  $ Oldpeak       : num  0 1 0 1.5 0 0 0 0 1.5 0 ...
##  $ ST_Slope      : Factor w/ 3 levels "Down","Flat",..: 3 2 3 2 3 3 3 3 2 3 ...
##  $ HeartDisease  : Factor w/ 2 levels "0","1": 1 2 1 2 1 1 1 1 2 1 ...

Pada tahap ini beberapa variabel diubah menjadi factor karena merupakan variabel kategorikal.

Variabel yang dikonversi antara lain:

  • Sex
  • ChestPainType
  • RestingECG
  • ExerciseAngina
  • ST_Slope
  • HeartDisease

Konversi ini penting agar model dapat mengenali variabel sebagai kategori, bukan sebagai nilai numerik.

4.Data Description

Dataset ini berisi informasi kesehatan pasien yang digunakan untuk memprediksi kemungkinan penyakit jantung.

Variabel yang digunakan dalam pemodelan antara lain:

  • Age
  • Sex
  • ChestPainType
  • RestingBP
  • Cholesterol
  • FastingBS
  • RestingECG
  • MaxHR
  • ExerciseAngina
  • Oldpeak
  • ST_Slope

Variabel HeartDisease menjadi variabel target yang akan diprediksi oleh model.

5.Data Splitting

set.seed(123)

trainIndex <- sample(seq_len(nrow(data)), size = 0.8*nrow(data))

train <- data[trainIndex, ]
test <- data[-trainIndex, ]

Dataset dibagi menjadi dua bagian yaitu:

  • 80% data training digunakan untuk membangun model
  • 20% data testing digunakan untuk mengevaluasi performa model

Pembagian data ini bertujuan agar model dapat diuji menggunakan data yang belum pernah digunakan saat proses pelatihan.

6.Build Logistic Regression Model

model_logistic <- glm(
  HeartDisease ~ Age + Sex + ChestPainType + RestingBP +
  Cholesterol + FastingBS + RestingECG + MaxHR +
  ExerciseAngina + Oldpeak + ST_Slope,
  data = train,
  family = binomial
)

summary(model_logistic)
## 
## Call:
## glm(formula = HeartDisease ~ Age + Sex + ChestPainType + RestingBP + 
##     Cholesterol + FastingBS + RestingECG + MaxHR + ExerciseAngina + 
##     Oldpeak + ST_Slope, family = binomial, data = train)
## 
## Coefficients:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.557926   1.601580  -0.973 0.330681    
## Age               0.020877   0.014825   1.408 0.159064    
## SexM              1.520755   0.299142   5.084 3.70e-07 ***
## ChestPainTypeATA -1.863610   0.365098  -5.104 3.32e-07 ***
## ChestPainTypeNAP -1.852727   0.290314  -6.382 1.75e-10 ***
## ChestPainTypeTA  -1.238357   0.472661  -2.620 0.008794 ** 
## RestingBP         0.002802   0.006461   0.434 0.664576    
## Cholesterol      -0.003754   0.001177  -3.189 0.001430 ** 
## FastingBS         0.960752   0.297533   3.229 0.001242 ** 
## RestingECGNormal -0.199598   0.298963  -0.668 0.504366    
## RestingECGST     -0.158395   0.397002  -0.399 0.689909    
## MaxHR            -0.003407   0.005569  -0.612 0.540755    
## ExerciseAnginaY   0.757258   0.270937   2.795 0.005191 ** 
## Oldpeak           0.402619   0.130097   3.095 0.001970 ** 
## ST_SlopeFlat      1.701060   0.471528   3.608 0.000309 ***
## ST_SlopeUp       -0.669212   0.486933  -1.374 0.169336    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 1007.44  on 733  degrees of freedom
## Residual deviance:  486.08  on 718  degrees of freedom
## AIC: 518.08
## 
## Number of Fisher Scoring iterations: 5

Model dibangun menggunakan fungsi glm() dengan parameter family = binomial, yang menunjukkan bahwa model yang digunakan adalah logistic regression.

Model ini memprediksi kemungkinan seseorang mengalami penyakit jantung berdasarkan berbagai faktor kesehatan seperti usia, tekanan darah, kadar kolesterol, dan kondisi klinis lainnya.

Output dari summary() menampilkan:

  • nilai koefisien regresi
  • tingkat signifikansi variabel
  • p-value dari setiap variabel

Variabel dengan p-value < 0.05 dianggap memiliki pengaruh signifikan terhadap kemungkinan penyakit jantung.

7.Odds Ratio

exp(coef(model_logistic))
##      (Intercept)              Age             SexM ChestPainTypeATA 
##        0.2105723        1.0210967        4.5756806        0.1551117 
## ChestPainTypeNAP  ChestPainTypeTA        RestingBP      Cholesterol 
##        0.1568089        0.2898601        1.0028056        0.9962528 
##        FastingBS RestingECGNormal     RestingECGST            MaxHR 
##        2.6136607        0.8190596        0.8535125        0.9965991 
##  ExerciseAnginaY          Oldpeak     ST_SlopeFlat       ST_SlopeUp 
##        2.1324207        1.4957364        5.4797552        0.5121122

Koefisien logistic regression dapat dikonversi menjadi Odds Ratio untuk mempermudah interpretasi.

Interpretasi Odds Ratio:

  • Odds Ratio > 1 menunjukkan peningkatan risiko penyakit jantung
  • Odds Ratio < 1 menunjukkan penurunan risiko penyakit jantung

Sebagai contoh, jika suatu variabel memiliki odds ratio sebesar 1.5, maka variabel tersebut meningkatkan kemungkinan terjadinya penyakit jantung sebesar 50% dibandingkan kategori referensi.

8. Prediction

prob_pred <- predict(model_logistic, test, type = "response")

class_pred <- ifelse(prob_pred > 0.5, 1, 0)
class_pred <- as.factor(class_pred)

Model logistic regression menghasilkan nilai probabilitas antara 0 hingga 1.

Probabilitas tersebut kemudian dikonversi menjadi kelas menggunakan threshold 0.5:

  • Probabilitas > 0.5 → diprediksi memiliki penyakit jantung
  • Probabilitas ≤ 0.5 → diprediksi tidak memiliki penyakit jantung

9.Evaluation

conf_matrix <- table(Predicted = class_pred,
                     Actual = test$HeartDisease)

conf_matrix
##          Actual
## Predicted  0  1
##         0 73  6
##         1 13 92

Confusion matrix digunakan untuk mengevaluasi performa model klasifikasi.

Komponen dalam confusion matrix meliputi:

  • True Positive (TP) : prediksi benar untuk pasien dengan penyakit jantung. Sebangan 92 pasien diprediksi memiliki penyakit jantung.
  • True Negative (TN) : 73 pasien diprediksi tidak memiliki penyakit jantung dan hasil aktual juga tidak memiliki penyakit jantung.
  • False Positive (FP) : 13 pasien diprediksi memiliki penyakit jantung, tetapi sebenarnya tidak memiliki penyakit jantung.
  • False Negative (FN) : 6 pasien diprediksi tidak memiliki penyakit jantung, tetapi sebenarnya memiliki penyakit jantung.

10.Accuracy

accuracy <- mean(class_pred == test$HeartDisease)
accuracy
## [1] 0.8967391

Accuracy menunjukkan tingkat ketepatan model dalam melakukan klasifikasi. Nilai accuracy yang diperoleh sekitar 0.89, maka dapat diinterpretasikan bahwa:

Model Logistic Regression mampu memprediksi status penyakit jantung dengan tingkat ketepatan sekitar 89%. Nilai ini menunjukkan bahwa model memiliki performa yang cukup baik dalam membedakan pasien yang memiliki penyakit jantung dan yang tidak.

11. ROC Curve dan AUC

ROC Curve (Receiver Operating Characteristic Curve) digunakan untuk mengevaluasi performa model klasifikasi dengan melihat kemampuan model dalam membedakan antara dua kelas.

library(pROC)
## Warning: package 'pROC' was built under R version 4.3.3
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
roc_curve <- roc(test$HeartDisease, prob_pred)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
plot(roc_curve, col="blue", main="ROC Curve - Logistic Regression")

auc_value <- auc(roc_curve)
auc_value
## Area under the curve: 0.9394

Nilai AUC (Area Under Curve) menunjukkan kemampuan model dalam membedakan antara kelas positif dan negatif.

Pada grafik ROC:

Sumbu Y (Sensitivity) menunjukkan kemampuan model dalam mendeteksi pasien yang benar-benar memiliki penyakit jantung.

Sumbu X (Specificity) menunjukkan kemampuan model dalam mengenali pasien yang tidak memiliki penyakit jantung.

Garis diagonal abu-abu pada grafik menunjukkan model klasifikasi acak. Jika kurva ROC berada dekat dengan garis diagonal tersebut, maka model tidak memiliki kemampuan prediksi yang baik.

Pada hasil yang diperoleh, kurva ROC terlihat melengkung jauh di atas garis diagonal dan mendekati sudut kiri atas grafik. Hal ini menunjukkan bahwa model Logistic Regression memiliki kemampuan yang baik dalam membedakan antara pasien yang memiliki penyakit jantung dan yang tidak.

Selain itu, nilai AUC (Area Under Curve) yang dihasilkan berada pada kategori tinggi. Nilai AUC yang mendekati 1 menunjukkan bahwa model memiliki performa klasifikasi yang sangat baik.

12. Visualisasi Distribusi Probabilitas

hist(prob_pred,
     main = "Distribution of Predicted Probabilities",
     xlab = "Predicted Probability",
     col = "lightblue")

Histogram ini menunjukkan distribusi probabilitas yang dihasilkan oleh model logistic regression.

Distribusi probabilitas ini menggambarkan seberapa yakin model dalam memprediksi kemungkinan pasien memiliki penyakit jantung.

Jika sebagian besar probabilitas berada di dekat 0 atau 1, maka model memiliki kemampuan klasifikasi yang baik dalam membedakan kedua kelas.

Dari histogram yang dihasilkan terlihat bahwa sebagian besar probabilitas terkonsentrasi pada dua area utama:

Area dekat 0, yang menunjukkan pasien dengan kemungkinan rendah mengalami penyakit jantung.

Area dekat 1, yang menunjukkan pasien dengan kemungkinan tinggi mengalami penyakit jantung.

Distribusi yang cukup terpisah antara kedua kelompok ini menunjukkan bahwa model mampu membedakan kelas dengan cukup jelas, sehingga menghasilkan performa klasifikasi yang baik.

13. Variabel Paling Signifikan dalam Model

Berdasarkan output summary(model_logistic), variabel yang dianggap signifikan secara statistik adalah variabel yang memiliki p-value < 0.05.

summary(model_logistic)
## 
## Call:
## glm(formula = HeartDisease ~ Age + Sex + ChestPainType + RestingBP + 
##     Cholesterol + FastingBS + RestingECG + MaxHR + ExerciseAngina + 
##     Oldpeak + ST_Slope, family = binomial, data = train)
## 
## Coefficients:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.557926   1.601580  -0.973 0.330681    
## Age               0.020877   0.014825   1.408 0.159064    
## SexM              1.520755   0.299142   5.084 3.70e-07 ***
## ChestPainTypeATA -1.863610   0.365098  -5.104 3.32e-07 ***
## ChestPainTypeNAP -1.852727   0.290314  -6.382 1.75e-10 ***
## ChestPainTypeTA  -1.238357   0.472661  -2.620 0.008794 ** 
## RestingBP         0.002802   0.006461   0.434 0.664576    
## Cholesterol      -0.003754   0.001177  -3.189 0.001430 ** 
## FastingBS         0.960752   0.297533   3.229 0.001242 ** 
## RestingECGNormal -0.199598   0.298963  -0.668 0.504366    
## RestingECGST     -0.158395   0.397002  -0.399 0.689909    
## MaxHR            -0.003407   0.005569  -0.612 0.540755    
## ExerciseAnginaY   0.757258   0.270937   2.795 0.005191 ** 
## Oldpeak           0.402619   0.130097   3.095 0.001970 ** 
## ST_SlopeFlat      1.701060   0.471528   3.608 0.000309 ***
## ST_SlopeUp       -0.669212   0.486933  -1.374 0.169336    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 1007.44  on 733  degrees of freedom
## Residual deviance:  486.08  on 718  degrees of freedom
## AIC: 518.08
## 
## Number of Fisher Scoring iterations: 5

KESIMPULAN

Berdasarkan hasil evaluasi model Regresi Logistik:

Dengan demikian, model Logistic Regression yang dibangun dapat digunakan sebagai pendekatan analitis untuk membantu mengidentifikasi faktor risiko penyakit jantung berdasarkan karakteristik pasien.

REFERENSI

World Health Organization. (2023). Cardiovascular Diseases (CVDs).

David W. Hosmer, Stanley Lemeshow, & Rodney X. Sturdivant. (2013). Applied Logistic Regression. Wiley.

Tom Fawcett. (2006). An Introduction to ROC Analysis. Pattern Recognition Letters.

Federico Soriano. (2021). Heart Failure Prediction Dataset. Kaggle.