1 Pendahuluan

Kanker payudara (Carcinoma Mammae) merupakan tumor ganas berupa benjolan abnormal yang tumbuh di dalam jaringan payudara. Berdasarkan data World Health Organization (WHO) tahun 2022, diperkirakan terdapat 2,3 juta kasus baru kanker payudara di seluruh dunia.

Sekitar 80% kasus kanker payudara berkembang pada wanita tanpa faktor risiko spesifik yang dapat dimodifikasi — hanya berkaitan dengan faktor penuaan dan jenis kelamin. Hal ini menunjukkan bahwa penentuan status tumor tidak dapat diidentifikasi secara akurat hanya melalui hasil riwayat penyakit pasien.

Oleh karena itu, digunakan Model Regresi Logistik Biner berbasis karakteristik mammographic mass sebagai instrumen pendukung deteksi dini.

Penelitian ini menganalisis karakteristik mammographic mass yang meliputi bentuk (shape), tepi (margin), dan kepadatan (density) bersama usia pasien (age) untuk memprediksi probabilitas keganasan lesi payudara.

1.1 Tujuan Penelitian

Penelitian ini bertujuan untuk:

  1. Membangun model regresi logistik biner yang mampu memprediksi probabilitas keganasan (malignancy) tumor payudara berdasarkan karakteristik mammografi.
  2. Membandingkan dua pendekatan pemodelan variabel ordinal Density: sebagai skala numerik kontinu (Model 1) vs. variabel kategorik nominal (Model 2).
  3. Mengidentifikasi faktor risiko dominan dan menginterpretasikan odds ratio setiap prediktor klinis.
  4. Mengevaluasi performa klasifikasi model akhir melalui akurasi, sensitivitas, spesifisitas, dan confusion matrix.

2 Material dan Metode

2.1 Pengumpulan Data dan Variabel

Dataset yang digunakan adalah dataset publik Mammographic Mass dari UCI Machine Learning Repository, dikumpulkan oleh Institute of Radiology.

# Load library yang dibutuhkan
library(tidyverse)
library(knitr)
library(kableExtra)
library(car)        
library(caret)        
library(ResourceSelection)

# ── Muat dataset ──────────────────────────────────────────────────────────────
# Dataset dapat diunduh dari: https://archive.ics.uci.edu/dataset/161/mammographic+mass
# Dataset tanpa missing value: https://drive.google.com/file/d/1KwCCnu0Hj7-qvuxpeV8CE8FSOjj1Wmdv/view?usp=drive_link

mam_raw <- read.csv("mammographic_masses.csv", header = TRUE, sep = ";")
names(mam_raw)
#> [1] "BI.Rads"  "Age"      "Shape"    "Margin"   "Density"  "Severity"
# ── Bersihkan data ────────────────────────────────────────────────────────────
mam <- mam_raw %>%
  select(-BI.Rads) %>%                   
  drop_na() %>%                          
  mutate(
    Severity = factor(Severity, levels = c(0, 1), labels = c("Benign", "Malignant")),
    Shape    = factor(Shape,
                      levels = 1:4,
                      labels = c("Round", "Oval", "Lobular", "Irregular")),
    Margin   = factor(Margin,
                      levels = 1:5,
                      labels = c("Circumscribed", "Microlobulated",
                                 "Obscured", "Ill-defined", "Spiculated")),
    Density_cat = factor(Density,
                         levels = 1:4,
                         labels = c("High", "Iso", "Low", "Fat-containing"))
  )

cat("Jumlah observasi setelah pembersihan:", nrow(mam), "\n")
#> Jumlah observasi setelah pembersihan: 828
cat("Distribusi Severity:\n")
#> Distribusi Severity:
print(table(mam$Severity))
#> 
#>    Benign Malignant 
#>       426       402

Informasi Variabel

Variabel Jenis Keterangan
Severity Biner (Respons) 0 = Benign, 1 = Malignant
Age Numerik kontinu Usia pasien (tahun)
Shape Nominal (4 kategori) Round, Oval, Lobular, Irregular
Margin Nominal (5 kategori) Circumscribed, Microlobulated, Obscured, Ill-defined, Spiculated
Density Ordinal (4 level) High, Iso, Low, Fat-containing

2.2 Analisis Deskriptif

Sebelum melanjutkan analisis ke tahap pemodelan, data dianalisis secara deskriptif untuk merangkum karakteristik dasar dan memahami sifat masing-masing variabel.

Data Kategorik
Variabel Severity, Shape, Margin, dan Density dianalisis menggunakan distribusi frekuensi dan proporsi untuk merangkum sebaran masing-masing kategori.

Data Numerik
Variabel Age dianalisis dengan menghitung rata-rata, median, nilai minimum, dan nilai maksimum untuk memahami distribusi dan variasi data numerik.

2.3 Pemodelan Regresi Logistik Biner

2.3.1 Fungsi Penghubung (Logit)

Variabel respons bersifat biner sehingga digunakan regresi logistik biner. Fungsi penghubung logit mengubah probabilitas non-linear menjadi bentuk linear:

\[ \text{logit}\big(\pi(x)\big) = \log\left(\frac{\pi(\text{Malignant})}{1 - \pi(\text{Malignant})}\right) = \alpha + \beta_1(\text{Age}) + \beta_2(\text{Shape}) + \beta_3(\text{Margin}) + \beta_4(\text{Density}) \]

2.3.2 Penaksiran Parameter — Maximum Likelihood

Penaksiran parameter dilakukan dengan Maximum Likelihood Estimation (MLE) melalui algoritma Fisher’s Scoring secara iteratif. Standard error diperoleh dari diagonal utama invers matriks informasi Fisher.

2.4 Pengujian Hipotesis dan Diagnostik Model

2.4.1 Uji Simultan — Likelihood Ratio Test (LRT)

Uji simultan digunakan untuk mengetahui apakah semua variabel independen (X) yang ada di dalam model secara bersama-sama (serentak) memiliki pengaruh yang signifikan terhadap variabel dependen (Y) \[ G^2 = -2(L_0 - L_1) \sim \chi^2_{(k)} \]

  • \(H_0\): \(\beta_{\text{Age}} = \beta_{\text{Shape}} = \beta_{\text{Margin}} = \beta_{\text{Density}} = 0\)
  • \(H_1\): Minimal satu \(\beta \neq 0\)

2.4.2 Uji Parsial — Uji Wald

Uji parsial digunakan untuk mengetahui pengaruh masing-masing variabel independen (X) secara sendirian (individual) terhadap variabel dependen (Y), dengan asumsi variabel independen lainnya dianggap konstan/tetap.

\[ W = \frac{\hat\beta_i}{SE(\hat\beta_i)} \sim N(0,1) \text{ (jika } H_0 \text{ benar)} \]

2.4.3 Goodness of Fit

2.4.3.1 Uji Hosmer-Lemeshow (Kelayakan Model)

  • Memastikan tidak ada perbedaan signifikan antara peluang keganasan hasil prediksi model dengan data aktual di lapangan (fit).

2.4.3.2 Analisis Deviance (Pengukuran Error Model)

  • Null Deviance: Besaran error saat model belum memasukkan variabel prediktor.
  • Residual Deviance: Besaran error setelah variabel prediktor dimasukkan ke dalam model (mengukur penurunan error).

2.4.3.3 Kriteria AIC (Akaike Information Criterion)

  • Digunakan untuk mengevaluasi kesederhanaan dan efisiensi model secara objektif.
  • Mencegah terjadinya overfitting.
  • Prinsip: Semakin kecil nilai AIC, semakin baik dan efisien model yang dihasilkan.

3 Hasil

3.1 Analisis Deskriptif

# ── Tabel frekuensi variabel kategorik ───────────────────────────────────────
freq_tbl <- function(var, var_name) {
  tbl <- as.data.frame(table(mam[[var]]))
  tbl$Persen <- round(tbl$Freq / nrow(mam) * 100, 2)
  tbl$Variabel <- var_name
  names(tbl)[1] <- "Kategori"
  tbl[, c("Variabel", "Kategori", "Freq", "Persen")]
}

tbl_kat <- rbind(
  freq_tbl("Severity",    "Severity"),
  freq_tbl("Shape",       "Shape"),
  freq_tbl("Margin",      "Margin"),
  freq_tbl("Density_cat", "Density")
)
names(tbl_kat) <- c("Variabel", "Kategori", "Frekuensi", "Persentase (%)")

nice_kable(tbl_kat, caption = "Tabel 1. Karakteristik Data Mammographic Masses")
Tabel 1. Karakteristik Data Mammographic Masses
Variabel Kategori Frekuensi Persentase (%)
Severity Benign 426 51.45
Severity Malignant 402 48.55
Shape Round 190 22.95
Shape Oval 179 21.62
Shape Lobular 81 9.78
Shape Irregular 378 45.65
Margin Circumscribed 319 38.53
Margin Microlobulated 23 2.78
Margin Obscured 106 12.80
Margin Ill-defined 253 30.56
Margin Spiculated 127 15.34
Density High 10 1.21
Density Iso 56 6.76
Density Low 754 91.06
Density Fat-containing 8 0.97
# ── Ringkasan variabel numerik Age ───────────────────────────────────────────
age_summary <- data.frame(
  Minimum   = min(mam$Age),
  `Kuartil 1` = quantile(mam$Age, 0.25),
  Median    = median(mam$Age),
  Mean      = round(mean(mam$Age), 2),
  `Kuartil 3` = quantile(mam$Age, 0.75),
  Maksimum  = max(mam$Age),
  check.names = FALSE
)
knitr::kable(age_summary, caption = "Tabel 2. Ringkasan Variabel Numerik (Age)", align = "c")
Tabel 2. Ringkasan Variabel Numerik (Age)
Minimum Kuartil 1 Median Mean Kuartil 3 Maksimum
25% 18 45.75 57 55.79 66 96

Interpretasi Deskriptif. Distribusi Severity relatif seimbang: Benign 51,45% dan Malignant 48,55%, sehingga data tidak mengalami ketimpangan kelas. Karakteristik massa didominasi oleh bentuk Irregular (45,65%), margin Circumscribed (38,53%), dan densitas Low (91,06%) yang memperlihatkan adanya pola asimetri. Rata-rata usia pasien sebesar 55,79 tahun. Indikator rerata usia di angka kepala lima ini menunjukkan bahwa mayoritas sampel berada pada kelompok paruh baya hingga lansia, yang merupakan fase siklus hidup dengan tingkat kerentanan tinggi terhadap kanker payudara.

3.2 Formulasi Model

Dua spesifikasi model dibandingkan untuk mengkaji sensitivitas penanganan variabel ordinal Density:

Model 1 — Density sebagai Skala Kontinu (Numerik) \[ \begin{aligned} \ln \left( \frac{p}{1-p} \right) &= \beta_0 + \beta_1 (\text{Age}) + \beta_2 (\text{Shape}_{\text{Oval}}) + \beta_3 (\text{Shape}_{\text{Lobular}}) + \beta_4 (\text{Shape}_{\text{Irregular}}) \\ &\quad + \beta_5 (\text{Margin}_{\text{Micro}}) + \beta_6 (\text{Margin}_{\text{Obscured}}) + \beta_7 (\text{Margin}_{\text{Ill-defined}}) + \beta_8 (\text{Margin}_{\text{Spiculated}}) + \beta_9 (\text{Density}) \end{aligned} \]

Model memperlakukan skor 1 hingga 4 sebagai satu kesatuan skala numerik. Model berasumsi bahwa dampak risiko dari skor 1 ke 2, 2 ke 3, dan 3 ke 4 memiliki bobot perubahan yang konstan. Pendekatan ini tidak memerlukan kategori acuan karena yang dihitung adalah gradien kemiringan trennya. Kelebihan model adalah menghasilkan model yang sederhana dan hemat parameter (parsimonious).

Model 2 — Density sebagai Variabel Nominal (Kategorik)

\[ \ln\left(\frac{p}{1-p}\right) = \beta_0 + \beta_1(\text{Age}) + \cdots + \beta_8(\text{Margin}_{\text{Spiculated}}) + \beta_9(\text{Density}_{\text{Iso}}) + \beta_{10}(\text{Density}_{\text{Low}}) + \beta_{11}(\text{Density}_{\text{Fat-containing}}) \] ::: {.interpret-box} Model memperlakukan skor 1 sampai 4 murni sebagai empat kelompok kategori terpisah yang berdiri sendiri. Pendekatan ini mewajibkan adanya satu kelompok acuan (yaitu Skor 1 / High) sebagai pembanding. Keunggulannya adalah model menjadi sangat fleksibel karena membebaskan tiap tingkatan density untuk memiliki lompatan nilai risiko yang berbeda. Namun kelemahannya, model menjadi boros parameter karena harus memecah satu variabel menjadi tiga koefisien dummy baru.

Kategori acuan: High Density (Tingkat 1).

# ── Referensi level ───────────────────────────────────────────────────────────
mam$Shape  <- relevel(mam$Shape,  ref = "Round")
mam$Margin <- relevel(mam$Margin, ref = "Circumscribed")

# ── Model 1: Density kontinu ──────────────────────────────────────────────────
m1 <- glm(Severity ~ Age + Shape + Margin + Density,
          data = mam, family = binomial(link = "logit"))

# ── Model 2: Density nominal ──────────────────────────────────────────────────
mam$Density_cat <- relevel(mam$Density_cat, ref = "High")
m2 <- glm(Severity ~ Age + Shape + Margin + Density_cat,
          data = mam, family = binomial(link = "logit"))

3.3 Perbandingan Goodness of Fit

# ── Hosmer-Lemeshow  ───────────────────────
hl_test <- function(model, g = 10) {
  tryCatch({
    ResourceSelection::hoslem.test(
      as.numeric(model$y), fitted(model), g = g
    )
  }, error = function(e) list(statistic = NA, p.value = NA))
}

hl1 <- hl_test(m1)
hl2 <- hl_test(m2)

# ── Akurasi ────────────────────────────────────────────────────────────────────
acc_fn <- function(model) {
  pred <- ifelse(fitted(model) > 0.5, "Malignant", "Benign")
  mean(pred == as.character(mam$Severity)) * 100
}

# ── Fungsi tambahan untuk evaluasi model ──────────────────────────────
acc_fn <- function(model){
  pred <- ifelse(fitted(model) > 0.5, 1, 0)
  mean(pred == model$y) * 100
}

sens_fn <- function(model){
  pred <- ifelse(fitted(model) > 0.5, 1, 0)
  sum(pred == 1 & model$y == 1) / sum(model$y == 1) * 100
}

spec_fn <- function(model){
  pred <- ifelse(fitted(model) > 0.5, 1, 0)
  sum(pred == 0 & model$y == 0) / sum(model$y == 0) * 100
}

ci_fn <- function(model){
  n <- length(model$y)
  p <- mean(ifelse(fitted(model) > 0.5, 1, 0) == model$y)
  error <- 1.96 * sqrt(p*(1-p)/n) * 100
  c((p*100)-error, (p*100)+error)
}

# ── Hosmer-Lemeshow test ──────────────────────────────
library(ResourceSelection)
hl1 <- hoslem.test(m1$y, fitted(m1), g=10)
hl2 <- hoslem.test(m2$y, fitted(m2), g=10)

# ── Tabel perbandingan GOF ──────────────────────────────
gof <- data.frame(
  `Metrik Evaluasi` = c(
    "Null Deviance (df)",
    "Residual Deviance (df)",
    "Log-Likelihood Maximum (ln L)",
    "Akaike Information Criterion (AIC)",
    "Akurasi Klasifikasi (%)",
    "Rentang 95% Confidence Interval (CI)",
    "Sensitivitas",
    "Spesifisitas",
    "Hosmer-Lemeshow χ² (p-value)"
  ),
  `Model 1 (Density Kontinu)` = c(
    paste0(round(m1$null.deviance, 4), " (df = ", m1$df.null, ")"),
    paste0(round(deviance(m1), 4), " (df = ", m1$df.residual, ")"),
    round(logLik(m1)[1], 4),
    round(AIC(m1), 4),
    paste0(round(acc_fn(m1), 2), "%"),
    paste0(round(ci_fn(m1)[1], 2), " – ", round(ci_fn(m1)[2], 2), "%"),
    paste0(round(sens_fn(m1), 2), "%"),
    paste0(round(spec_fn(m1), 2), "%"),
    paste0(round(hl1$statistic, 5), " (p = ", round(hl1$p.value, 4), ")")
  ),
  `Model 2 (Density Nominal)` = c(
    paste0(round(m2$null.deviance, 4), " (df = ", m2$df.null, ")"),
    paste0(round(deviance(m2), 4), " (df = ", m2$df.residual, ")"),
    round(logLik(m2)[1], 4),
    round(AIC(m2), 4),
    paste0(round(acc_fn(m2), 2), "%"),
    paste0(round(ci_fn(m2)[1], 2), " – ", round(ci_fn(m2)[2], 2), "%"),
    paste0(round(sens_fn(m2), 2), "%"),
    paste0(round(spec_fn(m2), 2), "%"),
    paste0(round(hl2$statistic, 5), " (p = ", round(hl2$p.value, 4), ")")
  ),
  check.names = FALSE
)

# ── Menampilkan tabel menggunakan kable untuk Rpubs ──────────────
library(knitr)
library(kableExtra)
kable(gof, caption = "Tabel 3. Statistik Kebaikan Suai (Goodness of Fit) Model", align="c") %>%
  kable_styling(full_width = FALSE, position = "center", bootstrap_options = c("striped", "hover", "condensed"))
Tabel 3. Statistik Kebaikan Suai (Goodness of Fit) Model
Metrik Evaluasi Model 1 (Density Kontinu) Model 2 (Density Nominal)
Null Deviance (df) 1147.156 (df = 827) 1147.156 (df = 827)
Residual Deviance (df) 726.8935 (df = 818) 723.6525 (df = 816)
Log-Likelihood Maximum (ln L) -363.4468 -361.8263
Akaike Information Criterion (AIC) 746.8935 747.6525
Akurasi Klasifikasi (%) 81.64% 81.52%
Rentang 95% Confidence Interval (CI) 79.01 – 84.28% 78.88 – 84.17%
Sensitivitas 85.32% 85.07%
Spesifisitas 78.17% 78.17%
Hosmer-Lemeshow χ² (p-value) 2.00894 (p = 0.9807) 1.06932 (p = 0.9978)
# ── Likelihood Ratio Test antara Model 1 dan Model 2 ─────────────────────────
lrt <- anova(m1, m2, test = "Chisq")
print(lrt)
#> Analysis of Deviance Table
#> 
#> Model 1: Severity ~ Age + Shape + Margin + Density
#> Model 2: Severity ~ Age + Shape + Margin + Density_cat
#>   Resid. Df Resid. Dev Df Deviance Pr(>Chi)
#> 1       818        727                     
#> 2       816        724  2     3.24      0.2

Pemilihan Model Terbaik. Model 2 menghasilkan Log-Likelihood yang sedikit lebih besar, namun pengujian LRT menghasilkan \(\chi^2 \approx 3{,}24\) (\(df = 2\), \(p = 0{,}1978 > 0{,}05\)), tidak signifikan secara statistik. Artinya fleksibilitas yang ditawarkan oleh Model 2 (Nominal) sama sekali tidak memberikan kontribusi peningkatan akurasi yang berarti pada data riil pasien di lapangan.

Berdasarkan prinsip parsimoni, Model 1 dipilih sebagai model final karena: - AIC lebih rendah (746,89 vs 747,65) - Efisiensi parameter lebih tinggi (df lebih besar) - Performa akurasi setara (81,64%) serta sensitivitas yang lebih tinggi (85,32%) yang lebih tinggi - Kedua model fit berdasarkan uji Hosmer-Lemeshow (\(p > 0{,}05\))

3.4 Uji Multikolinearitas

# ── GVIF (Generalized VIF) ────────────────────────────────────────────────────
gvif_res <- as.data.frame(car::vif(m1))
gvif_res$Variabel <- rownames(gvif_res)
names(gvif_res)[1:3] <- c("GVIF", "Df", "GVIF^(1/(2*Df))")
gvif_res$Keterangan <- ifelse(
  gvif_res$`GVIF^(1/(2*Df))` < 2,
  "Bebas Multikolinearitas", "Terindikasi Multikolinearitas"
)
gvif_out <- gvif_res[, c("Variabel", "GVIF", "Df", "GVIF^(1/(2*Df))", "Keterangan")]

nice_kable(gvif_out,
           caption = "Tabel 4. Hasil Uji Multikolinearitas (GVIF)",
           digits = 6)
Tabel 4. Hasil Uji Multikolinearitas (GVIF)
Variabel GVIF Df GVIF^(1/(2*Df)) Keterangan
Age Age 1.014 1 1.007 Bebas Multikolinearitas
Shape Shape 1.891 3 1.112 Bebas Multikolinearitas
Margin Margin 1.935 4 1.086 Bebas Multikolinearitas
Density Density 1.026 1 1.013 Bebas Multikolinearitas

Interpretasi GVIF. Seluruh variabel prediktor memiliki nilai \(\text{GVIF}^{1/(2\cdot df)}\) pada rentang yang sangat rendah (1,006855 hingga 1,112007). Hasil ini membuktikan bahwa Model 1 terbebas dari bias multikolinearitas, sehingga estimasi koefisien bersifat stabil dan bebas bias.

3.4.1 Uji Signifikansi Keseluruhan (Likelihood Ratio Test - LRT)

Berikut adalah tabel analisis deviance untuk menguji pengaruh seluruh variabel prediktor secara serentak:

# Model null untuk Model 1 (tanpa prediktor)
model_null1 <- glm(Severity ~ 1, data = mam, family = binomial(link = "logit"))

# Uji Chi-Square serentak untuk semua prediktor Model 1
anova(model_null1, m1, test = "Chisq")

3.5 Estimasi Parameter Model Terpilih (Model 1)

# ── Tabel koefisien regresi ────────────────────────────────────────────────────
coef_tbl <- as.data.frame(summary(m1)$coefficients)
coef_tbl$Variabel <- rownames(coef_tbl)
names(coef_tbl) <- c("β (Koefisien)", "SE", "z-value", "p-value", "Variabel")
coef_tbl$`Signifikansi` <- ifelse(
  coef_tbl$`p-value` < 0.001, "***",
  ifelse(coef_tbl$`p-value` < 0.01, "**",
         ifelse(coef_tbl$`p-value` < 0.05, "*",
                ifelse(coef_tbl$`p-value` < 0.1, ".", "ns")))
)

nice_kable(coef_tbl,
           caption = "Tabel 5. Koefisien Regresi Logistik Model 1",
           digits  = 4)
Geser tabel ke kanan/kiri untuk melihat seluruh kolom ↔︎
Tabel 5. Koefisien Regresi Logistik Model 1
β (Koefisien) SE z-value p-value Variabel Signifikansi
(Intercept) -4.4481 0.8645 -5.1452 0.0000 (Intercept) ***
Age 0.0549 0.0078 7.0747 0.0000 Age ***
ShapeOval -0.2744 0.3179 -0.8632 0.3880 ShapeOval ns
ShapeLobular 0.6089 0.3731 1.6321 0.1027 ShapeLobular ns
ShapeIrregular 1.3546 0.3325 4.0742 0.0000 ShapeIrregular ***
MarginMicrolobulated 1.6610 0.5602 2.9653 0.0030 MarginMicrolobulated **
MarginObscured 1.1852 0.3508 3.3788 0.0007 MarginObscured ***
MarginIll-defined 1.4733 0.3018 4.8822 0.0000 MarginIll-defined ***
MarginSpiculated 2.0068 0.3731 5.3784 0.0000 MarginSpiculated ***
Density -0.1327 0.2546 -0.5210 0.6024 Density ns

Persamaan Model Final (Model 1)

\[ \begin{aligned} \ln\left(\frac{p}{1-p}\right) = \; &{-4{,}4481} + {0{,}0549}(\text{Age}) - {0{,}2744}(\text{Shape}_{\text{Oval}}) + {0{,}6090}(\text{Shape}_{\text{Lobular}}) + {1{,}3546}(\text{Shape}_{\text{Irregular}}) \\ & + {1{,}6610}(\text{Margin}_{\text{Micro}}) + {1{,}1852}(\text{Margin}_{\text{Obscured}}) + {1{,}4733}(\text{Margin}_{\text{Ill-defined}}) + {2{,}0069}(\text{Margin}_{\text{Spiculated}}) - {0{,}1327}(\text{Density}) \end{aligned} \]

3.6 Analisis Odds Ratio Model Terpilih

# ── Odds Ratio dan CI ──────────────────────────────────────────────────────────
or_tbl <- as.data.frame(exp(cbind(OR = coef(m1), confint(m1, level = 0.95))))
or_tbl$Variabel <- rownames(or_tbl)
or_tbl$`CI 95%`  <- paste0(
  round(or_tbl$`2.5 %`, 4), " – ", round(or_tbl$`97.5 %`, 4)
)

# Ambil p-value dari model
pval <- summary(m1)$coefficients[, 4]
or_tbl$Signifikan <- ifelse(pval < 0.05, "Signifikan", "Tidak Signifikan")

or_out <- or_tbl[, c("Variabel", "OR", "CI 95%", "Signifikan")]
or_out <- or_out[-1, ]   # hapus intercept

nice_kable(or_out,
           caption = "Tabel 6. Estimasi Odds Ratio Model 1",
           digits  = 4)
Tabel 6. Estimasi Odds Ratio Model 1
Variabel OR CI 95% Signifikan
Age Age 1.0564 1.0408 – 1.073 Signifikan
ShapeOval ShapeOval 0.7600 0.4044 – 1.4123 Tidak Signifikan
ShapeLobular ShapeLobular 1.8385 0.8804 – 3.8142 Tidak Signifikan
ShapeIrregular ShapeIrregular 3.8753 2.0158 – 7.4491 Signifikan
MarginMicrolobulated MarginMicrolobulated 5.2647 1.7822 – 16.2625 Signifikan
MarginObscured MarginObscured 3.2714 1.6484 – 6.5377 Signifikan
MarginIll-defined MarginIll-defined 4.3637 2.4274 – 7.9461 Signifikan
MarginSpiculated MarginSpiculated 7.4398 3.6185 – 15.6858 Signifikan
Density Density 0.8758 0.5331 – 1.4536 Tidak Signifikan

Interpretasi Estimasi Parameter dan Odds Ratio Utama

Variabel β OR p-value Interpretasi
Intercept -4,4481 - <0.001 Nilai logit saat semua prediktor = 0; probabilitas 0,47%.
Age 0.0549 1.0564 <0.001 Setiap kenaikan usia 1 tahun, odds keganasan meningkat 5,64% (CI: 4,02%–7,31%).
Shape Oval -0,2744 0.76 0.3881 Lesi oval memiliki odds 19,27% lebih rendah dibanding Round; tidak signifikan.
Shape Lobular 0,6090 1,8385 0.1027 Lesi berbentuk lobular memiliki odds 67,75% lebih tinggi dibanding Round; tidak signifikan.
Shape Irregular 1.3546 3.8753 <0.001 Lesi irregular memiliki odds 3,87× lebih tinggi dibanding Round; signifikan.
Margin Microlobulated 1,661 5,2647 0.0074 Odds 5,26× lebih tinggi dibanding Circumscribed; signifikan.
Margin Obscured 1,1852 3,2714 <0.001 Odds 3,27× lebih tinggi dibanding Circumscribed; signifikan.
Margin Ill-defined 1,4733 4,3637 <0.001 Odds 4,36× lebih tinggi dibanding Circumscribed; signifikan.
Margin Spiculated 2.0069 7.4398 <0.001 Odds 7,44× lebih tinggi dibanding Circumscribed; signifikan; penanda utama stadium lanjut.
Density -0.1327 0.8758 0.6000 Setiap kenaikan 1 satuan skor menunjukkan penurunan odds keganasan 12,42%; tidak signifikan.

3.7 Evaluasi Prediksi Model — Confusion Matrix

# ── Confusion Matrix (threshold = 0.5) ────────────────────────────────────────
pred_class <- factor(
  ifelse(fitted(m1) > 0.5, "Malignant", "Benign"),
  levels = c("Benign", "Malignant")
)

cm <- confusionMatrix(pred_class, mam$Severity, positive = "Malignant")
print(cm)
#> Confusion Matrix and Statistics
#> 
#>            Reference
#> Prediction  Benign Malignant
#>   Benign       333        59
#>   Malignant     93       343
#>                                               
#>                Accuracy : 0.816               
#>                  95% CI : (0.788, 0.842)      
#>     No Information Rate : 0.514               
#>     P-Value [Acc > NIR] : < 0.0000000000000002
#>                                               
#>                   Kappa : 0.633               
#>                                               
#>  Mcnemar's Test P-Value : 0.00744             
#>                                               
#>             Sensitivity : 0.853               
#>             Specificity : 0.782               
#>          Pos Pred Value : 0.787               
#>          Neg Pred Value : 0.849               
#>              Prevalence : 0.486               
#>          Detection Rate : 0.414               
#>    Detection Prevalence : 0.527               
#>       Balanced Accuracy : 0.817               
#>                                               
#>        'Positive' Class : Malignant           
#> 
# ── Sajikan confusion matrix sebagai tabel ─────────────────────────────────────
cm_df <- data.frame(
  ` ` = c("Prediksi Benign (Jinak)", "Prediksi Malignant (Ganas)", "Total Aktual"),
  `Aktual: Benign` = c(
    paste0(cm$table[1,1], " (True Negative)"),
    paste0(cm$table[2,1], " (False Positive)"),
    cm$table[1,1] + cm$table[2,1]
  ),
  `Aktual: Malignant` = c(
    paste0(cm$table[1,2], " (False Negative)"),
    paste0(cm$table[2,2], " (True Positive)"),
    cm$table[1,2] + cm$table[2,2]
  ),
  `Total Prediksi` = c(
    cm$table[1,1] + cm$table[1,2],
    cm$table[2,1] + cm$table[2,2],
    nrow(mam)
  ),
  check.names = FALSE
)

knitr::kable(cm_df,
             caption = "Tabel 7. Confusion Matrix Klasifikasi Keganasan Model 1",
             align   = "c")
Tabel 7. Confusion Matrix Klasifikasi Keganasan Model 1
Aktual: Benign Aktual: Malignant Total Prediksi
Prediksi Benign (Jinak) 333 (True Negative) 59 (False Negative) 392
Prediksi Malignant (Ganas) 93 (False Positive) 343 (True Positive) 436
Total Aktual 426 402 828

Ringkasan Performa Klasifikasi Model 1

Metrik Nilai
Akurasi Keseluruhan 81,64% (95% CI: 78,83% – 84,22%)
Sensitivitas (True Positive Rate) 85,32%
Spesifisitas (True Negative Rate) 78,17%
Kappa 0,6333 (Substantial Agreement)
Hosmer-Lemeshow \(p\)-value 0,9807 (Model Fit)

Performa Klasifikasi Model (Confusion Matrix):

  • Akurasi Keseluruhan (81,64%; 95% CI = 78,83% – 84,22%) — Model memiliki reliabilitas yang tinggi dalam mengklasifikasikan massa tumor secara tepat, yang berarti dalam implementasi riil sistem pendukung keputusan (Clinical Decision Support System), komputer mampu memprediksi dengan benar status keganasan pada 81 dari 100 pasien berdasarkan karakteristik mammografinya.
  • Sensitivitas / True Positive Rate (85,32%) — Indikator paling krusial dalam domain onkologi medis; model berhasil mendeteksi secara akurat 343 dari 402 kasus ganas aktual. Nilai sensitivitas yang tinggi ini meminimalkan risiko pasien kanker lolos diagnosis (False Negative) menjadi hanya 14,68% (59 kasus), sehingga sangat aman digunakan sebagai instrumen skrining awal agar pasien tidak terlambat mendapatkan penanganan biopsi atau bedah.
  • Spesifisitas / True Negative Rate (78,17%) — Model mampu mengidentifikasi secara benar 333 dari 426 pasien yang secara aktual memiliki tumor jinak (True Negative). Tingkat spesifisitas yang stabil ini berfungsi menekan angka kesalahan vonis ganas (False Positive) menjadi 21,83% (93 kasus), yang dalam implementasi klinis berperan penting mengurangi kecemasan psikologis pasien serta mencegah terjadinya tindakan medis lanjutan yang tidak perlu (overtreatment).
  • Goodness-of-Fit (Hosmer-Lemeshow \(\chi^2\) = 2,00089; \(p = 0{,}9807\)) — Menunjukkan nilai \(p\text{-value}\) yang sangat tinggi jauh di atas batas kritis 0,05. Hal ini membuktikan secara sahih tidak ada perbedaan signifikan antara frekuensi hasil prediksi model dengan data aktual di lapangan, sehingga model regresi kontinu ini dinyatakan sangat layak (fit), stabil, dan valid.

3.8 Penanganan Variabel Density yang Tidak Signifikan

Meskipun tidak signifikan secara statistik, variabel Density tetap dipertahankan dalam model final dengan landasan ilmiah:

Density tetap dipertahankan (diretensi) di dalam model final meskipun tidak signifikan adalah karena kepatuhan terhadap Standar Internasional BI-RADS (Breast Imaging Reporting and Data System). Berdasarkan panduan resmi American College of Radiology (ACR), penilaian tingkat kepadatan (density) jaringan payudara merupakan komponen wajib dan mutlak yang harus dilaporkan dalam setiap pemeriksaan mamografi bersama dengan karakteristik Shape (bentuk) dan Margin (tepi). Mengeluarkan variabel ini hanya karena pertimbangan angka statistik (p-value) akan menyebabkan model menyalahi protokol standar klinis yang berlaku di dunia medis. Oleh karena itu, variabel Density tetap dimasukkan sebagai variabel kontrol wajib untuk menjaga validitas, objektivitas, dan pemenuhan standar regulasi medis yang utuh.

4 Discussion

Hasil pengujian parsial Wald pada Model 1 menunjukkan bahwa variabel Age, karakteristik bentuk Shape Irregular, serta seluruh level pada karakteristik Margin memiliki kontribusi yang signifikan (p < 0,05) dalam membentuk probabilitas keganasan lesi payudara. Sebaliknya, karakteristik bentuk Shape Oval (p = 0,388) dan Shape Lobular (p = 0,1027) terbukti tidak memiliki perbedaan risiko yang signifikan jika dibandingkan dengan bentuk acuan bulat (Round).

Variabel Usia (Age) memperlihatkan hubungan positif linier yang kuat terhadap kecenderungan keganasan (p < 0,001; OR = 1,0564). Setiap peningkatan usia pasien sebesar satu tahun akan meningkatkan risiko keganasan lesi sebesar 1,056 kali lipat. Hal ini sejalan dengan data epidemiologi WHO [2] yang menyatakan bahwa pertambahan usia berkaitan erat dengan paparan kumulatif hormonal estrogen internal serta penurunan efektivitas mekanisme perbaikan kerusakan DNA seluler akibat penuaan jaringan stroma payudara [2, 1].

Bentuk massa tidak beraturan (Shape Irregular) memiliki nilai OR = 3,8753 terhadap bentuk bulat (Round). Hilangnya batas sferis simetris mengindikasikan karakteristik sel kanker yang invasif, di mana proliferasi sel terjadi dengan kecepatan tidak seragam dan mendesak jaringan parenkim payudara yang sehat di sekitarnya [1].

Indikator risiko tinggi ditunjukkan oleh tepi berduri (Margin Spiculated) dengan OR = 7,4398 terhadap tepi halus (Circumscribed). Secara patologi anatomi, visualisasi tepi berduri (spiculated margin) pada citra mammografi merupakan manifestasi langsung dari proses desmoplasia akibat infiltrasi untaian sel ganas yang menginvasi stroma payudara, menjadikannya penanda utama tumor ganas stadium lanjut secara radiologis [1].

5 Kesimpulan

5.0.1 Ringkasan Temuan Utama

  1. Model terpilih adalah Model 1 (Density) sebagai skala kontinu terbukti sebagai spesifikasi terbaik berdasarkan prinsip parsimoni statistik. Model ini menghasilkan efisiensi parameter optimal dengan nilai AIC terendah (746,8935) dan akurasi model paling tinggi (81,64%).

  2. Performa diagnostik andal: Model matematika yang dikembangkan memiliki tingkat sensitivitas tinggi mencapai 85,32%, yang berarti sangat handal dan aman dalam meminimalkan risiko lolosnya pasien kanker dari penegakan diagnosis awal (False Negative).

  3. Prediktor keganasan utama:

    • Usia pasien (Age) — risiko naik 1,056× per tahun
    • Bentuk tidak beraturan (Shape Irregular) — risiko 3,87×
    • Tepi berduri (Margin Spiculated) — risiko tertinggi 7,44×
  4. Density tidak signifikan secara statistik namun dipertahankan sebagai kontrol klinis radiologis (masking effect, standar BI-RADS).

  5. Model direkomendasikan sebagai instrumen pendukung keputusan klinis (DSS) untuk membantu radiolog meningkatkan efektivitas deteksi dini kanker payudara.

6 Referensi

  1. Suparna, K.; Sari, L.M.K.K.S. Kanker payudara: diagnostik, faktor risiko, dan stadium. Ganesha Medicina 2022, 2, 42–48. https://doi.org/10.23887/gm.v2i1.47032

  2. World Health Organization. Breast cancer. Available online: https://www.who.int/news-room/fact-sheets/detail/breast-cancer (accessed on 14 August 2025).

  3. Bodewes, F.T.H.; van Asselt, A.A.; Dorrius, M.D.; Greuter, M.J.W.; de Bock, G.H. Mammographic breast density and the risk of breast cancer: A systematic review and meta-analysis. The Breast 2022, 66, 279–289. https://doi.org/10.1016/j.breast.2022.09.007

  4. Hosmer, D.W.; Lemeshow, S.; Sturdivant, R.X. Applied Logistic Regression, 3rd ed.; Wiley: New York, 2013.

  5. UCI Machine Learning Repository — Mammographic Mass Dataset. https://archive.ics.uci.edu/dataset/161/mammographic+mass