Penelitian ini bertujuan untuk mengelompokkan kecamatan di Kota Semarang berdasarkan jumlah penduduk penyandang disabilitas pada tahun 2024 dengan menggunakan metode Principal Component Analysis (PCA) dan K-Means Clustering.
Pengelompokan kecamatan dilakukan untuk mengidentifikasi pola distribusi penyandang disabilitas dan karakteristik wilayah, sehingga hasilnya dapat digunakan sebagai dasar perumusan kebijakan sosial dan perencanaan pembangunan yang inklusif.
Analisis dilakukan melalui beberapa tahapan, yaitu statistik deskriptif, deteksi outlier, uji asumsi multikolinearitas dan kelayakan data untuk PCA, ekstraksi komponen utama, penentuan jumlah klaster, pengelompokan dengan K-Means, evaluasi kualitas klaster, serta pemetaan spasial hasil klaster.
library(psych) #untuk analisis statistik deskriptif tambahan
library(car) #untuk analisis regresi dan VIF
library(readxl) #untuk membaca file excel
library(tidyverse) #untuk manipulasi dan visualisasi data
library(factoextra)#untuk visualisasi clustering & PCA
library(cluster) #untuk menghitung silhouette
library(writexl) #untuk menyimpan hasil ke Excel
library(plotly) #untuk visualisasi 3D interaktif
#membaca file Excel ke dalam R
data_pkl1 <- read_excel("C:\\Users\\ASUS\\OneDrive\\Gambar\\Dokumen\\PKL\\Disabilitas.xlsx")
head(data_pkl1) #melihat 6 baris pertama data
## # A tibble: 6 × 7
## Kecamatan DISABILITAS_FISIK DISABILITAS_NETRA DISABILITAS_WICARA
## <chr> <dbl> <dbl> <dbl>
## 1 Semarang Tengah 10 6 31
## 2 Semarang Utara 16 4 36
## 3 Semarang Timur 22 8 40
## 4 Gayamsari 12 10 19
## 5 Genuk 13 6 26
## 6 Pedurungan 3 2 4
## # ℹ 3 more variables: DISABILITAS_MENTAL <dbl>, DISABILITAS_LAINNYA <dbl>,
## # DISABILITAS_FISIK_DAN_MENTAL <dbl>
View(data_pkl1) #membuka data dalam jendela viewer
Data yang digunakan merupakan data jumlah penyandang disabilitas per kecamatan di Kota Semarang tahun 2024 dengan enam variabel, yaitu: 1. Disabilitas fisik 2. Disabilitas netra 3. Disabilitas wicara 4. Disabilitas mental 5. Disabilitas lainnya, dan 6. Disabilitas fisik dan mental Setiap baris merepresentasikan satu kecamatan sebagai unit observasi.
#statistika deskriptif
descriptive_stats <- function(df){ #membuat fungsi statistik deskriptif
data.frame(
Min = sapply(df, min, na.rm = TRUE), #nilai minimum tiap variabel
Max = sapply(df, max, na.rm = TRUE), #nilai maksimum
Mean = sapply(df, mean, na.rm = TRUE), #rata-ratas
SD = sapply(df, sd, na.rm = TRUE), #standar deviasi
Sum = sapply(df, sum, na.rm = TRUE), #total jumlah
N = sapply(df, function(x) sum(!is.na(x))) #jumlah data valid
) |> round(2) #membulatkan 2 angka desimal
}
data1 <- data_pkl1[, c(2:7)] #mengambil kolom numerik (tanpa kecamatan)
descriptive_stats(data1) #menampilkan hasil statistik deskriptif
## Min Max Mean SD Sum N
## DISABILITAS_FISIK 0 22 5.88 6.66 94 16
## DISABILITAS_NETRA 0 10 2.50 3.33 40 16
## DISABILITAS_WICARA 1 40 11.38 14.02 182 16
## DISABILITAS_MENTAL 0 70 23.56 23.89 377 16
## DISABILITAS_LAINNYA 0 28 7.94 8.88 127 16
## DISABILITAS_FISIK_DAN_MENTAL 0 3 0.62 0.89 10 16
Statistik deskriptif digunakan untuk memberikan gambaran umum karakteristik data jumlah penyandang disabilitas di setiap kecamatan.
Hasil analisis menunjukkan bahwa variabel disabilitas mental memiliki rata-rata tertinggi dibandingkan jenis disabilitas lainnya, yaitu sebesar 23,56 dengan nilai maksimum mencapai 70. Hal ini mengindikasikan bahwa jumlah penyandang disabilitas mental relatif lebih besar dan bervariasi antar kecamatan.
Sementara itu, variabel disabilitas fisik dan mental memiliki nilai rata-rata paling kecil (0,62), yang menunjukkan bahwa kategori ini jarang ditemukan dibandingkan kategori disabilitas lainnya. Nilai standar deviasi yang cukup besar pada beberapa variabel, seperti disabilitas mental dan disabilitas wicara, menunjukkan adanya variasi data yang cukup tinggi antar kecamatan di Kota Semarang.
#Ubah "Kecamatan" menjadi row names
data_fix <- data_pkl1 %>%
column_to_rownames(var = "Kecamatan")
#mengubah kolom kecamatan menjadi nama baris
print(data_fix) #menampilkan data
## DISABILITAS_FISIK DISABILITAS_NETRA DISABILITAS_WICARA
## Semarang Tengah 10 6 31
## Semarang Utara 16 4 36
## Semarang Timur 22 8 40
## Gayamsari 12 10 19
## Genuk 13 6 26
## Pedurungan 3 2 4
## Semarang Selatan 0 0 2
## Candisari 1 0 1
## Gajahmungkur 1 0 1
## Tembalang 4 3 3
## Banyumanik 2 0 1
## Gunungpati 0 0 2
## Semarang Barat 5 0 3
## Mijen 2 0 4
## Ngaliyan 2 0 8
## Tugu 1 1 1
## DISABILITAS_MENTAL DISABILITAS_LAINNYA
## Semarang Tengah 36 17
## Semarang Utara 50 28
## Semarang Timur 45 16
## Gayamsari 36 13
## Genuk 61 23
## Pedurungan 37 9
## Semarang Selatan 3 2
## Candisari 12 4
## Gajahmungkur 5 0
## Tembalang 3 3
## Banyumanik 4 1
## Gunungpati 3 0
## Semarang Barat 11 4
## Mijen 1 0
## Ngaliyan 70 6
## Tugu 0 1
## DISABILITAS_FISIK_DAN_MENTAL
## Semarang Tengah 1
## Semarang Utara 1
## Semarang Timur 3
## Gayamsari 1
## Genuk 1
## Pedurungan 2
## Semarang Selatan 0
## Candisari 0
## Gajahmungkur 0
## Tembalang 0
## Banyumanik 0
## Gunungpati 0
## Semarang Barat 0
## Mijen 0
## Ngaliyan 1
## Tugu 0
View(data_fix) #membuka viewer
Deteksi outlier dilakukan menggunakan jarak Mahalanobis yang didefinisikan sebagai:
\[ \ D_i^2 = (x_i - \mu)' \Sigma^{-1} (x_i - \mu) \ \]
dengan \(\ x_i\ \) adalah vektor observasi ke-i, \(\mu\ \) adalah vektor rata-rata, dan \(\ Sigma\ \) adalah matriks kovarians.
Observasi dikategorikan sebagai outlier apabila nilai jarak Mahalanobis melebihi nilai kritis distribusi Chi-Square dengan derajat bebas sebesar jumlah variabel dan tingkat signifikansi 97,5%.
#Hitung mean dan matriks kovarians
mean_vector <- colMeans(data_fix, na.rm = TRUE)
#menghitung rata-rata tiap variabel
cov_matrix <- cov(data_fix, use = "complete.obs")
#menghitung matriks kovarians
#menhitung jarak Mahalanobis tiap observasi
mahalanobis_dist <- mahalanobis(data_fix, mean_vector, cov_matrix)
#Menentukan bata outlier berdasarkan distribusi Chi-Square 97.5%
threshold <- qchisq(0.975, df = ncol(data_fix))
#menandai data yang termasuk outlier
data_pkl1$outlier <- mahalanobis_dist > threshold
#menampilkan hanya data yang terdeteksi outlier
outlier <- data_pkl1[data_pkl1$outlier == TRUE,]
print(outlier)
## # A tibble: 0 × 8
## # ℹ 8 variables: Kecamatan <chr>, DISABILITAS_FISIK <dbl>,
## # DISABILITAS_NETRA <dbl>, DISABILITAS_WICARA <dbl>,
## # DISABILITAS_MENTAL <dbl>, DISABILITAS_LAINNYA <dbl>,
## # DISABILITAS_FISIK_DAN_MENTAL <dbl>, outlier <lgl>
#menimpan nilai jarak Mahalanobis ke dataset
data_pkl1$mahalanobis_dist <- mahalanobis_dist
Hasil perhitungan menunjukkan bahwa tidak terdapat kecamatan yang terdeteksi sebagai outlier multivariat. Hal ini berarti seluruh kecamatan memiliki pola jumlah penyandang disabilitas yang masih berada dalam rentang variasi normal secara multivariat.
#visualisasi outlier
data_pkl1$observasi <- rownames(data_fix)
ggplot(data_pkl1, aes(x = mahalanobis_dist, y = observasi, colour = outlier)) +
geom_point() + #membuat scatter plot
labs(title = "Deteksi Outlier dengan Mahalanobis Distance",
x = "Jarak Mahalanobis",
y = "Observasi") +
theme_minimal()
Visualisasi jarak Mahalanobis juga menunjukkan bahwa seluruh observasi berada di bawah batas ambang yang ditentukan, sehingga seluruh data dapat digunakan pada tahap analisis selanjutnya.
Multikolinearitas diuji menggunakan Variance Inflation Factor (VIF) dengan rumus:
\[ \ VIF_j = \frac{1}{1 - R_j^2} \ \]
di mana \(\ R_j^2\ \) adalah koefisien determinasi hasil regresi variabel ke-j terhadap variabel lainnya. Nilai VIF di atas 10 menunjukkan adanya multikolinearitas yang kuat.
#uji non-multikolinearitas
hitung_vif <- function(data){
vif_values <- sapply(names(data), function(var){
formula <- as.formula(paste(var, "~ .")) #membuat model regresi
model <- lm(formula, data = data) # regresi linear
R2 <- summary(model)$r.squared #ambil nilai R^2
vif_value <- 1 / (1 - R2) #rumus VIF manual
return(vif_value)
})
data.frame(
variabel = names(vif_values),
VIF = vif_values,
row.names = NULL
)
}
vif_result <- hitung_vif(data_fix) #jalankan fungsi VIF
print(vif_result)
## variabel VIF
## 1 DISABILITAS_FISIK 15.339289
## 2 DISABILITAS_NETRA 3.592994
## 3 DISABILITAS_WICARA 15.528227
## 4 DISABILITAS_MENTAL 4.108175
## 5 DISABILITAS_LAINNYA 8.894194
## 6 DISABILITAS_FISIK_DAN_MENTAL 3.692837
Hasil perhitungan VIF menunjukkan bahwa variabel disabilitas fisik dan disabilitas wicara memiliki nilai VIF di atas 10, yang mengindikasikan adanya multikolinearitas yang cukup kuat. Hal ini wajar karena jenis disabilitas tertentu cenderung memiliki keterkaitan satu sama lain.
Oleh karena itu, agar analisis tetap bisa dilanjutkan, dilakukanlah Principal Component Analysis (PCA) yang mampu menangani korelasi antar variabel, sehingga multikolinearitas ini tidak menjadi masalah yang signifikan dan hasil nya tetap valid dan reliabel.
PCA digunakan untuk mereduksi dimensi data dengan membentuk komponen utama sebagai kombinasi linear variabel asli. Secara matematis, komponen utama ke-k dapat dituliskan sebagai:
\[ \ PC_k = a_{1k}X_1 + a_{2k}X_2 + \cdots + a_{pk}X_p \ \]
dengan $ a_{jk} $ adalah loading variabel ke-j pada komponen ke-k.
#principal componen analysis
data_scaled_pca <- scale(data_fix)
#standarisasi data (mean=0, sd=1)
pca_result <- prcomp(data_scaled_pca,
center = TRUE,
scale. = TRUE)
#melakukan PCA
summary(pca_result) #ringkasan hasil PCA
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 2.178 0.74066 0.63092 0.45228 0.25501 0.19483
## Proportion of Variance 0.791 0.09143 0.06634 0.03409 0.01084 0.00633
## Cumulative Proportion 0.791 0.88240 0.94874 0.98283 0.99367 1.00000
eigenvalues <- pca_result$sdev^2 #menghitung eigenvalue
prop_var <- eigenvalues / sum(eigenvalues) #proporsi varians
cum_var <- cumsum(prop_var) #varians kumulatif
print(eigenvalues)
## [1] 4.74581909 0.54857139 0.39805865 0.20455973 0.06503241 0.03795873
print(prop_var)
## [1] 0.790969848 0.091428565 0.066343108 0.034093289 0.010838734 0.006326456
print(cum_var)
## [1] 0.7909698 0.8823984 0.9487415 0.9828348 0.9936735 1.0000000
Hasil PCA menunjukkan bahwa komponen utama pertama (PC1) memiliki eigenvalue sebesar 4,75 dan menjelaskan sekitar 79,1% variasi data. Jika digabungkan dengan PC2, proporsi varians kumulatif mencapai 88,2%, dan dengan tiga komponen mencapai 94,87%.
Hal ini menunjukkan bahwa sebagian besar informasi data dapat direpresentasikan hanya dengan beberapa komponen utama, sehingga PCA berhasil mereduksi dimensi data secara signifikan.
fviz_eig(pca_result) #scree plot
Scree plot menunjukkan adanya penurunan tajam pada eigenvalue setelah komponen pertama, kemudian cenderung melandai pada komponen berikutnya. Berdasarkan kriteria elbow dan proporsi varians kumulatif, empat komponen utama dipilih untuk analisis klaster karena telah menjelaskan lebih dari 98% variasi data.
loadings <- pca_result$rotation #kontribusi variabel
print(loadings)
## PC1 PC2 PC3 PC4
## DISABILITAS_FISIK -0.4355966 0.30675607 0.02778775 0.31450733
## DISABILITAS_NETRA -0.3941960 0.49057618 0.22074306 -0.73475182
## DISABILITAS_WICARA -0.4388396 0.18199709 -0.18389147 0.37556452
## DISABILITAS_MENTAL -0.3717492 -0.72330923 -0.20699586 -0.38759278
## DISABILITAS_LAINNYA -0.4221665 -0.02944553 -0.54708201 0.08629775
## DISABILITAS_FISIK_DAN_MENTAL -0.3819199 -0.32873926 0.75798302 0.25000147
## PC5 PC6
## DISABILITAS_FISIK -0.38173912 0.68610823
## DISABILITAS_NETRA 0.06374982 -0.10626747
## DISABILITAS_WICARA -0.32224563 -0.70398139
## DISABILITAS_MENTAL -0.37607337 0.06418463
## DISABILITAS_LAINNYA 0.70677255 0.12097496
## DISABILITAS_FISIK_DAN_MENTAL 0.32466958 -0.06015252
pca_scores <- as.data.frame(pca_result$x) #skor PCA
head(pca_scores)
## PC1 PC2 PC3 PC4 PC5
## Semarang Tengah -2.0848013 0.4148045472 -0.3528236 -0.06054182 0.04273472
## Semarang Utara -3.1374033 0.0006083401 -1.3250578 0.67807101 0.20074522
## Semarang Timur -4.3436217 0.3670014970 1.4083679 0.71443632 -0.30098086
## Gayamsari -2.1238729 0.9542906321 0.3247228 -1.20984643 -0.03780857
## Genuk -2.7988094 -0.2888971924 -0.8610266 -0.40019176 0.06963891
## Pedurungan -0.3749634 -1.2229841659 1.0472114 -0.04213654 0.70201809
## PC6
## Semarang Tengah -0.54079211
## Semarang Utara 0.07748139
## Semarang Timur 0.05398660
## Gayamsari 0.08532936
## Genuk 0.16808956
## Pedurungan 0.04725000
#mengambil 4 komponen utama pertama
data_pca_final <- pca_scores[, 1:4]
summary(data_pca_final)
## PC1 PC2 PC3 PC4
## Min. :-4.344 Min. :-2.12998 Min. :-1.32506 Min. :-1.20985
## 1st Qu.:-2.095 1st Qu.:-0.03266 1st Qu.:-0.24288 1st Qu.:-0.12393
## Median : 1.209 Median : 0.11697 Median : 0.03979 Median : 0.05434
## Mean : 0.000 Mean : 0.00000 Mean : 0.00000 Mean : 0.00000
## 3rd Qu.: 1.781 3rd Qu.: 0.37234 3rd Qu.: 0.08984 3rd Qu.: 0.19255
## Max. : 1.941 Max. : 0.95429 Max. : 1.40837 Max. : 0.71444
data_scaled <- as.data.frame(data_pca_final)
#dataset akhir untuk clustering
Nilai loading menunjukkan kontribusi masing-masing variabel terhadap komponen utama. Semua variabel memiliki kontribusi yang cukup besar terhadap PC1, yang menunjukkan bahwa PC1 merepresentasikan pola umum jumlah penyandang disabilitas di setiap kecamatan.
Komponen lainnya merepresentasikan variasi spesifik antar jenis disabilitas, seperti kombinasi disabilitas fisik dan mental serta disabilitas lainnya.
#menentukan jumlah klaster
fviz_nbclust(data_scaled, kmeans, method = "wss") #elbow method
fviz_nbclust(data_scaled, kmeans, method = "silhouette") #silhouette method
Metode elbow dan silhouette digunakan untuk menentukan jumlah klaster optimal. Kedua metode menunjukkan bahwa jumlah klaster optimal berada pada k = 3, sehingga analisis K-Means dilakukan dengan tiga klaster.
Metode K-Means bertujuan meminimalkan fungsi objektif:
\[ \ \sum_{k=1}^{K} \sum_{i \in C_k} \|x_i - \mu_k\|^2 \ \]
di mana \(\ C_k\ \) adalah klaster ke-k dan \(\ \mu_k\) adalah centroid klaster ke-k.
#K-Means Clustering
set.seed(123) #agar hasil random konsisten
kmeans_result <- kmeans(data_scaled, centers = 3, nstart = 100) #menjalankan K-Means dengan 3 cluster
print(kmeans_result)
## K-means clustering with 3 clusters of sizes 2, 9, 5
##
## Cluster means:
## PC1 PC2 PC3 PC4
## 1 -0.2560955 -1.6764826 0.47375141 -0.21486492
## 2 1.6667444 0.2116842 -0.01574282 0.07864473
## 3 -2.8977017 0.2895616 -0.16116349 -0.05561454
##
## Clustering vector:
## Semarang Tengah Semarang Utara Semarang Timur Gayamsari
## 3 3 3 3
## Genuk Pedurungan Semarang Selatan Candisari
## 3 1 2 2
## Gajahmungkur Tembalang Banyumanik Gunungpati
## 2 2 2 2
## Semarang Barat Mijen Ngaliyan Tugu
## 2 2 1 2
##
## Within cluster sum of squares by cluster:
## [1] 1.156964 1.530955 11.462183
## (between_SS / total_SS = 84.0 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
#Hasil klaster per kecamatan
hasil_cluster <- data.frame(
Kecamatan = rownames(data_fix),
Cluster = kmeans_result$cluster
)
print(hasil_cluster)
## Kecamatan Cluster
## Semarang Tengah Semarang Tengah 3
## Semarang Utara Semarang Utara 3
## Semarang Timur Semarang Timur 3
## Gayamsari Gayamsari 3
## Genuk Genuk 3
## Pedurungan Pedurungan 1
## Semarang Selatan Semarang Selatan 2
## Candisari Candisari 2
## Gajahmungkur Gajahmungkur 2
## Tembalang Tembalang 2
## Banyumanik Banyumanik 2
## Gunungpati Gunungpati 2
## Semarang Barat Semarang Barat 2
## Mijen Mijen 2
## Ngaliyan Ngaliyan 1
## Tugu Tugu 2
View(hasil_cluster)
#Menambahkan hasil klaster ke data
data_scaled$cluster <- as.factor(kmeans_result$cluster)
Hasil K-Means dengan tiga klaster menunjukkan bahwa:
Proporsi variasi yang dijelaskan oleh perbedaan antar klaster mencapai 84%, yang menunjukkan bahwa pembentukan klaster cukup baik dalam membedakan karakteristik kecamatan.
#evaluasi silhouette
sil <- silhouette(kmeans_result$cluster, dist(data_scaled[, -ncol(data_scaled)]))
#menghitung silhouette tiap observasi
fviz_silhouette(sil)
## cluster size ave.sil.width
## 1 1 2 0.47
## 2 2 9 0.81
## 3 3 5 0.39
#visualisasi silhouette
Nilai rata-rata silhouette menunjukkan bahwa klaster 2 memiliki kualitas klaster terbaik dengan nilai 0,81, sedangkan klaster 1 dan klaster 3 memiliki nilai silhouette sedang. Secara keseluruhan, average nilai silhouette adalah 0.64. Hal ini menunjukkan bahwa struktur klaster cukup jelas dan valid.
#menyimpan hasil klaster
write_xlsx(
hasil_cluster,
path = "C:/Users/ASUS/OneDrive/Gambar/Dokumen/PKL/Hasil_Cluster_Kecamatan_Semarang.xlsx"
)
#menghitung centroid
centroids <- aggregate(
data_scaled[, -ncol(data_scaled)],
by = list(cluster = data_scaled$cluster),
FUN = mean
)
print(centroids)
## cluster PC1 PC2 PC3 PC4
## 1 1 -0.2560955 -1.6764826 0.47375141 -0.21486492
## 2 2 1.6667444 0.2116842 -0.01574282 0.07864473
## 3 3 -2.8977017 0.2895616 -0.16116349 -0.05561454
View(centroids)
Nilai centroid menunjukkan rata-rata skor komponen utama (PC1–PC4) pada masing-masing klaster. Karena data telah melalui proses standarisasi, maka nilai positif dapat diartikan sebagai posisi di atas rata-rata keseluruhan, sedangkan nilai negatif menunjukkan posisi di bawah rata-rata.
Agar interpretasinya lebih bermakna, nilai centroid perlu dikaitkan dengan hasil loading komponen utama. Loading membantu menjelaskan kecamatan mana yang paling berkontribusi pada setiap komponen.
Klaster 1 memiliki nilai negatif pada PC1 dan PC2, serta nilai positif yang cukup besar pada PC3.
Komponen pertama (PC1) banyak dipengaruhi oleh Kecamatan Semarang Timur dan Semarang Utara. Karena centroid klaster 1 bernilai negatif pada PC1, maka kecamatan dalam klaster ini cenderung tidak memiliki karakteristik dominan seperti yang ditunjukkan oleh kedua kecamatan tersebut pada dimensi utama.
Pada PC2, yang banyak dipengaruhi oleh Gayamsari, klaster 1 juga bernilai negatif. Hal ini menunjukkan bahwa pola pada klaster ini tidak searah dengan karakteristik yang kuat pada Gayamsari.
Namun demikian, klaster 1 memiliki nilai positif yang cukup tinggi pada PC3. Komponen ini dipengaruhi oleh Semarang Timur dan Pedurungan. Artinya, meskipun klaster 1 tidak menonjol pada variasi utama, klaster ini memiliki ciri tertentu yang lebih terlihat pada dimensi ketiga.
Klaster 2 memiliki nilai PC1 paling tinggi dan positif dibandingkan klaster lainnya. Karena PC1 merupakan komponen yang menjelaskan variasi terbesar dalam data dan banyak dipengaruhi oleh Semarang Timur serta Semarang Utara, maka klaster 2 dapat diartikan sebagai kelompok kecamatan yang paling mencerminkan pola utama jumlah penduduk disabilitas di Kota Semarang.
Nilai PC2 pada klaster ini juga positif, yang berarti cenderung searah dengan karakteristik Gayamsari. Secara umum, klaster 2 dapat dikatakan sebagai kelompok dengan karakteristik yang relatif lebih tinggi atau lebih dominan pada dimensi utama dibandingkan klaster lainnya.
Klaster 3 memiliki nilai PC1 yang sangat negatif. Hal ini menunjukkan bahwa klaster ini berada pada arah yang berlawanan dengan pola utama yang dipengaruhi oleh Semarang Timur dan Semarang Utara. Dengan kata lain, kecamatan dalam klaster ini memiliki karakteristik yang relatif lebih rendah pada dimensi variasi terbesar.
Meskipun PC2 bernilai positif, pengaruhnya tidak sebesar klaster 2. Nilai pada PC3 dan PC4 juga relatif kecil, sehingga tidak menunjukkan karakteristik yang terlalu menonjol pada dimensi tersebut.
Secara keseluruhan, PC1 menjadi pembeda utama antar klaster karena memiliki kontribusi variasi terbesar. Klaster 2 berada pada posisi paling dominan dalam struktur utama data, klaster 3 berada pada arah yang berlawanan, sedangkan klaster 1 menunjukkan karakteristik yang lebih spesifik pada dimensi ketiga.
Dengan menggabungkan hasil PCA dan K-Means, pengelompokan kecamatan di Kota Semarang berdasarkan jumlah penduduk disabilitas tahun 2024 dapat dipahami secara lebih menyeluruh, tidak hanya dari sisi pengelompokan, tetapi juga dari struktur variasi data yang mendasarinya.
#Visualisasi cluster 3D
plot_ly(x = data_scaled$PC1,
y = data_scaled$PC2,
z = data_scaled$PC3,
color = as.factor(kmeans_result$cluster))
#pemetaan klaster
library(geodata) #mengambil data spasial GADM
library(sf) #manipulasi data spasial
library(ggplot2)
library(dplyr)
#mengambil peta administrasi level kecamatan
semarang_kec_map <- gadm(
"Indonesia",
level = 3,
path = tempdir()
)
semarang_kec_map <- semarang_kec_map[
semarang_kec_map$NAME_1 == "Jawa Tengah" &
semarang_kec_map$NAME_2 == "Kota Semarang",
]
#konversi ke format sf
semarang_kec_map_sf <- st_as_sf(semarang_kec_map)
unique(semarang_kec_map$NAME_3)
## [1] "Banyumanik" "Candisari" "Gajahmungkur" "Gayamsari"
## [5] "Genuk" "Gunungpati" "Mijen" "Ngaliyan"
## [9] "Pedurungan" "Semarang Barat" "Semarang Selatan" "Semarang Tengah"
## [13] "Semarang Timur" "Semarang Utara" "Tembalang" "Tugu"
data_cluster_peta <- data.frame(
Kecamatan = c("Banyumanik", "Gajahmungkur", "Genuk", "Mijen",
"Pedurungan", "Semarang Selatan", "Semarang Timur", "Tembalang",
"Candisari", "Gayamsari", "Gunungpati", "Ngaliyan",
"Semarang Barat", "Semarang Tengah", "Semarang Utara", "Tugu"),
Cluster = c(2, 2, 3, 2, 1, 2, 3, 2, 2, 3, 2, 1, 2, 3, 3, 2),
#Kolom nama yang disamakan dengan shapefile
Nama_shapefile = c("Banyumanik", "Gajahmungkur", "Genuk", "Mijen",
"Pedurungan", "Semarang Selatan", "Semarang Timur", "Tembalang",
"Candisari", "Gayamsari", "Gunungpati", "Ngaliyan",
"Semarang Barat", "Semarang Tengah", "Semarang Utara", "Tugu")
)
#Gabungkan hasil cluster asli (bukan manual lagi)
semarang_kec_map_clustered <- semarang_kec_map_sf %>%
left_join(hasil_cluster, by = c("NAME_3" = "Kecamatan"))
#Transform CRS
semarang_kec_map_proj <- st_transform(
semarang_kec_map_clustered,
crs = 32749
)
semarang_kec_centroid <- st_point_on_surface(
semarang_kec_map_proj
)
ggplot(data = semarang_kec_map_clustered) +
geom_sf(aes(fill = as.factor(Cluster)), color = "white") +
geom_sf_text(data = semarang_kec_centroid,
aes(label = NAME_3),
size = 2.5,
color = "black") +
scale_fill_manual(values = c("1" = "green",
"2" = "gold",
"3" = "red"),
name = "Klaster") +
labs(title = "Peta Klaster Penyandang Disabilitas di Kota Semarang",
subtitle = "Hasil K-Means Clustering",
caption = "Sumber: GADM, Data Klaster K-Means") +
theme_minimal()
Peta klaster menunjukkan adanya pola spasial distribusi penyandang disabilitas di Kota Semarang.
Klaster 3 (warna merah) umumnya terletak di wilayah timur dan utara kota yang memiliki jumlah penyandang disabilitas relatif tinggi. Klaster 1 (warna hijau) menunjukkan wilayah dengan karakteristik tertentu yang berbeda dari klaster lainnya, sedangkan klaster 2 (warna kuning) merupakan wilayah dengan jumlah penyandang disabilitas yang relatif sedang dan tersebar di sebagian besar kecamatan.
Pola ini mengindikasikan adanya heterogenitas spasial distribusi penyandang disabilitas di Kota Semarang, yang dapat menjadi dasar perencanaan program pelayanan sosial berbasis wilayah.
Berdasarkan analisis yang dilakukan, dapat disimpulkan bahwa PCA berhasil mereduksi enam variabel jenis disabilitas menjadi empat komponen utama yang menjelaskan lebih dari 98% variasi data.
Metode K-Means dengan tiga klaster berhasil mengelompokkan kecamatan di Kota Semarang berdasarkan karakteristik jumlah penyandang disabilitas. Evaluasi silhouette menunjukkan bahwa struktur klaster cukup baik, dengan klaster 2 memiliki kualitas pemisahan terbaik.
Pemetaan spasial klaster menunjukkan adanya pola distribusi geografis yang jelas, yang mengindikasikan perbedaan karakteristik sosial di setiap wilayah. Hasil ini diharapkan dapat menjadi dasar bagi pemerintah daerah dalam perencanaan kebijakan pembangunan yang inklusif bagi penyandang disabilitas.