Pendahuluan

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.

Standardisasi (Z-Score)

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 (Jarak Mahalanobis)

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 (Variance Inflation Factor)

VIF digunakan untuk melihat indikasi multikolinearitas:

\[ VIF_j=\frac{1}{1-R_j^2} \] Semakin besar VIF, semakin kuat multikolinearitasnya.

K-Means Clustering

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\).

Penentuan Jumlah Klaster Optimal

\[ s(i)=\frac{b(i)-a(i)}{\max\{a(i),b(i)\}} \]

Nilai rata-rata silhouette tertinggi biasanya dipilih sebagai jumlah klaster terbaik.

Input Data dan Pemilihan Variabel

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.

Statistik Deskriptif dan Boxplot

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 dan Deteksi Outlier Multivariat

# 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")

Pemeriksaan Asumsi (VIF)

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.

Menentukan Jumlah Klaster Optimal (Silhouette dan Elbow)

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.

Pemodelan K-Means dengan 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.

Ringkasan Karakteristik Klaster (Skala Asli)

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.

Visualisasi Cluster Plot

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.

Tabel Akhir Hasil Klaster

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.

Pemetaan Klaster Kecamatan Kota Semarang

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.

Kesimpulan

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.