Data yang digunakan untuk pengelompokan kali ini yaitu data rata-rata konsumsi per kapita seminggu beberapa macam bahan makanan penting 2025. Data rata-rata konsumsi per kapita seminggu merupakan indikator statistik yang menggambarkan jumlah rata-rata bahan makanan yang dikonsumsi setiap penduduk dalam satu minggu, yang dihitung dari survei rumah tangga.
data <- "Kabupaten_Kota,ayam_ras,Tahu,Tempe,Telur
Pacitan,0.095,0.22,0.208,2.586
Ponorogo,0.1,0.223,0.214,2.363
Trenggalek,0.124,0.186,0.185,2.266
Tulungagung,0.127,0.179,0.149,2.518
Blitar,0.099,0.22,0.167,2.407
Kediri,0.134,0.282,0.183,2.281
Malang,0.125,0.216,0.219,2.128
Lumajang,0.125,0.191,0.191,1.995
Jember,0.106,0.284,0.248,1.901
Banyuwangi,0.119,0.265,0.175,1.897
Bondowoso,0.105,0.393,0.249,1.837
Situbondo,0.082,0.342,0.202,1.546
Probolinggo,0.085,0.25,0.179,1.737
Pasuruan,0.098,0.236,0.261,1.967
Sidoarjo,0.161,0.21,0.204,2.484
Mojokerto,0.118,0.251,0.231,2.017
Jombang,0.1,0.256,0.19,1.968
Nganjuk,0.121,0.372,0.27,2.294
Madiun,0.126,0.237,0.293,2.264
Magetan,0.148,0.198,0.219,2.502
Ngawi,0.119,0.198,0.238,2.537
Bojonegoro,0.106,0.149,0.228,1.883
Tuban,0.113,0.154,0.202,1.914
Lamongan,0.128,0.168,0.149,2.069
Gresik,0.168,0.2,0.176,2.578
Bangkalan,0.101,0.15,0.117,1.614
Sampang,0.077,0.218,0.148,1.93
Pamekasan,0.089,0.207,0.123,1.974
Sumenep,0.094,0.222,0.118,1.698
Kota Kediri,0.143,0.302,0.17,2.388
Kota Blitar,0.117,0.181,0.133,2.152
Kota Malang,0.174,0.236,0.217,2.49
Kota Probolinggo,0.117,0.281,0.172,2.164
Kota Pasuruan,0.141,0.251,0.243,2.369
Kota Mojokerto,0.18,0.212,0.205,2.291
Kota Madiun,0.153,0.222,0.228,2.403
Kota Surabaya,0.199,0.264,0.161,2.858
Kota Batu,0.162,0.226,0.25,2.355"
df <- read.csv(text = data)
df_final <- df %>% remove_rownames() %>% column_to_rownames(var = "Kabupaten_Kota")
head(df_final)
## ayam_ras Tahu Tempe Telur
## Pacitan 0.095 0.220 0.208 2.586
## Ponorogo 0.100 0.223 0.214 2.363
## Trenggalek 0.124 0.186 0.185 2.266
## Tulungagung 0.127 0.179 0.149 2.518
## Blitar 0.099 0.220 0.167 2.407
## Kediri 0.134 0.282 0.183 2.281
Uji asumsi non-multikolinearitas bertujuan untuk mengetahui apakah terdapat korelasi yang tinggi di antara variabel-variabelindependen yang digunakan dalam model. Untuk mengevaluasi hal ini, digunakan nilai Tolerance dan VIF (Variance Inflation Factor) dari masing-masing variabel. Asumsi non-multikolinearitas dianggap terpenuhi jika nilai VIF kurang dari 10, yang berarti tidak terdapat hubungan linear yang kuat antar variabel dalam model penelitian.
\(H_0\):Tidak terdapat hubungan linier antar variabel independen (Tidak terjadi multikolinieritas)
\(H_1\):Terdapat hubungan linier antar variabel independen (Terjadi multikolinieritas)
\(\alpha=5\%\)
df_numerik <- df_final[, c("ayam_ras", "Tahu", "Tempe", "Telur")]
vif_all <- sapply(names(df_numerik), function(x) {
formula <- as.formula(paste(x, "~ ."))
model <- lm(formula, data = df_numerik)
r_sq <- summary(model)$r.squared
vif_val <- 1 / (1 - r_sq)
return(vif_val)
})
vif_table <- data.frame(Variabel = names(vif_all), VIF = as.numeric(vif_all))
print(vif_table)
## Variabel VIF
## 1 ayam_ras 1.980769
## 2 Tahu 1.183005
## 3 Tempe 1.210851
## 4 Telur 2.017420
corr_matrix <- cor(df_final[, c("ayam_ras", "Tahu", "Tempe", "Telur")])
ggcorrplot(corr_matrix,
type = "full", # Menampilkan 4x4 penuh
lab = TRUE, # Menampilkan angka korelasi
lab_size = 4,
method = "square", # Bentuk kotak agar terlihat seperti matriks
colors = c("#6D9EC1", "white", "#E4672E"),
title = "Matriks Korelasi 4x4 Konsumsi Protein Jatim",
ggtheme = theme_minimal())
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the ggcorrplot package.
## Please report the issue at <https://github.com/kassambara/ggcorrplot/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
\(H_0\) ditolak jika nilai VIF kurang dari 10.
\(H_0\) gagal ditolak karena nilai VIF masing-masing variabel kurang dari 10
Pada taraf signifikansi $% $ \(H_0\) ditolak sehingga dapat disimpulkan bahwa asumsi Non-Multikolinieritas terpenuhi
Standardisasi data merupakan proses transformasi data yang bertujuan untuk menyamakan skala atau rentang nilai antar variabel sehingga data dapat dibandingkan secara lebih proporsional. Proses ini dilakukan dengan mengubah nilai asli setiap variabel menjadi nilai baku menggunakan metode Z-score
df_scaled <- scale(df_final)
head(df_scaled)
## ayam_ras Tahu Tempe Telur
## Pacitan -0.97275695 -0.2345065 0.2353606 1.3447182
## Ponorogo -0.79986283 -0.1801697 0.3733097 0.6162683
## Trenggalek 0.03002898 -0.8503246 -0.2934445 0.2994089
## Tulungagung 0.13376546 -0.9771106 -1.1211393 1.1225900
## Blitar -0.83444165 -0.2345065 -0.7072919 0.7599983
## Kediri 0.37581723 0.8884557 -0.3394275 0.3484078
Penentuan jumlah cluster optimal dilakukan menggunakan metode Silhouette. Metode ini mengevaluasi kualitas klaster berdasarkan nilai koefisien Silhouette, yang menunjukkan seberapa baik suatu data cocok dengan klasternya sendiri dibandingkan dengan klaster lain. Jumlah cluster yang optimal ditentukan dari nilai Silhouette rata-rata tertinggi, yang mengindikasikan pemisahan klaster yang baik serta kekompakan antar anggota dalam klaster.
wss <- numeric(10)
for (k in 1:10) {
set.seed(123)
wss[k] <- kmeans(df_scaled, centers = k, nstart = 25)$tot.withinss
}
plot(1:10, wss, type = "b", pch = 19, frame = FALSE,
xaxt = "n", # Menghilangkan sumbu X otomatis
xlab = "Jumlah Klaster (K)",
ylab = "Total WSS",
main = "Elbow Method: Penentuan K Optimal",
col = "blue")
axis(1, at = 1:10)
abline(v = 3, lty = 2, col = "red")
k_range <- 2:10
sil_widths <- numeric(length(k_range))
for (i in seq_along(k_range)) {
k <- k_range[i]
km_temp <- kmeans(df_scaled, centers = k, nstart = 25)
sh <- silhouette(km_temp$cluster, dist(df_scaled))
sil_widths[i] <- mean(sh[, 3])
}
tabel_silhouette <- data.frame(
K = k_range,
Average_Silhouette_Width = round(sil_widths, 4)
)
knitr::kable(tabel_silhouette,
col.names = c("Jumlah Klaster (K)", "Rata-rata Nilai Silhouette"),
caption = "Nilai Silhouette untuk Penentuan K Optimal")
| Jumlah Klaster (K) | Rata-rata Nilai Silhouette |
|---|---|
| 2 | 0.2544 |
| 3 | 0.2835 |
| 4 | 0.2387 |
| 5 | 0.2349 |
| 6 | 0.2731 |
| 7 | 0.2939 |
| 8 | 0.2949 |
| 9 | 0.3026 |
| 10 | 0.3234 |
Dari hasil di atas menunjukkan hasil penentuan jumlah cluster optimal yang diperoleh adalah 3 cluster, karena nilai koefisien Silhouette tertinggi ditemukan pada cluster ke-3 dengan nilai sebesar 0.2835. Penentuan ini dilakukan dikarenakan bila memilih nilai K yang besar dengal populasi yang sedikit akan kurang efektif.
set.seed(123)
final_cluster <- kmeans(df_scaled, centers = 3, nstart = 25)
print(final_cluster)
## K-means clustering with 3 clusters of sizes 19, 12, 7
##
## Cluster means:
## ayam_ras Tahu Tempe Telur
## 1 -0.5432515 -0.467106538 -0.5935443 -0.3523621
## 2 1.1653671 0.008500068 0.2315287 0.9374831
## 3 -0.5232322 1.253289059 1.2141426 -0.6507026
##
## Clustering vector:
## Pacitan Ponorogo Trenggalek Tulungagung
## 1 1 1 1
## Blitar Kediri Malang Lumajang
## 1 2 1 1
## Jember Banyuwangi Bondowoso Situbondo
## 3 1 3 3
## Probolinggo Pasuruan Sidoarjo Mojokerto
## 1 3 2 3
## Jombang Nganjuk Madiun Magetan
## 1 3 3 2
## Ngawi Bojonegoro Tuban Lamongan
## 2 1 1 1
## Gresik Bangkalan Sampang Pamekasan
## 2 1 1 1
## Sumenep Kota Kediri Kota Blitar Kota Malang
## 1 2 1 2
## Kota Probolinggo Kota Pasuruan Kota Mojokerto Kota Madiun
## 1 2 2 2
## Kota Surabaya Kota Batu
## 2 2
##
## Within cluster sum of squares by cluster:
## [1] 39.67813 18.67328 17.16103
## (between_SS / total_SS = 49.0 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
set.seed(123)
final_cluster <- kmeans(df_scaled, centers = 3, nstart = 25)
data_hasil_final <- data.frame(df, Cluster = as.factor(final_cluster$cluster))
head(data_hasil_final, 10)
## Kabupaten_Kota ayam_ras Tahu Tempe Telur Cluster
## Pacitan Pacitan 0.095 0.220 0.208 2.586 1
## Ponorogo Ponorogo 0.100 0.223 0.214 2.363 1
## Trenggalek Trenggalek 0.124 0.186 0.185 2.266 1
## Tulungagung Tulungagung 0.127 0.179 0.149 2.518 1
## Blitar Blitar 0.099 0.220 0.167 2.407 1
## Kediri Kediri 0.134 0.282 0.183 2.281 2
## Malang Malang 0.125 0.216 0.219 2.128 1
## Lumajang Lumajang 0.125 0.191 0.191 1.995 1
## Jember Jember 0.106 0.284 0.248 1.901 3
## Banyuwangi Banyuwangi 0.119 0.265 0.175 1.897 1
library(dplyr)
profil_klaster <- data_hasil_final %>%
group_by(Cluster) %>%
summarise(
Jumlah_Daerah = n(),
Mean_Ayam = mean(ayam_ras),
Mean_Tahu = mean(Tahu),
Mean_Tempe = mean(Tempe),
Mean_Telur = mean(Telur)
)
Berdasarkan nilai rata-rata di atas, karakteristik tiap klaster dapat dijabarkan sebagai berikut:
Klaster 1: Wilayah Konsumsi Protein Rendah (Minimalis) Klaster ini terdiri dari 14 Kabupaten/Kota. Kelompok ini memiliki nilai rata-rata terendah pada hampir seluruh komoditas, terutama pada ayam ras (0,1050) dan tempe (0,1637). Secara statistik, wilayah dalam kelompok ini menunjukkan pola konsumsi protein yang paling terbatas dibandingkan kelompok lainnya di Jawa Timur.
Klaster 2: Wilayah Konsumsi Protein Hewani Tinggi Klaster ini merupakan kelompok terbesar dengan anggota 17 Kabupaten/Kota. Karakteristik utama kelompok ini adalah tingginya konsumsi protein hewani, di mana rata-rata konsumsi ayam ras mencapai 0,1443 dan telur mencapai 2,4351 (tertinggi di antara semua klaster). Wilayah ini umumnya memiliki daya beli atau aksesibilitas yang lebih baik terhadap produk peternakan.
Klaster 3: Wilayah Konsumsi Protein Nabati Tinggi Klaster ini hanya beranggotakan 7 Kabupaten/Kota, namun memiliki pola yang sangat unik. Meskipun konsumsi ayam dan telurnya berada di level menengah, masyarakat di wilayah ini merupakan konsumen tahu dan tempe tertinggi di Jawa Timur, dengan rata-rata konsumsi tahu sebesar 0,3021 dan tempe 0,2506. Hal ini menunjukkan preferensi kuat terhadap protein berbasis kedelai.