Data

df <- tibble::tribble(
  ~Kecamatan, ~Jumlah_Penduduk, ~Kepadatan_per_km2, ~Pustu, ~Apotek, ~Tenaga_Kesehatan,
  "Weru",      57910, 1269.96, 3, 11,   38,
  "Bulu",      37179,  801.27, 3,  4,   32,
  "Tawangsari",56995, 1449.52, 7, 10,   36,
  "Sukoharjo", 10017, 2139.66, 5, 43,  595,
  "Nguter",    56015,  968.28, 4,  8,   38,
  "Bendosari", 65180, 1169.78, 4, 15,  207,
  "Polokarto", 88708, 1326.18, 5, 20,   30,
  "Mojolaban", 93242, 2435.15, 3, 26,   36,
  "Grogol",   121870, 3889.88, 4, 47,  841,
  "Baki",      72678, 3105.90, 3, 20,   34,
  "Gatak",     54532, 2733.43, 3, 13,   36,
  "Kartasura",111984, 5170.08, 3, 40, 1009
)

kable(df, caption = "Data Kecamatan")
Data Kecamatan
Kecamatan Jumlah_Penduduk Kepadatan_per_km2 Pustu Apotek Tenaga_Kesehatan
Weru 57910 1269.96 3 11 38
Bulu 37179 801.27 3 4 32
Tawangsari 56995 1449.52 7 10 36
Sukoharjo 10017 2139.66 5 43 595
Nguter 56015 968.28 4 8 38
Bendosari 65180 1169.78 4 15 207
Polokarto 88708 1326.18 5 20 30
Mojolaban 93242 2435.15 3 26 36
Grogol 121870 3889.88 4 47 841
Baki 72678 3105.90 3 20 34
Gatak 54532 2733.43 3 13 36
Kartasura 111984 5170.08 3 40 1009

Statistik Deskriptif

num <- df %>% select(-Kecamatan)

stat <- tibble(
  Variabel = names(num),
  Min = sapply(num, min),
  Mean = sapply(num, mean),
  SD = sapply(num, sd),
  Max = sapply(num, max)
)

kable(stat, digits = 2, caption = "Statistik Deskriptif")
Statistik Deskriptif
Variabel Min Mean SD Max
Jumlah_Penduduk 10017.00 68859.17 31309.94 121870.00
Kepadatan_per_km2 801.27 2204.92 1333.74 5170.08
Pustu 3.00 3.92 1.24 7.00
Apotek 4.00 21.42 14.54 47.00
Tenaga_Kesehatan 30.00 244.33 358.75 1009.00

Standarisasi (Z-score)

Variabel-variabel yang digunakan memiliki satuan yang berbeda maka perlu dilakukan standarisasi data, misalnya dengan z-score dengan rumus: \[ Z_{np} = \frac{X_{np} - \bar{X}_{p}}{S_{p}} \]

X <- df %>% select(-Kecamatan)
X_scaled <- scale(X)

# cek sekilas hasil standardisasi
head(X_scaled)
##      Jumlah_Penduduk Kepadatan_per_km2       Pustu     Apotek Tenaga_Kesehatan
## [1,]      -0.3497026       -0.70100716 -0.73918030 -0.7165086       -0.5751473
## [2,]      -1.0118246       -1.05241640 -0.73918030 -1.1980024       -0.5918721
## [3,]      -0.3789265       -0.56637864  2.48633375 -0.7852934       -0.5807223
## [4,]      -1.8793447       -0.04893305  0.87357672  1.4846058        0.9774717
## [5,]      -0.4102265       -0.92719748  0.06719821 -0.9228631       -0.5751473
## [6,]      -0.1175079       -0.77611902  0.06719821 -0.4413693       -0.1040654

Menentukan Jumlah Klaster (Silhouette)

Silhouette dapat dihitung dengan rumus: \[ \mathrm{Silhouette} = \frac{b_i - a_i}{\max\{a_i,\, b_i\}} \]

set.seed(123)

k_range <- 2:6
sil <- numeric(length(k_range))

for(i in seq_along(k_range)){
  k <- k_range[i]
  km <- kmeans(X_scaled, centers = k, nstart = 25)
  s <- silhouette(km$cluster, dist(X_scaled))
  sil[i] <- mean(s[, 3])
}

sil_tbl <- tibble(K = k_range, Silhouette = sil)
kable(sil_tbl, digits = 4, caption = "Silhouette Score")
Silhouette Score
K Silhouette
2 0.5118
3 0.4228
4 0.3719
5 0.3623
6 0.3113
ggplot(sil_tbl, aes(x = K, y = Silhouette)) +
  geom_line() +
  geom_point(size = 2) +
  labs(title = "Silhouette Score vs K", x = "Jumlah Klaster (K)", y = "Silhouette Score")

best_k <- sil_tbl$K[which.max(sil_tbl$Silhouette)]

Jumlah klaster terbaik yang digunakan untuk klasterisasi adalah 2 klaster.

K-Means Clustering

Pengukuran kedekatan dalam K-Means umumnya menggunakan jarak Euclidean, yang dirumuskan sebagai berikut:

\[ d_{ij} = \sqrt{\sum_{k=1}^{p} (x_{ik} - x_{jk})^2} \]

set.seed(123)
km_final <- kmeans(X_scaled, centers = best_k, nstart = 25)

hasil <- df %>%
  mutate(Cluster = as.factor(km_final$cluster)) %>%
  arrange(Cluster, Kecamatan)

kable(hasil, caption = "Hasil Klaster per Kecamatan")
Hasil Klaster per Kecamatan
Kecamatan Jumlah_Penduduk Kepadatan_per_km2 Pustu Apotek Tenaga_Kesehatan Cluster
Baki 72678 3105.90 3 20 34 1
Bendosari 65180 1169.78 4 15 207 1
Bulu 37179 801.27 3 4 32 1
Gatak 54532 2733.43 3 13 36 1
Mojolaban 93242 2435.15 3 26 36 1
Nguter 56015 968.28 4 8 38 1
Polokarto 88708 1326.18 5 20 30 1
Sukoharjo 10017 2139.66 5 43 595 1
Tawangsari 56995 1449.52 7 10 36 1
Weru 57910 1269.96 3 11 38 1
Grogol 121870 3889.88 4 47 841 2
Kartasura 111984 5170.08 3 40 1009 2

Profiling Klaster (Rata-rata per Klaster)

profil <- hasil %>%
  group_by(Cluster) %>%
  summarise(
    Jumlah_Penduduk = mean(Jumlah_Penduduk),
    Kepadatan_per_km2 = mean(Kepadatan_per_km2),
    Pustu = mean(Pustu),
    Apotek = mean(Apotek),
    Tenaga_Kesehatan = mean(Tenaga_Kesehatan),
    .groups = "drop"
  )

kable(profil, digits = 2, caption = "Rata-rata Variabel per Klaster (Profiling)")
Rata-rata Variabel per Klaster (Profiling)
Cluster Jumlah_Penduduk Kepadatan_per_km2 Pustu Apotek Tenaga_Kesehatan
1 59245.6 1739.91 4.0 17.0 108.2
2 116927.0 4529.98 3.5 43.5 925.0

Klaster 1 memiliki rata-rata jumlah penduduk sekitar 59246 jiwa dengan kepadatan sekitar 1740 jiwa/km². Rata-rata puskesmas pembantu sebanyak 4 unit, apotek sekitar 17 unit, dan tenaga kesehatan sekitar 108 orang. Klaster ini merepresentasikan kecamatan dengan karakteristik relatif lebih rendah.

Sebaliknya, Klaster 2 memiliki rata-rata jumlah penduduk sekitar 116927 jiwa dengan kepadatan sekitar 4530 jiwa/km². Jumlah puskesmas pembantu sekitar 4 unit, apotek sekitar 44 unit, dan tenaga kesehatan sekitar 925 orang. Klaster ini menunjukkan kecamatan dengan kepadatan dan fasilitas kesehatan lebih tinggi.