Dosen Pengampu: Ike Fitriyaningsih, M.Si
## age gender chest_pain_type blood_pressure cholesterol max_heart_rate
## 1 24 1 4 250 139 212
## 2 29 0 4 132 187 147
## 3 46 0 3 271 185 193
## 4 73 NA 2 102 200 125
## 5 49 1 3 91 163 192
## 6 63 1 3 18 154 107
## 7 48 0 3 143 275 165
## 8 37 1 4 263 201 201
## 9 20 0 3 113 127 139
## 10 77 1 1 138 217 201
## exercise_angina plasma_glucose skin_thickness insulin bmi
## 1 0 108 33 109 37.99930
## 2 0 202 42 NA 25.58835
## 3 0 149 43 102 37.89203
## 4 0 105 77 165 18.66024
## 5 0 162 31 170 12.76798
## 6 0 103 67 102 22.37385
## 7 0 248 NA 136 27.90071
## 8 0 186 21 180 35.66340
## 9 1 123 NA 120 26.52915
## 10 0 199 100 132 18.39360
## diabetes_pedigree hypertension heart_disease residence_type smoking_status
## 1 0.4802775 1 1 Urban Smoker
## 2 0.2839864 1 1 Urban Unknown
## 3 2.4723086 1 0 Rural Non-Smoker
## 4 1.4720523 0 1 Rural Smoker
## 5 0.5376265 1 1 Rural Smoker
## 6 1.0624109 0 0 Rural Non-Smoker
## 7 1.0737608 1 1 Rural Non-Smoker
## 8 0.1512359 0 0 Urban Smoker
## 9 1.9102780 1 0 Urban Non-Smoker
## 10 1.8253058 1 0 Rural Non-Smoker
data %>%
summarise(across(everything(), ~sum(is.na(.)))) %>%
pivot_longer(everything(), names_to = "Kolom", values_to = "Jumlah_NA") %>%
mutate(Persen_NA = round((Jumlah_NA / nrow(data)) * 100, 2))## # A tibble: 16 × 3
## Kolom Jumlah_NA Persen_NA
## <chr> <int> <dbl>
## 1 age 0 0
## 2 gender 472 7.87
## 3 chest_pain_type 0 0
## 4 blood_pressure 0 0
## 5 cholesterol 0 0
## 6 max_heart_rate 0 0
## 7 exercise_angina 0 0
## 8 plasma_glucose 609 10.2
## 9 skin_thickness 614 10.2
## 10 insulin 568 9.47
## 11 bmi 0 0
## 12 diabetes_pedigree 0 0
## 13 hypertension 0 0
## 14 heart_disease 0 0
## 15 residence_type 0 0
## 16 smoking_status 0 0
# Cek nilai kosong " " atau spasi pada kolom karakter
sapply(data, function(x) {
if (is.character(x) || is.factor(x)) sum(trimws(x) == "") else 0
})## age gender chest_pain_type blood_pressure
## 0 0 0 0
## cholesterol max_heart_rate exercise_angina plasma_glucose
## 0 0 0 0
## skin_thickness insulin bmi diabetes_pedigree
## 0 0 0 0
## hypertension heart_disease residence_type smoking_status
## 0 0 455 0
Dari hasil cek nilai kosong pada setiap kolom dataset, ditemukan kolom gender, plasma_glucose, skin_thickness, dan insulin memiliki nilai kosong (NA). Selain itu, terdapat 455 baris nilai dengan kolom kosong (” “) pada kolom residence_type, yang berarti baris-baris tersebut tidak memiliki informasi tentang jenis tempat tinggal pasien.
ohe_encode <- function(df, column) {
dummies <- dummyVars(as.formula(paste("~", column)), data = df)
ohe <- predict(dummies, newdata = df)
colnames(ohe) <- gsub("\\.", "_", colnames(ohe))
ohe_df <- as.data.frame(ohe)
df <- cbind(df, ohe_df)
df <- df[, !(names(df) %in% column)]
return(df)
}
data <- ohe_encode(data, "residence_type")
data <- ohe_encode(data, "gender")
data <- ohe_encode(data, "smoking_status")data %>%
summarise(across(everything(), ~sum(is.na(.)))) %>%
pivot_longer(everything(), names_to = "Kolom", values_to = "Jumlah_NA") %>%
mutate(Persen_NA = round((Jumlah_NA / nrow(data)) * 100, 2))## # A tibble: 18 × 3
## Kolom Jumlah_NA Persen_NA
## <chr> <int> <dbl>
## 1 age 0 0
## 2 chest_pain_type 0 0
## 3 blood_pressure 0 0
## 4 cholesterol 0 0
## 5 max_heart_rate 0 0
## 6 exercise_angina 0 0
## 7 plasma_glucose 0 0
## 8 skin_thickness 0 0
## 9 insulin 0 0
## 10 bmi 0 0
## 11 diabetes_pedigree 0 0
## 12 hypertension 0 0
## 13 heart_disease 0 0
## 14 residence_typeRural 0 0
## 15 residence_typeUrban 0 0
## 16 smoking_statusNon-Smoker 0 0
## 17 smoking_statusSmoker 0 0
## 18 smoking_statusUnknown 0 0
fcm_result <- cmeans(data_scaled, centers = 3, m = 2)
fviz_cluster(list(data = data_scaled, cluster = fcm_result$cluster),
main = "Fuzzy C-Means Clustering tanpa PCA)")
Proses lanjutan dari preprocessing adalah analisis menggunakan algoritma
Fuzzy C-Means (FCM) tanpa PCA. Parameter jumlah klaster ditentukan 3
cluster sesuai asumsi awal segmentasi yang diinginkan. Selain itu
digunakan parameter fuzziness m = 2, yang merupakan nilai default umum
untuk mengatur derajat keanggotaan ganda dimana semakin besar m, semakin
kabur batas klasternya.
Visualisasi Fuzzy C-Means tanpa PCA menunjukkan tiga klaster yang terpisah dengan jelas, masing-masing ditandai oleh warna merah, hijau, dan biru. Metode Fuzzy C-Means membolehkan setiap data memiliki keanggotaan pada lebih dari satu klaster, sehingga area antar klaster saling tumpang tindih dan batas klaster kurang tegas.
silhouette_fcm <- silhouette(fcm_result$cluster, dist(data_scaled))
silhouette_score_fcm <- mean(silhouette_fcm[, 3])
cat("Silhouette Score Fuzzy C-Means tanpa PCA:", silhouette_score_fcm)## Silhouette Score Fuzzy C-Means tanpa PCA: 0.08152587
Pada bagian ini didapatkan Silhouette Score Fuzzy C-Means sebesar 0.098, yang menandakan kualitas klaster masih tergolong rendah. Hal ini terjadi karena dimensi data yang tinggi, serta tumpang tindih antar klaster.
## PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10
## 0.10366 0.20654 0.27089 0.33078 0.38998 0.44797 0.50503 0.56139 0.61739 0.67246
## PC11 PC12 PC13 PC14 PC15 PC16 PC17 PC18
## 0.72705 0.78132 0.83493 0.88817 0.94046 0.99219 1.00000 1.00000
# Hitung variansi kumulatif
cum_var <- summary(pca_res)$importance[3, ]
n_components <- which(cum_var >= 0.8)[1]
pca_data <- as.data.frame(pca_res$x[, 1:3])Hasil visualisasi scree plot menunjukkan bahwa komponen utama pertama (PC1) hingga komponen kedua (PC2) menyumbang proporsi variansi yang cukup besar dibandingkan komponen-komponen berikutnya. Grafik memperlihatkan pola “elbow” yang menandakan penurunan signifikan dalam kontribusi variansi setelah beberapa komponen awal.
Namun demikian, dalam konteks klasterisasi, tujuan utama bukan hanya mempertahankan sebanyak mungkin variansi data, melainkan merepresentasikan struktur spasial data secara optimal agar klaster yang terbentuk lebih kompak dan terpisah dengan jelas. Perlu dipahami bahwa variansi yang tinggi belum tentu relevan dalam proses klasterisasi apabila informasi yang dikandung tidak berkontribusi terhadap pemisahan jarak antar titik data.
Oleh karena itu, pemilihan jumlah komponen utama tidak semata-mata didasarkan pada nilai variansi kumulatif, melainkan juga mempertimbangkan kualitas hasil klasterisasi misalnya melalui nilai Silhouette Score. Berdasarkan pertimbangan tersebut, tiga komponen utama pertama dipilih untuk digunakan dalam proses klasterisasi.
fcm_pca <- cmeans(pca_data, centers = 3, m = 2)
fviz_cluster(list(data = pca_data, cluster = fcm_pca$cluster),
main = "Fuzzy C-Means Clustering dengan PCA")silhouette_fcm_pca <- silhouette(fcm_pca$cluster, dist(pca_data))
silhouette_score_fcm_pca <- mean(silhouette_fcm_pca[, 3])
cat("Silhouette Score Fuzzy C-Means dengan PCA:", silhouette_score_fcm_pca)## Silhouette Score Fuzzy C-Means dengan PCA: 0.5341565
Setelah data direduksi dimensinya menggunakan PCA menjadi 3 komponen utama, selanjutnya dilakukan klasterisasi menggunakan Fuzzy C-Means.
Hasil visualisasi klaster menunjukkan adanya tiga klaster utama yang terbentuk, yaitu:
Cluster 1 warna merah
Cluster 2 warna hijau
Cluster 3 warna biru
Dengan silhouette score 0.534, pengelompokan klaster lebih terlihat terpisah meski antar klaster masih nampak tumpang tindih
silhouette_df <- data.frame(
Metode = c("Tanpa PCA", "Dengan PCA"),
Silhouette = c(silhouette_score_fcm, silhouette_score_fcm_pca)
)
ggplot(silhouette_df, aes(x = Metode, y = Silhouette, fill = Metode)) +
geom_bar(stat = "identity", width = 0.4) +
ggtitle("Perbandingan Silhouette Score Fuzzy C-Means") +
theme_minimal()## cluster size ave.sil.width
## 1 1 2981 0.08
## 2 2 4 0.34
## 3 3 3015 0.08
Hasil silhouette plot tanpa PCA menunjukkan tiga klaster dengan ukuran
yang tidak seimbang, dimana klaster 1 dan klaster 2 mendominasi dengan
2825 data dan 2951 data. Sedangkan klaster 3 terendah berisi 224 data.
Rata-rata nilai silhouette pada ketiga klaster relatif rendah, yaitu
hanya 0.12 unruk klaster 1, 0.08 unruk klaster 2, dan 0.26 untuk klaster
3, yang mengindikasikan bahwa pemisahan antar klaster kurang optimal dan
terdapat tumpang tindih yang cukup besar antar anggota klaster.
Nilai-nilai ini mencerminkan bahwa struktur klaster yang terbentuk belum
cukup baik dalam memisahkan kelompok data secara jelas.
## cluster size ave.sil.width
## 1 1 1621 0.57
## 2 2 1560 0.60
## 3 3 2819 0.47
Hasil silhouette plot menunjukkan pembentukan tiga klaster dengan ukuran
yang cukup seimbang, yakni klaster 1 sebanyak 1547 data, klaster 2
sebanyak 1683 data, dan klaster 3 sebanyak 2770 data. Rata-rata nilai
silhouette untuk masing-masing klaster adalah 0,61 untuk klaster 1, 0,57
untuk klaster 2, dan 0,47 untuk klaster 3, yang mencerminkan kualitas
pemisahan klaster yang cukup baik. Nilai silhouette tertinggi terdapat
pada klaster 1, menunjukkan pemisahan yang jelas dari klaster lain,
diikuti oleh klaster 2 dan klaster 3.
Hal ini mengindikasikan bahwa penggunaan PCA berkontribusi positif dalam membentuk struktur klaster yang lebih jelas dan proporsional, dibandingkan clustering tanpa PCA.