Penelitian ini bertujuan untuk mengelompokkan kecamatan di Kota Semarang berdasarkan jumlah penduduk menurut sektor pekerjaan pada tahun 2024 dengan menggunakan metode K-Means Clustering. Pengelompokan dilakukan untuk mengidentifikasi pola distribusi tenaga kerja antar kecamatan sehingga dapat diketahui wilayah-wilayah yang memiliki karakteristik serupa berdasarkan komposisi sektor pekerjaan.
Perbedaan jumlah penduduk yang bekerja pada sektor tenaga kesehatan, perdagangan, dan karyawan swasta dapat mencerminkan tingkat aktivitas ekonomi dan perkembangan suatu wilayah. Kecamatan dengan konsentrasi tenaga kerja tinggi pada sektor tertentu dapat menunjukkan adanya pusat aktivitas ekonomi atau kawasan yang lebih berkembang, sedangkan kecamatan dengan jumlah tenaga kerja relatif lebih rendah dapat mengindikasikan karakteristik wilayah yang berbeda.
Analisis dilakukan melalui beberapa tahapan, yaitu statistik deskriptif untuk memahami karakteristik awal data, standardisasi variabel menggunakan z-score untuk menyamakan skala pengukuran, deteksi outlier multivariat menggunakan jarak Mahalanobis, pemeriksaan struktur korelasi menggunakan uji VIF, penentuan jumlah klaster optimal menggunakan metode Silhouette dan Elbow (Within Sum of Squares), pengelompokan menggunakan algoritma K-Means, evaluasi hasil klaster, serta visualisasi spasial dalam bentuk peta klaster Kecamatan Kota Semarang.
Hasil dari penelitian ini diharapkan dapat memberikan gambaran mengenai pola pengelompokan kecamatan berdasarkan sektor pekerjaan sehingga dapat menjadi bahan pertimbangan dalam perencanaan pembangunan dan pengambilan kebijakan yang lebih terarah sesuai karakteristik wilayah.
K-Means umumnya menggunakan jarak Euclidean, sehingga variabel berskala besar dapat mendominasi jarak. Untuk menghindari hal tersebut dilakukan standardisasi z-score:
\[ z_{ij}=\frac{x_{ij}-\bar{x}_j}{s_j} \] dengan \(x_{ij}\) nilai observasi ke-\(i\) pada variabel ke-\(j\), \(\bar{x}_j\) rata-rata variabel ke-\(j\), dan \(s_j\) simpangan baku variabel ke-\(j\).
Outlier multivariat diperiksa menggunakan jarak Mahalanobis:
\[
D_i^2=(\mathbf{x}_i-\boldsymbol{\mu})^T\mathbf{S}^{-1}(\mathbf{x}_i-\boldsymbol{\mu})
\] dengan \(\mathbf{x}_i\)
vektor observasi, \(\boldsymbol{\mu}\)
vektor rata-rata, dan \(\mathbf{S}\)
matriks kovarians.
Kriteria umum:
\[ D_i^2>\chi^2_{\alpha,p} \] dengan \(p\) jumlah variabel dan \(\alpha\) taraf signifikansi.
VIF digunakan untuk melihat indikasi multikolinearitas:
\[ VIF_j=\frac{1}{1-R_j^2} \] Semakin besar VIF, semakin kuat multikolinearitasnya.
Tujuan K-Means adalah meminimalkan jumlah kuadrat jarak dalam klaster (Within-Cluster Sum of Squares):
\[ \min\sum_{l=1}^{k}\sum_{\mathbf{x}_i\in C_l}\|\mathbf{x}_i-\boldsymbol{\mu}_l\|^2 \] dengan \(C_l\) adalah klaster ke-\(l\) dan \(\boldsymbol{\mu}_l\) centroid klaster ke-\(l\).
\[ s(i)=\frac{b(i)-a(i)}{\max\{a(i),b(i)\}} \]
Nilai rata-rata silhouette tertinggi biasanya dipilih sebagai jumlah klaster terbaik.
library(readxl)
library(tibble)
UBAH PATH SESUAI LOKASI FILE KAMU
KP <- read_excel("D:/SEMESTER 6/KERJA PRAKTIK/data.xlsx")
data <- KP[, 2:4]
data
## # A tibble: 16 × 3
## X1 X2 X3
## <dbl> <dbl> <dbl>
## 1 229 37 17453
## 2 242 117 35388
## 3 181 70 21639
## 4 200 52 22050
## 5 286 80 43855
## 6 1039 85 61027
## 7 384 86 19952
## 8 327 21 25225
## 9 430 27 18016
## 10 925 132 57645
## 11 1043 83 40011
## 12 361 47 30641
## 13 617 108 49551
## 14 237 82 22349
## 15 599 50 44451
## 16 77 12 10660
Interpretasi:
Data dibaca dari file Excel dan dipilih tiga variabel (kolom 2–4)
sebagai variabel analisis. Kolom pertama diasumsikan sebagai identitas
kecamatan. Tahap ini memastikan algoritma clustering bekerja pada
variabel numerik yang relevan.
library(psych)
summary(data)
## X1 X2 X3
## Min. : 77.0 Min. : 12.00 Min. :10660
## 1st Qu.: 235.0 1st Qu.: 44.50 1st Qu.:21217
## Median : 344.0 Median : 75.00 Median :27933
## Mean : 448.6 Mean : 68.06 Mean :32495
## 3rd Qu.: 603.5 3rd Qu.: 85.25 3rd Qu.:44004
## Max. :1043.0 Max. :132.00 Max. :61027
boxplot(KP$X1, main = "Tenaga Kesehatan (X1)", ylab = "Jumlah (Orang)")
boxplot(KP$X2, main = "Perdagangan (X2)", ylab = "Jumlah (Orang)")
boxplot(KP$X3, main = "Karyawan Swasta (X3)", ylab = "Jumlah (Orang)")
Interpretasi:
Ringkasan statistik menunjukkan sebaran data antar variabel berbeda
cukup jauh. Hal ini penting karena K-Means sensitif terhadap skala.
Boxplot membantu melihat sebaran data dan potensi nilai ekstrem secara
univariat.
# Standardisasi z-score
data_z <- scale(KP[, 2:4])
# Mahalanobis distance
mean_vec <- colMeans(data_z)
cov_mat <- cov(data_z)
jarak_mahal <- mahalanobis(data_z, mean_vec, cov_mat)
# Batas chi-square
batas <- qchisq(0.975, df = ncol(data_z))
outlier <- jarak_mahal > batas
# Tabel hasil
outlier_mahal <- data.frame(
Kecamatan = KP$Kecamatan,
Mahalanobis = jarak_mahal,
Outlier = outlier
)
outlier_mahal
## Kecamatan Mahalanobis Outlier
## 1 Semarang Tengah 1.0644915 FALSE
## 2 Semarang Utara 4.2528282 FALSE
## 3 Semarang Timur 1.1742221 FALSE
## 4 Gayamsari 0.6524441 FALSE
## 5 Genuk 4.1377371 FALSE
## 6 Pedurungan 4.8412296 FALSE
## 7 Semarang Selatan 3.5949393 FALSE
## 8 Candisari 2.2021198 FALSE
## 9 Gajahmungkur 2.5263146 FALSE
## 10 Tembalang 3.9356425 FALSE
## 11 Banyumanik 6.8308738 FALSE
## 12 Gunungpati 0.6771448 FALSE
## 13 Semarang Barat 1.7667148 FALSE
## 14 Mijen 1.7416880 FALSE
## 15 Ngaliyan 2.7519531 FALSE
## 16 Tugu 2.8496566 FALSE
Interpretasi:
Standardisasi dilakukan agar ketiga variabel setara dalam kontribusi
jarak. Hasil jarak Mahalanobis dibandingkan dengan batas chi-square.
Jika Outlier = TRUE maka kecamatan dianggap outlier
multivariat. Pada data ini, seluruh kecamatan tidak terdeteksi sebagai
outlier multivariat sehingga data relatif aman untuk K-Means.
library(ggplot2)
ggplot(outlier_mahal,
aes(x = Mahalanobis, y = reorder(Kecamatan, Mahalanobis),
color = Outlier)) +
geom_point(size = 3) +
theme_minimal() +
labs(title = "Deteksi Outlier Multivariat (Mahalanobis)",
x = "Jarak Mahalanobis", y = "Kecamatan")
Interpretasi:
Plot memperlihatkan kecamatan berdasarkan besar jarak Mahalanobis.
Meskipun ada kecamatan dengan jarak lebih besar, semuanya masih di bawah
batas kritis sehingga tidak dianggap ekstrem secara multivariat.
#Ubah ke data frame agar bisa disimpan#
data_z<-as.data.frame(data_z)
data_z
## X1 X2 X3
## 1 -0.70853211 -0.88963435 -0.9804333
## 2 -0.66658088 1.40157686 0.1885989
## 3 -0.86342897 0.05549027 -0.7075831
## 4 -0.80211563 -0.46003225 -0.6807934
## 5 -0.52459209 0.34189167 0.7404916
## 6 1.90535236 0.48509237 1.8597903
## 7 -0.20834434 0.51373251 -0.8175444
## 8 -0.39228436 -1.34787660 -0.4738418
## 9 -0.05990152 -1.17603576 -0.9437360
## 10 1.53747232 1.83117896 1.6393460
## 11 1.91826043 0.42781209 0.4899335
## 12 -0.28256575 -0.60323295 -0.1208182
## 13 0.54355082 1.14381560 1.1117661
## 14 -0.68271597 0.39917195 -0.6613041
## 15 0.48546450 -0.51731253 0.7793399
## 16 -1.19903882 -1.60563786 -1.4232120
library(writexl)
write_xlsx(data_z, "D:/SEMESTER 6/KERJA PRAKTIK/Standarisasi z-score.xlsx")
library(car)
vif_all <- function(data_z) {
variables <- colnames(data_z)
vif_values <- c()
for (var in variables) {
independent_vars <- setdiff(variables, var)
formula <- as.formula(paste(var, "~", paste(independent_vars, collapse = " + ")))
model <- lm(formula, data = data_z)
vif_values[var] <- max(vif(model))
}
return(vif_values)
}
vif_all(data_z)
## X1 X2 X3
## 1.820007 2.720584 1.287063
Interpretasi:
Nilai VIF yang relatif kecil (umumnya < 5) menunjukkan tidak terjadi
multikolinearitas berlebihan. Ini berarti masing-masing variabel masih
memberi informasi yang berbeda dalam pembentukan klaster.
library(car)
library(psych)
library(cluster)
library(tidyverse)
library(factoextra)
library(ggplot2)
set.seed(123)
silhouette_plot <- fviz_nbclust(data_z, kmeans, method = "silhouette")
silhouette_plot
sil_data <- data.frame(silhouette_plot$data)
sil_data
## clusters y
## 1 1 0.0000000
## 2 2 0.4268754
## 3 3 0.3529697
## 4 4 0.2651954
## 5 5 0.1948444
## 6 6 0.2748915
## 7 7 0.2356296
## 8 8 0.1938045
## 9 9 0.1907849
## 10 10 0.1456622
Interpretasi:
Metode Silhouette memilih jumlah klaster dengan nilai rata-rata
silhouette tertinggi. Pada hasil ini, nilai tertinggi muncul saat
k = 2, sehingga kandidat klaster terbaik adalah 2
klaster.
fviz_nbclust(data_z, kmeans, method = "wss") +
labs(title = "Elbow Method (Within Sum of Squares)")
Interpretasi:
Elbow Method melihat penurunan WSS. Penurunan paling tajam terjadi dari
k=1 ke k=2, lalu melandai setelahnya. Pola ini mendukung pemilihan
k = 2.
set.seed(123)
final <- kmeans(data_z, 2)
final
## K-means clustering with 2 clusters of sizes 7, 9
##
## Cluster means:
## X1 X2 X3
## 1 0.7427039 0.7305793 0.9727523
## 2 -0.5776586 -0.5682283 -0.7565851
##
## Clustering vector:
## [1] 2 1 2 2 1 1 2 2 2 1 1 2 1 2 1 2
##
## Within cluster sum of squares by cluster:
## [1] 12.945736 6.772102
## (between_SS / total_SS = 56.2 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Interpretasi:
K-Means membagi 16 kecamatan menjadi 2 klaster. Rata-rata klaster pada
data z-score menunjukkan arah karakteristik: klaster dengan mean positif
cenderung memiliki nilai di atas rata-rata pada variabel-variabel
tersebut, sedangkan mean negatif cenderung di bawah rata-rata.
KP$cluster <- as.factor(final$cluster)
library(dplyr)
cluster_summary_KP <- KP %>%
group_by(cluster) %>%
summarise(
rata_X1 = mean(X1, na.rm = TRUE),
rata_X2 = mean(X2, na.rm = TRUE),
rata_X3 = mean(X3, na.rm = TRUE)
)
cluster_summary_KP
## # A tibble: 2 × 4
## cluster rata_X1 rata_X2 rata_X3
## <fct> <dbl> <dbl> <dbl>
## 1 1 679. 93.6 47418.
## 2 2 270. 48.2 20887.
Interpretasi:
Ringkasan rata-rata pada skala asli memudahkan pembacaan.
- Klaster dengan rata-rata lebih tinggi menunjukkan
kecamatan dengan intensitas sektor pekerjaan (X1, X2, X3) lebih
besar.
- Klaster dengan rata-rata lebih rendah menunjukkan
kecamatan dengan intensitas sektor pekerjaan lebih kecil.
Dengan demikian, dua klaster yang terbentuk bisa dibaca sebagai kelompok kecamatan dengan konsentrasi tenaga kerja yang relatif tinggi vs relatif rendah berdasarkan tiga sektor pekerjaan yang dianalisis.
data_awal <- KP[, 2:4]
fviz_cluster(final, data = data_awal)
Interpretasi:
Plot klaster menunjukkan pemisahan dua kelompok kecamatan berdasarkan
kemiripan tiga variabel. Jika titik-titik dalam klaster terlihat relatif
berdekatan, berarti anggota klaster tersebut memiliki karakteristik yang
mirip.
finalakhir <- data.frame(KP, cluster = final$cluster)
finalakhir
## Kecamatan X1 X2 X3 cluster cluster.1
## 1 Semarang Tengah 229 37 17453 2 2
## 2 Semarang Utara 242 117 35388 1 1
## 3 Semarang Timur 181 70 21639 2 2
## 4 Gayamsari 200 52 22050 2 2
## 5 Genuk 286 80 43855 1 1
## 6 Pedurungan 1039 85 61027 1 1
## 7 Semarang Selatan 384 86 19952 2 2
## 8 Candisari 327 21 25225 2 2
## 9 Gajahmungkur 430 27 18016 2 2
## 10 Tembalang 925 132 57645 1 1
## 11 Banyumanik 1043 83 40011 1 1
## 12 Gunungpati 361 47 30641 2 2
## 13 Semarang Barat 617 108 49551 1 1
## 14 Mijen 237 82 22349 2 2
## 15 Ngaliyan 599 50 44451 1 1
## 16 Tugu 77 12 10660 2 2
Interpretasi:
Tabel akhir memuat kecamatan beserta label klasternya. Hasil ini dapat
digunakan untuk analisis lanjutan, misalnya membandingkan klaster dengan
aspek wilayah (pusat/pinggiran), atau dipakai sebagai dasar
pemetaan.
library(sf)
library(geodata)
library(ggplot2)
library(readxl)
library(dplyr)
# Ambil peta level 3 (kecamatan)
jateng_map <- gadm("Indonesia", level = 3, path = tempdir())
# Filter Provinsi Jawa Tengah
jateng_map <- jateng_map[jateng_map$NAME_1 == "Jawa Tengah", ]
# Filter Kota Semarang
semarang_map <- jateng_map[jateng_map$NAME_2 == "Kota Semarang", ]
# Konversi ke sf
semarang_map_sf <- st_as_sf(semarang_map)
# Gabungkan data klaster
data_clustered <- data.frame(
Kecamatan = KP$Kecamatan,
Cluster = KP$cluster
)
semarang_map_clustered <- semarang_map_sf %>%
left_join(data_clustered, by = c("NAME_3" = "Kecamatan"))
# Titik label
semarang_centroid <- st_point_on_surface(semarang_map_clustered)
ggplot(data = semarang_map_clustered) +
geom_sf(aes(fill = as.factor(Cluster)), color = "white", size = 0.3) +
geom_sf_text(
data = semarang_centroid,
aes(label = NAME_3),
size = 3,
color = "black"
) +
scale_fill_manual(
values = c("1" = "orange", "2" = "red"),
name = "Klaster"
) +
labs(
title = "Peta Klaster Kecamatan Kota Semarang",
subtitle = "Hasil K-Means Clustering Tahun 2024",
caption = "Sumber: GADM dan Data Penelitian (diolah)"
) +
theme_minimal()
Interpretasi:
Peta klaster membantu melihat pola spasial: apakah kecamatan dalam satu
klaster cenderung mengelompok secara geografis atau tersebar.
Visualisasi ini memudahkan pembacaan hasil clustering dalam konteks
wilayah.
Secara umum, klaster dengan nilai rata-rata lebih tinggi menggambarkan
kecamatan yang memiliki intensitas sektor pekerjaan yang lebih besar
pada tiga variabel yang digunakan, sedangkan klaster lainnya menunjukkan
intensitas yang relatif lebih rendah.
Berdasarkan metode Silhouette dan Elbow (WSS), jumlah klaster optimal untuk pengelompokan kecamatan di Kota Semarang berdasarkan sektor pekerjaan tahun 2024 adalah 2 klaster. Hasil K-Means membagi kecamatan menjadi dua kelompok dengan karakteristik yang berbeda. Klaster pertama cenderung memiliki nilai rata-rata sektor pekerjaan yang lebih tinggi, sedangkan klaster kedua memiliki nilai rata-rata yang lebih rendah.