R-Markdown ini berisi tentang tahapan melakukan analisis clustering data menggunakan metode Fuzzy C-Means Clustering. Cara kerja algoritma Fuzzy C-Means yaitu dengan menggeser pusat cluster tidak terlalu banyak dan dapat memberikan hasil cluster. Fuzzy C-Means merupakan suatu metode mengelompokkan data yang keberadaan titik datanya ditentukan berdasarkan derajat keanggotaan dengan skala antara 0 sampai 1.
Analisis ini menggunakan data dari dataset berikut (data bersumber
dari data sekunder di website BPS Provinsi Jateng):
DATA
PENDIDIKAN
Berdasarkan dataset tersebut, akan dilakukan clustering 34
kabupaten/kota di Provinsi Jawa Tengah berdasarkan Indikator Pendidikan
dan Literasi Tahun 2024, dengan variabel yang digunakan dalam analisis
sebagai berikut:
1. RLS (Rata-Rata Lama Sekolah)
2. IPLM (Indeks Pembangunan Literasi Masyarakat)
3. TKM (Tingkat Kegemaran Membaca)
Tahapan analisis clustering dengan metode Fuzzy C-Means Clustering di
R sebagai berikut:
1. Memanggil Package yang dibutuhkan
2. Mengimpor data
3. Mendeskripsikan data menggunakan statistika deskriptif
4. Checking outlier dan Menangani Outlier
5. Menyamakan skala data dengan Normalisasi Min-Max
6. Melakukan uji sampel representatif menggunakan KMO
7. Melakukan uji non-multikolinearitas dengan nilai VIF
8. Melakukan analisis dengan Fuzzy C-Means Clustering
9. Melakukan validasi cluster dengan Indeks Xie Beni, Partition
Coefficient, Modified Partition Coefficient
10. Evaluasi jumlah cluster optimal dan m-fuzzier terbaik
11. Profilisasi serta interpretasi karakteristik wilayah masing-masing
cluster
12. Visualisasi Cluster
# Membaca data
data <- read_excel("D:\\SEMESTER 6\\KOMLAN\\DATA PENDIDIKAN.xlsx")
data <- as.data.frame(data)
head(data)## Kabupaten/Kota RLS IPLM TKM
## 1 Cilacap 7.40 64.41 68.99
## 2 Banyumas 7.91 67.88 67.39
## 3 Purbalingga 7.36 70.33 63.98
## 4 Banjarnegara 6.87 73.11 63.85
## 5 Kebumen 7.87 78.81 80.77
## 6 Purworejo 8.65 78.32 70.24
## RLS IPLM TKM
## Min. : 6.410 Min. : 44.56 Min. :63.11
## 1st Qu.: 7.380 1st Qu.: 61.75 1st Qu.:67.09
## Median : 7.870 Median : 66.65 Median :72.56
## Mean : 8.321 Mean : 68.82 Mean :73.13
## 3rd Qu.: 9.270 3rd Qu.: 74.98 3rd Qu.:78.17
## Max. :11.480 Max. :100.00 Max. :88.43
Keterangan:
Output tersebut memberikan gambaran umum mengenai statistika deskriptif
masing-masing variabel (mean, median, nilai minimum, nilai maksimum,
kuartil) sehingga dapat dilihat rentang nilai tiap variabel sebelum
diproses lebih lanjut.
Outlier adalah sebuah titik yang terletak sangat jauh dari rata-rata variabel random pada umumnya yang berkorelasi dengan titik tersebut. Jarak antara outlier dengan nilai variabel random lain diukur terhadap ambang batas yang diberikan, biasanya beberapa kali dari standar deviasi. Pada klasterisasi, adanya outlier dapat menghasilkan kelompok klaster yang berbeda dengan jumlah outlier biasanya sedikit.
Deteksi Outlier
Salah satu metode deteksi outlier adalah pendeteksian outlier dengan
jarak Mahalanobis. Pendeteksian outlier dengan jarak Mahalanobis
merupakan pendeteksian outlier multivariat dengan mempertimbangkan
hubungan dua atau lebih variabel secara bersamaan. Jarak Mahalanobis
adalah jarak antara titik data dengan centroid dari sekelompok data
dengan memperhitungkan korelasi antarvariabel. \[D^2 = (x - \mu)^T \Sigma^{-1} (x - \mu)\]
Keterangan:
\(D^2\) : Jarak Mahalanobis
\(x\) : Vektor observasi (data)
\(\mu\) : Vektor rata-rata (centroid)
dari data
\(\Sigma^{-1}\) : Invers dari matriks
kovarians
Data yang memiliki nilai \(D^2\) lebih besar dari nilai kritis Chi-Square (\(\chi^2\)) akan diidentifikasi sebagai outlier.
Penanganan Outlier
Salah satu metode penanganan outlier adalah dengan menggunakan
Winsorization. Winsorization merupakan metode penanganan outlier dengan
mengganti nilai outlier dengan persentil tertentu sehingga distribusi
data dan jumlah sampel masih lengkap dan mengurangi pengaruh
outlier.
# 1. Menghitung Jarak Mahalanobis
center <- colMeans(data_num)
cov_matrix <- cov(data_num)
jarak_mah <- mahalanobis(data_num, center, cov_matrix)
# 2. Menentukan nilai kritis (alpha = 0.05, df = jumlah variabel)
cutoff <- qchisq(p = 0.95, df = ncol(data_num))
outliers <- which(jarak_mah > cutoff)
cat("Batas kritis Chi-Square:", cutoff, "\n")## Batas kritis Chi-Square: 7.814728
## Terdapat 2 kabupaten/kota yang terdeteksi sebagai outlier multivariat:
## [1] "Karanganyar" "Kota Magelang"
# 3. Melakukan Capping / Winsorize (Batas 5% bawah dan 95% atas)
winsorize <- function(x, lower = 0.05, upper = 0.95) {
q_lower <- quantile(x, lower)
q_upper <- quantile(x, upper)
x[x < q_lower] <- q_lower
x[x > q_upper] <- q_upper
return(x)
}
# 4. Menerapkan winsorize pada seluruh kolom numerik
data_num <- as.data.frame(lapply(data_num, winsorize))
rownames(data_num) <- rownames(data) # Kembalikan nama baris
cat("\n--- Statistika Deskriptif Setelah Winsorize ---\n")##
## --- Statistika Deskriptif Setelah Winsorize ---
## RLS IPLM TKM
## Min. : 6.777 Min. :45.44 Min. :63.94
## 1st Qu.: 7.380 1st Qu.:61.75 1st Qu.:67.09
## Median : 7.870 Median :66.65 Median :72.56
## Mean : 8.329 Mean :68.85 Mean :73.05
## 3rd Qu.: 9.270 3rd Qu.:74.98 3rd Qu.:78.17
## Max. :11.304 Max. :99.89 Max. :84.78
Keterangan:
Berdasarkan pengecekan outlier menggunakan jarak mahalanobis, didapatkan
batas kritis Chi-Square pada data sebesar 7.8147, data
yang memiliki jarak mahalanobis yang lebih besar daripada nilai
Chi-Square tersebut dianggap outlier. Setelah dilakukan pengujian,
terdapat 2 wilayah yang terdeteksi sebagai outlier yaitu
Karanganyar dan Kota Magelang. Outlier
ditangani dengan menggunakan metode winsorization dengan batas bawah 5%
dan batas atas 95%.
Normalisasi diperlukan ketika variabel-variabel dalam model memiliki
satuan atau skala yang berbeda karena variabel dengan skala yang lebih
besar akan memiliki pengaruh dominan dan menyebabkan terjadinya bias
dalam proses analisis. Salah satu metode normalisasi yang sering
digunakan adalah Normalisasi Min-Max. Normalisasi Min-Max adalah metode
yang mentransformasikan nilai variabel sehingga berada dalam rentang
[0,1] \[X_{norm} = \frac{X - X_{min}}{X_{max}
- X_{min}}\] Keterangan:
\(X_{norm}\) : Nilai hasil
normalisasi
\(X\) : Nilai data asli
\(X_{min}\) : Nilai minimum pada
variabel tersebut
\(X_{max}\) : Nilai maksimum pada
variabel tersebut
# Normalisasi Min Max
normalize_minmax <- function(x) {
return ((x - min(x)) / (max(x) - min(x)))
}
data_norm <- as.data.frame(lapply(data_num, normalize_minmax))
rownames(data_norm) <- rownames(data_num)
# Cek hasil normalisasi
summary(data_norm)## RLS IPLM TKM
## Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.1332 1st Qu.:0.2996 1st Qu.:0.1514
## Median :0.2414 Median :0.3896 Median :0.4137
## Mean :0.3428 Mean :0.4300 Mean :0.4371
## 3rd Qu.:0.5507 3rd Qu.:0.5426 3rd Qu.:0.6829
## Max. :1.0000 Max. :1.0000 Max. :1.0000
Keterangan:
Dikarenakan setiap variabel (RLS, IPLM, TKM) memiliki skala pengukuran
yang berbeda, maka dilakukan normalisasi min-max untuk menyetarakan
skala data sehingga data memiliki rentang [0,1]. Hal ini dilakukan untuk
mencegah adanya bias.
Data yang digunakan dalam analisis cluster harus dapat menggambarkan kondisi sebenarnya dari populasi sehingga hasil yang didapatkan dapat maksimal. Pengujian asumsi dapat dilakukan dengan uji Kaiser Mayer-Olkin (KMO). Sampel dianggap dapat mewakili populasi jika nilai KMO lebih besar dari 0,5 maka sampel mewakili populasi sehingga layak untuk dilakukan analisis cluster. \[ \text{KMO} = \frac{\sum_{j=1}^{m} \sum_{k=1, k \neq j}^{m} r^2_{x_j x_k}}{\sum_{j=1}^{m} \sum_{k=1, k \neq j}^{m} r^2_{x_j x_k} + \sum_{j=1}^{m} \sum_{k=1, k \neq j}^{m} \rho^2_{x_j x_k}} \]
Keterangan:
\(\text{KMO}\) = nilai uji
Kaiser-Mayer-Olkin
\(m\) = banyak variabel
\(r^2_{x_j x_k}\) = korelasi antara
variabel \(x_j\) dan \(x_k\)
\(\rho^2_{x_j x_k}\) = korelasi parsial
antara variabel \(x_j\) dan \(x_k\)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = data_norm)
## Overall MSA = 0.58
## MSA for each item =
## RLS IPLM TKM
## 0.55 0.55 0.80
Keterangan:
Nilai KMO untuk setiap variabel > 0.5 sehingga sampel yang digunakan
sudah representatif dan mampu mewakili populasi dengan baik.
Multikolinieritas adalah adanya hubungan linier yang sempurna atau pasti di antara beberapa atau semua variabel. Cara untuk mengidentifikasi multikolinearitas adalah menghitung nilai Variance Inflation Factor (VIF). Jika nilai VIF < 10 dianggap tidak terdapat multikolinearitas dalam data. \[ VIF_j = \frac{1}{1 - R_j^2} \]
Keterangan:
\(VIF_j\) = nilai Variance Inflation
Factor (VIF) pada variabel ke-j
\(R_j^2\) = Koefisien determinasi
variabel \(X_j\) pada variabel bebas
lainnya dalam model
\(j\) = \(1,
2, \dots, m\)
# Uji Asumsi Non Multikolinearitas
dummy_model <- lm(rnorm(nrow(data_norm)) ~ RLS + IPLM + TKM, data = data_norm)
vif_result <- vif(dummy_model)
print(vif_result)## RLS IPLM TKM
## 1.773937 1.818769 1.110668
Keterangan:
Nilai VIF untuk setiap variabel < 10 sehingga tidak ada hubungan
linear yang sempurna antarvariabel dan asumsi non multikolinearitas
terpenuhi.
Diperlukan uji coba dengan beberapa nilai k cluster untuk mendapatkan hasil yang optimal. Sebagian besar literatur dan jurnal penelitian menggunakan m = 2 sebagai standar agar sifat fuzzy (keanggotaan probabilistik) dari algoritma ini tetap optimal. Hasil dari beberapa k cluster kemudian divalidasi untuk mendapatkan nilai k yang optimal.
Validasi Cluster
Validasi cluster diperlukan untuk melakukan pengujian cluster yang
optimal serta untuk menilai seberapa tepat suatu objek dikelompokkan
dalam cluster tersebut. Beberapa validasi cluster yang dapat digunakan
seperti, indeks Xie-Beni, indeks Partition Coefficient (PC), indeks
Modified Partition Coefficient (MPC).
Indeks Xie-Beni
Indeks Xie-Beni didasarkan pada jarak intracluster yaitu kedekatan antar
anggota di setiap cluster dan intercluster yaitu perbedaan antara suatu
cluster dengan cluster lain. Banyak cluster optimum didapatkan dengan
meminimalkan nilai indeks.
\[
XB = \frac{\sum_{i=1}^{n} \sum_{k=1}^{c} \left( \mu_{ik}^w \left[
\sum_{j=1}^{m} (X_{ij} - V_{kj})^2 \right] \right)}{n \min_{i \neq k}
\left[ \sum_{j=1}^{m} (V_{ij} - V_{kj})^2 \right]}
\] Dimana:
\(X_{ij}\) = objek data ke-i pada
variabel ke-j,
\(V_{kj}\) = nilai pusat
cluster ke-k pada variabel ke-j,
\(V_{ij}\) = nilai pusat
cluster ke-i pada variabel ke-j,
\(\mu_{ik}\) = nilai keanggotaan objek
data ke-i dengan pusat cluster ke-k
Indeks Partition Coefficient
Indeks Partition Coefficient digunakan untuk menguji nilai derajat
keanggotaan, tanpa melihat nilai data yang biasanya mengandung informasi
geometrik atau sebaran data. Jumlah cluster optimal diperoleh dengan
melihat nilai indeks terbesar. \[
PC(c) = \frac{1}{n} \sum_{k=1}^{c} \sum_{i=1}^{n} \mu_{ik}^2
\] Indeks Modified Partition Coefficient
(MPC)
Indeks Modified Partition Coefficient (MPC) merupakan modifikasi dari
indeks Partition Coefficient (PC) yang mampu mengurangi perubahan yang
monoton pada PC sehingga dengan diketahuinya indeks MPC maka dapat
memvalidasi jumlah cluster yang tepat. Jumlah cluster optimal diperoleh
dengan melihat nilai indeks terbesar. \[
MPC(c) = 1 - \frac{c}{c - 1} (1 - PC(c))
\]
# VALIDASI CLUSTER (MENCARI K DAN M TERBAIK)
eval_results <- data.frame()
data_mat <- as.matrix(data_norm)
n_data <- nrow(data_mat)
# Uji coba k dari 2 sampai 5, dengan m=2
for (k in 2:5) {
for (m in c(2.0)) {
# 1. Jalankan FCM
fcm_eval <- cmeans(x = data_mat, centers = k, iter.max = 100, m = m)
u_matrix <- fcm_eval$membership
centroid_mat <- fcm_eval$centers
# 2. Menghitung Indeks Validasi
# A. Partition Coefficient (PC) -> Maximize (Mendekati 1 lebih baik)
pc_val <- sum(u_matrix^2) / n_data
# B. Modified Partition Coefficient (MPC) -> Maximize (Mendekati 1 lebih baik)
mpc_val <- 1 - (k / (k - 1)) * (1 - pc_val)
# C. Xie-Beni Index (XB) -> Minimize (Mendekati 0 lebih baik)
# Hitung Pembilang
d2 <- matrix(0, nrow = n_data, ncol = k)
for(j in 1:k) {
diff_mat <- sweep(data_mat, 2, centroid_mat[j, ], "-")
d2[, j] <- rowSums(diff_mat^2)
}
xb_pembilang <- sum((u_matrix^m) * d2)
# Hitung Penyebut
dist_centers <- dist(centroid_mat)^2
xb_penyebut <- n_data * min(dist_centers)
# Nilai XB Akhir
xb_val <- xb_pembilang / xb_penyebut
eval_results <- rbind(eval_results, data.frame(
k = k,
m = m,
PC = pc_val,
MPC = mpc_val,
XB = xb_val
))
}
}
print(eval_results)## k m PC MPC XB
## 1 2 2 0.6810641 0.3621281 0.3182154
## 2 3 2 0.6589375 0.4884063 0.1979698
## 3 4 2 0.5520757 0.4027676 0.4439099
## 4 5 2 0.5119772 0.3899715 0.3828487
Keterangan:
Penentuan k dan m fuzzier terbaik dilakukan dengan melakukan algoritma
Fuzzy C-Means Clustering secara berulang untuk beberapa nilai k dan m
untuk mendapat hasil yang optimal. Cluster yang diuji (k) adalah
k=2,3,4,5 serta m yang diuji hanya m=2 (sesuai standar literatur). Untuk
memilih k terbaik digunakan validasi cluster dengan beberapa
indeks,seperti Xie-Beni (XB), Partition Coefficient (PC), dan Modified
Partition Coefficient (MPC). Kriteria memilih k terbaik sebagai
berikut:
1. Nilai terbesar dari PC (semakin mendekati 1 semakin baik)
2. Nilai terbesar dari MPC (semakin mendekati 1 semakin baik)
3. Nilai terkecil dari XB (semakin mendekati 0 semakin baik)
Berdasarkan output validasi cluster, jumlah k-cluster terbaik adalah k=3 dengan nilai PC kedua tertinggi (0.6589), nilai MPC tertinggi (0.4884), dan nilai XB terendah (0.1979). Maka dari itu diperoleh k dan m-fuzzier paling optimal yaitu k=3 dan m=2 untuk analisis selanjutnya.
Fuzzy C-Means (FCM) adalah algoritma clustering yang memungkinkan suatu data memiliki tingkat keanggotaan pada beberapa cluster sekaligus. Tingkat keanggotaan ini menunjukkan seberapa kuat hubungan data tersebut dengan setiap cluster, dengan nilai antara 0 dan 1. Dalam FCM, setiap data tidak hanya dimiliki oleh satu cluster, melainkan dapat menjadi bagian dari beberapa cluster dengan nilai keanggotaan yang berbeda. Jika jumlah cluster yang ditentukan adalah c, maka setiap data akan memiliki c nilai keanggotaan. Algoritma Fuzzy C-Means Clustering sebagai berikut:
Memasukkan data yang akan dicluster ke dalam sebuah matriks \(X\) berukuran \(n \times m\), dengan \(n\) adalah banyaknya data yang akan dicluster dan \(m\) adalah variabel setiap data. \(X_{ij}\) = data ke-\(i\) (\(i=1,2,\dots,n\)), variabel ke-\(j\) (\(j=1,2,\dots,m\)). \[ X = \begin{bmatrix} x_{11} & x_{12} & \dots & x_{1m} \\ x_{21} & x_{22} & \dots & x_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \dots & x_{nm} \end{bmatrix} \]
Menentukan beberapa parameter awal, sebagai berikut:
Membangkitkan bilangan acak \(\mu_{ik}\) dengan \(i\) (\(i=1,2,\dots,n\)) merupakan banyak data dan
\(k\) (\(k=1,2,\dots,c\)) merupakan banyak cluster
sebagai elemen-elemen matriks partisi awal \(\mathbf{U}\). \[
U^{(0)} = \begin{bmatrix}
\mu_{11} & \mu_{12} & \dots & \mu_{1c} \\
\mu_{21} & \mu_{22} & \dots & \mu_{2c} \\
\vdots & \vdots & \dots & \vdots \\
\mu_{n1} & \mu_{n2} & \dots & \mu_{nc}
\end{bmatrix}
\] Dengan syarat:
\[\mu_{ik} \in [0,1]; (1 \leq i \leq n; 1
\leq k \leq c)\] \[\sum_{k=1}^{c}
\mu_{ik} = 1 ; 1 \leq i \leq n\]
Menghitung pusat cluster ke-k : \(V_{kj}\), dengan k=1,2,…c dan j=1,2,…m \[ V_{kj} = \frac{\sum_{i=1}^{n} (\mu_{ik})^w * X_{ij}}{\sum_{i=1}^{n} (\mu_{ik})^w} \]
Menghitung fungsi objektif pada iterasi ke-t, \(P_t\): \[ P_t = \sum_{i=1}^{n} \sum_{k=1}^{c} \left( {\mu_{ik}}^w {d_{ik}}^2(X_{ij}, V_{kj}) \right) \] dengan \({d_{ik}}^2(X_{ij}, V_{kj})\) adalah jarak Euclidean antara data ke-i dengan pusat cluster ke k, sehingga diperoleh sebagai berikut: \[ P_t = \sum_{i=1}^{n} \sum_{k=1}^{c} \left( {\mu_{ik}}^w \left[ \sum_{j=1}^{m} (X_{ij} - V_{kj})^2 \right] \right) \]
Menghitung perubahan derajat keanggotaan setiap data pada setiap cluster (memperbaiki matriks partisi (\(\mathbf{U}\)) dengan: \[ \mu_{ik} = \frac{\left[ \sum_{j=1}^{m} (X_{ij} - V_{kj})^2 \right]^{\frac{-1}{w-1}}}{\sum_{k=1}^{c} \left[ \sum_{j=1}^{m} (X_{ij} - V_{kj})^2 \right]^{\frac{-1}{w-1}}} \] dengan : \(i=1,2,\dots,n\) dan \(k=1,2,\dots,c\).
Menyelidiki kondisi berhenti
## RLS IPLM TKM
## Cluster 1 0.2717651 0.3667846 0.6852225
## Cluster 2 0.1777694 0.3295329 0.1508963
## Cluster 3 0.8798557 0.8564067 0.5682306
# Membuat tabel gabungan agar nama Kabupaten/Kota terlihat jelas
hasil_akhir <- data.frame(
Kabupaten_Kota = rownames(data_norm),
Jarak_C1 = fcm_result$d[, 1],
Jarak_C2 = fcm_result$d[, 2],
Jarak_C3 = fcm_result$d[, 3],
Keanggotaan_C1 = fcm_result$u[, 1],
Keanggotaan_C2 = fcm_result$u[, 2],
Keanggotaan_C3 = fcm_result$u[, 3],
Cluster_Akhir = fcm_result$cluster
)
rownames(hasil_akhir) <- NULLKeterangan:
Output di atas menunjukkan centroid (rata-rata) tiap cluster secara
multivariat yang masih dalam bentuk data hasil transformasi normalisasi
min max.
# 2. Jarak anggota kluster terhadap masing-masing centroid
print(hasil_akhir[, c("Kabupaten_Kota", "Jarak_C1", "Jarak_C2","Jarak_C3")])## Kabupaten_Kota Jarak_C1 Jarak_C2 Jarak_C3
## 1 Cilacap 0.214494257 0.01032729 0.91518246
## 2 Banyumas 0.272598134 0.01229489 0.75591286
## 3 Purbalingga 0.495573490 0.04088762 1.04429907
## 4 Banjarnegara 0.552632396 0.07940133 1.18257169
## 5 Kebumen 0.076458373 0.51569022 0.52424159
## 6 Purworejo 0.222970447 0.15385224 0.35176719
## 7 Wonosobo 0.088626639 0.34699712 0.84226747
## 8 Magelang 0.088205447 0.34857385 1.04593138
## 9 Boyolali 0.405842216 0.02697033 0.88165425
## 10 Klaten 0.081478460 0.42136177 0.39189192
## 11 Sukoharjo 0.352189537 0.36929411 0.17697606
## 12 Wonogiri 0.137946048 0.39200209 1.20560009
## 13 Karanganyar 0.678022032 0.26644606 1.16000370
## 14 Sragen 0.360255410 0.03737357 0.74624971
## 15 Grobogan 0.348219840 0.12275836 1.42167006
## 16 Blora 0.406680117 0.04927842 0.93062731
## 17 Rembang 0.025818204 0.15876071 0.74595436
## 18 Pati 0.012246914 0.39164106 0.64325522
## 19 Kudus 0.130432157 0.58726714 0.22932486
## 20 Jepara 0.009545637 0.31144068 0.63936096
## 21 Demak 0.023882288 0.17848227 0.55011767
## 22 Semarang 0.099234032 0.12902301 0.45762321
## 23 Temanggung 0.213352430 0.01177198 0.95034279
## 24 Kendal 0.100428888 0.71859671 0.84688502
## 25 Batang 0.083967181 0.12277809 0.90168938
## 26 Pekalongan 0.113169534 0.72508462 0.92937296
## 27 Pemalang 0.595767212 0.14795063 1.76301442
## 28 Tegal 0.389742784 0.02432857 1.22491012
## 29 Brebes 0.391989821 0.04105175 1.34819485
## 30 Kota Magelang 1.030372662 1.84656636 0.22147849
## 31 Kota Surakarta 0.986757666 1.17405270 0.05598545
## 32 Kota Salatiga 0.951857076 1.27839707 0.03575212
## 33 Kota Semarang 0.621521389 0.74087967 0.08277436
## 34 Kota Pekalongan 0.383286765 0.89972069 0.15524656
## 35 Kota Tegal 0.208258106 0.17477587 0.38595504
Keterangan:
Output di atas menunjukkan jarak antara setiap titik data dengan
centroid tiap klaster. Jarak yang digunakan adalah jarak Euclidean
dengan rumus:
\[
d(x_i, x_k) = \sqrt{\sum_{j=1}^{m} (x_{ij} - x_{kj})^2}
\]
# 3. Nilai Derajat Keanggotaan
print(hasil_akhir[, c("Kabupaten_Kota", "Keanggotaan_C1", "Keanggotaan_C2","Keanggotaan_C3")])## Kabupaten_Kota Keanggotaan_C1 Keanggotaan_C2 Keanggotaan_C3
## 1 Cilacap 0.04544624 0.94390238 0.01065138
## 2 Banyumas 0.04249482 0.94218065 0.01532453
## 3 Purbalingga 0.07355682 0.89153669 0.03490649
## 4 Banjarnegara 0.11866192 0.82588570 0.05545238
## 5 Kebumen 0.77273194 0.11456845 0.11269962
## 6 Purworejo 0.32434797 0.47006148 0.20559055
## 7 Wonosobo 0.73495141 0.18771416 0.07733443
## 8 Magelang 0.74773141 0.18921093 0.06305766
## 9 Boyolali 0.06057651 0.91153898 0.02788452
## 10 Klaten 0.71363330 0.13799482 0.14837188
## 11 Sukoharjo 0.25356746 0.24182299 0.50460954
## 12 Wonogiri 0.68197827 0.23998905 0.07803268
## 13 Karanganyar 0.24217838 0.61626838 0.14155324
## 14 Sragen 0.08991136 0.86668352 0.04340512
## 15 Grobogan 0.24500403 0.69498537 0.06001059
## 16 Blora 0.10320239 0.85169861 0.04509900
## 17 Rembang 0.83525835 0.13583254 0.02890910
## 18 Pati 0.95210010 0.02977289 0.01812700
## 19 Kudus 0.55838904 0.12401832 0.31759264
## 20 Jepara 0.95640706 0.02931382 0.01427912
## 21 Demak 0.84945841 0.11366401 0.03687758
## 22 Semarang 0.50353342 0.38727707 0.10918950
## 23 Temanggung 0.05168426 0.93671260 0.01160314
## 24 Kendal 0.79469578 0.11106426 0.09423996
## 25 Batang 0.56274116 0.38485522 0.05240362
## 26 Pekalongan 0.78256602 0.12214110 0.09529289
## 27 Pemalang 0.18640292 0.75060681 0.06299027
## 28 Tegal 0.05767630 0.92397222 0.01835149
## 29 Brebes 0.09225580 0.88092068 0.02682352
## 30 Kota Magelang 0.16102435 0.08985060 0.74912505
## 31 Kota Surakarta 0.05137235 0.04317699 0.90545066
## 32 Kota Salatiga 0.03525053 0.02624651 0.93850295
## 33 Kota Semarang 0.10698026 0.08974537 0.80327436
## 34 Kota Pekalongan 0.25674620 0.10937552 0.63387827
## 35 Kota Tegal 0.36614425 0.43628739 0.19756837
Keterangan:
Output di atas menunjukkan tingkat keanggotaan tiap titik data untuk
masuk ke dalam suatu cluster. Fuzzy C-Means memungkinkan suatu data
memiliki tingkat keanggotaan pada beberapa cluster sekaligus sehingga
satu data bisa menjadi bagian dari beberapa cluster. Tingkat keanggotaan
menunjukkan kuat hubungan data dengan setiap cluster.
# 4. Label Kluster yang menjadi keanggotaan akhir
print(hasil_akhir[, c("Kabupaten_Kota", "Cluster_Akhir")])## Kabupaten_Kota Cluster_Akhir
## 1 Cilacap 2
## 2 Banyumas 2
## 3 Purbalingga 2
## 4 Banjarnegara 2
## 5 Kebumen 1
## 6 Purworejo 2
## 7 Wonosobo 1
## 8 Magelang 1
## 9 Boyolali 2
## 10 Klaten 1
## 11 Sukoharjo 3
## 12 Wonogiri 1
## 13 Karanganyar 2
## 14 Sragen 2
## 15 Grobogan 2
## 16 Blora 2
## 17 Rembang 1
## 18 Pati 1
## 19 Kudus 1
## 20 Jepara 1
## 21 Demak 1
## 22 Semarang 1
## 23 Temanggung 2
## 24 Kendal 1
## 25 Batang 1
## 26 Pekalongan 1
## 27 Pemalang 2
## 28 Tegal 2
## 29 Brebes 2
## 30 Kota Magelang 3
## 31 Kota Surakarta 3
## 32 Kota Salatiga 3
## 33 Kota Semarang 3
## 34 Kota Pekalongan 3
## 35 Kota Tegal 2
Keterangan:
Output di atas menunjukkan pengelompokkan tiap data ke dalam suatu
cluster. Pengelompokkan didasarkan jarak terdekat dengan suatu cluster
dan derajat keanggotaan tertinggi dengan suatu cluster.
# profilisasi kluster
data_final <- cbind(data_num, Cluster = fcm_result$cluster)
profil_cluster <- data_final %>%
group_by(Cluster) %>%
summarise(
Rata_RLS = mean(RLS),
Rata_IPLM = mean(IPLM),
Rata_TKM = mean(TKM),
Jumlah_KabKota = n()
)
print(profil_cluster)## # A tibble: 3 × 5
## Cluster Rata_RLS Rata_IPLM Rata_TKM Jumlah_KabKota
## <int> <dbl> <dbl> <dbl> <int>
## 1 1 7.96 65.6 78.4 14
## 2 2 7.72 62.8 66.8 15
## 3 3 10.7 91.7 76.0 6
Keterangan:
Output di atas menunjukkan informasi mengenai rata-rata akhir tiap
cluster (sudah didenormalisasi). Karakteristik setiap cluster sebagai
berikut:
Cluster 1
Cluster 1 memiliki rata-rata RLS dan IPLM menengah walaupun nilainya
tidak terlalu jauh dengan cluster 2 (RLS dan IPLM terendah). Akan
tetapi, cluster 1 memiliki rata-rata TKM tertinggi. Cluster 1 terdiri
atas 14 wilayah, yaitu Kebumen, Wonosobo, Magelang, Klaten, Wonogiri,
Rembang, Pati, Kudus, Jepara, Demak, Semarang, Kendal, Batang, dan
Pekalongan.
Cluster 2
Cluster 2 memiliki rata-rata RLS, IPLM, dan TKM paling rendah. Cluster 2
terdiri atas 15 wilayah, yaitu Cilacap, Banyumas, Purbalingga,
Banjarnegara, Purworejo, Boyolali, Karanganyar, Sragen, Grobogan, Blora,
Temanggung, Pemalang, Tegal, Brebes, dan Kota Tegal.
Cluster 3
Cluster 3 memiliki rata-rata RLS, IPLM tertinggi. Akan tetapi, rata-rata
TKM menengah walaupun nilainya tidak terlalu jauh dengan cluster 1 (TKM
tertinggi). Cluster 3 terdiri atas 6 wilayah, yaitu Sukoharjo, Kota
Magelang, Kota Surakarta, Kota Salatiga, Kota Semarang, dan Kota
Pekalongan.
# visualisasi
fcm_kmeans <- list(cluster = fcm_result$cluster)
class(fcm_kmeans) <- "kmeans"
plot_cluster <- fviz_cluster(fcm_kmeans,
data = data_norm,
geom = c("point", "text"),
ellipse.type = "convex",
palette = "aaas",
repel = TRUE,
main = "Visualisasi Fuzzy C-Means Clustering Jawa Tengah")
print(plot_cluster)
Keterangan:
Output di atas menunjukkan visualisasi koordinat tiap titik data dengan
centroid sehingga membentuk cluster-cluster dalam format 2 dimensi.
# A. Mengunduh data spasial peta Indonesia dari GADM (Otomatis)
indo_map <- gadm(country = "IDN", level = 2, path = getwd())
# B. Mengubah format ke 'sf' agar bisa dibaca oleh ggplot dan memfilter Jawa Tengah
indo_sf <- st_as_sf(indo_map)
jateng_sf <- indo_sf %>% filter(NAME_1 == "Jawa Tengah")
# C. Menyiapkan data hasil kluster dari langkah sebelumnya
df_peta <- data.frame(
Nama_Daerah = rownames(data_norm),
Cluster = as.factor(fcm_result$cluster)
)
df_peta <- df_peta %>%
mutate(Nama_Daerah = case_when(
Nama_Daerah == "Kota Surakarta" ~ "Surakarta",
Nama_Daerah == "Kota Salatiga" ~ "Salatiga",
TRUE ~ Nama_Daerah
))
# D. Menggabungkan (Join) data peta dengan data hasil kluster Anda
peta_cluster <- left_join(jateng_sf, df_peta, by = c("NAME_2" = "Nama_Daerah"))
# E. Membuat Plot Peta
plot_peta_jateng <- ggplot(data = peta_cluster) +
geom_sf(aes(fill = Cluster), color = "white", size = 0.3) +
scale_fill_manual(values = c("1" = "#5DADE2", "2" = "#F5B041", "3" = "#48C9B0"),
na.value = "grey90", name = "Kluster") +
theme_minimal() +
labs(title = "Peta Persebaran Cluster Pendidikan di Jawa Tengah",
subtitle = "Berdasarkan RLS, IPLM, dan TKM menggunakan Fuzzy C-Means",
caption = "Sumber data: BPS Jawa Tengah") +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
plot.subtitle = element_text(size = 11, hjust = 0.5),
legend.position = "bottom",
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank()
)
print(plot_peta_jateng)