library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.4.2
## Warning: package 'ggplot2' was built under R version 4.4.3
## Warning: package 'tidyr' was built under R version 4.4.2
## Warning: package 'readr' was built under R version 4.4.2
## Warning: package 'purrr' was built under R version 4.4.2
## Warning: package 'stringr' was built under R version 4.4.3
## Warning: package 'forcats' was built under R version 4.4.2
## Warning: package 'lubridate' was built under R version 4.4.2
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.4.3
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
data_tpg <- read.csv("C:/Users/Resea/Documents/Semester 5/TPG/TUGAS INDIVIDU/0_df_long.csv", sep = ";", header = TRUE)
head (data_tpg)
## KabKot Tahun Bulan Produk Harga Kategori KodeBPS
## 1 Kab. Aceh Barat 2022 Januari Beras Premium 11429 Beras 11.05
## 2 Kab. Aceh Barat 2022 Januari Beras Medium 9979 Beras 11.05
## 3 Kab. Aceh Barat 2022 Januari Bawang Merah 31000 Bawang 11.05
## 4 Kab. Aceh Barat 2022 Januari Bawang Putih (Bonggol) 28636 Bawang 11.05
## 5 Kab. Aceh Barat 2022 Januari Cabai Merah Keriting 19409 Cabai 11.05
## 6 Kab. Aceh Barat 2022 Januari Cabai Rawit Merah 45706 Cabai 11.05
## KodeProv NamaProv
## 1 11 Aceh
## 2 11 Aceh
## 3 11 Aceh
## 4 11 Aceh
## 5 11 Aceh
## 6 11 Aceh
str(data_tpg) # Melihat struktur data
## 'data.frame': 340620 obs. of 9 variables:
## $ KabKot : chr "Kab. Aceh Barat" "Kab. Aceh Barat" "Kab. Aceh Barat" "Kab. Aceh Barat" ...
## $ Tahun : int 2022 2022 2022 2022 2022 2022 2022 2022 2022 2022 ...
## $ Bulan : chr "Januari" "Januari" "Januari" "Januari" ...
## $ Produk : chr "Beras Premium" "Beras Medium" "Bawang Merah" "Bawang Putih (Bonggol)" ...
## $ Harga : num 11429 9979 31000 28636 19409 ...
## $ Kategori: chr "Beras" "Beras" "Bawang" "Bawang" ...
## $ KodeBPS : num 11.1 11.1 11.1 11.1 11.1 ...
## $ KodeProv: int 11 11 11 11 11 11 11 11 11 11 ...
## $ NamaProv: chr "Aceh" "Aceh" "Aceh" "Aceh" ...
data_tpg <- data_tpg %>%
mutate(
Tahun = as.integer(Tahun),
Harga = as.numeric(Harga),
KodeProv = as.numeric(KodeProv)
)
produk_hewani <- c("Daging Ayam Ras", "Daging Sapi Murni", "Telur Ayam Ras")
data_jabar_hewani_2025 <- data_tpg %>%
filter(
Tahun == 2025,
NamaProv == "Jawa Barat",
Produk %in% produk_hewani
)
head(data_jabar_hewani_2025)
## KabKot Tahun Bulan Produk Harga Kategori KodeBPS
## 1 Kab. Bandung 2025 Januari Daging Sapi Murni 125300 Protein 32.04
## 2 Kab. Bandung 2025 Januari Daging Ayam Ras 35672 Protein 32.04
## 3 Kab. Bandung 2025 Januari Telur Ayam Ras 27803 Protein 32.04
## 4 Kab. Bandung 2025 Februari Daging Sapi Murni 126342 Protein 32.04
## 5 Kab. Bandung 2025 Februari Daging Ayam Ras 35147 Protein 32.04
## 6 Kab. Bandung 2025 Februari Telur Ayam Ras 27929 Protein 32.04
## KodeProv NamaProv
## 1 32 Jawa Barat
## 2 32 Jawa Barat
## 3 32 Jawa Barat
## 4 32 Jawa Barat
## 5 32 Jawa Barat
## 6 32 Jawa Barat
Menggunakan hirarki imputasi seperti ini: 1. Harga asli 2. Rata-rata per Kab/Kota & Produk (di Jawa Barat 2025) 3. Rata-rata Jawa Barat per Produk (2025) 4. Rata-rata provinsi tetangga Jawa Barat (DKI Jakarta, Banten, Jawa Tengah) 5. Rata-rata nasional per Produk (2025)
# Rata-rata Kab/Kota per Produk Jawa Barat 2025
mean_kab_prod_jabar <- data_jabar_hewani_2025 %>%
group_by(KabKot, Produk) %>%
summarise(mean_kab = mean(Harga, na.rm = TRUE), .groups = "drop")
# Rata-rata Jawa Barat per Produk 2025
mean_jabar_prod <- data_jabar_hewani_2025 %>%
group_by(Produk) %>%
summarise(mean_jabar = mean(Harga, na.rm = TRUE), .groups = "drop")
# Rata-rata Provinsi Tetangga
neighbor_jabar <- c("DKI Jakarta", "Banten", "Jawa Tengah")
mean_tetangga <- data_tpg %>%
filter(
Tahun == 2025,
NamaProv %in% neighbor_jabar,
Produk %in% produk_hewani
) %>%
group_by(Produk) %>%
summarise(mean_neighbor = mean(Harga, na.rm = TRUE), .groups = "drop")
# Rata-rata Nasional per Produk Hewani 2025
mean_nasional <- data_tpg %>%
filter(
Tahun == 2025,
Produk %in% produk_hewani
) %>%
group_by(Produk) %>%
summarise(mean_nasional = mean(Harga, na.rm = TRUE), .groups = "drop")
library(dplyr)
library(ggplot2)
data_jabar_hewani_2025 <- data_jabar_hewani_2025 |>
mutate(
Bulan = factor(
Bulan,
levels = c("Januari","Februari","Maret","April","Mei","Juni",
"Juli","Agustus","September","Oktober","November","Desember")
)
)
data_jabar_hewani_2025 |>
group_by(Produk) |>
summarise(mean_harga = mean(Harga, na.rm = TRUE)) |>
ggplot(aes(x = reorder(Produk, mean_harga), y = mean_harga)) +
geom_col() +
coord_flip() +
labs(
title = "Rata-rata harga komoditas hewani\nJawa Barat, 2025",
x = "Produk",
y = "Rata-rata Harga"
)
Grafik tersebut menunjukkan bahwa pada tahun 2025 di Jawa Barat,
rata-rata harga komoditas hewani paling tinggi adalah daging sapi murni,
disusul oleh daging ayam ras, sementara telur ayam ras memiliki harga
rata-rata paling rendah; artinya, untuk memenuhi kebutuhan protein
hewani, masyarakat cenderung lebih mudah menjangkau telur dan daging
ayam ras dibandingkan daging sapi karena perbedaan harga yang cukup
besar.
ggplot(data_jabar_hewani_2025,
aes(x = Produk, y = Harga)) +
geom_boxplot() +
coord_flip() +
labs(
title = "Distribusi harga komoditas hewani\nJawa Barat, 2025",
x = "Produk",
y = "Harga"
)
## Warning: Removed 1 row containing non-finite outside the scale range
## (`stat_boxplot()`).
Grafik boxplot tersebut menunjukkan bahwa pada tahun 2025 di Jawa Barat,
telur ayam ras memiliki harga paling rendah dan
penyebaran yang relatif sempit sehingga harganya cukup stabil,
daging ayam ras berharga lebih tinggi dengan rentang
harga yang sedikit lebih lebar dan terdapat beberapa nilai ekstrem yang
menunjukkan variasi harga di beberapa pasar, sedangkan daging
sapi murni memiliki tingkat harga paling tinggi dengan sebaran
yang juga cukup sempit meskipun ada titik-titik pencilan, sehingga
secara umum harga daging sapi konsisten mahal namun masih terjadi
variasi di beberapa lokasi.
data_jabar_hewani_2025_imp <- data_jabar_hewani_2025 %>%
# Join mean kab/kota
left_join(mean_kab_prod_jabar, by = c("KabKot", "Produk")) %>%
# Join mean Jabar
left_join(mean_jabar_prod, by = "Produk") %>%
# Join mean tetangga
left_join(mean_tetangga, by = "Produk") %>%
# Join mean nasional
left_join(mean_nasional, by = "Produk") %>%
mutate(
Harga_imputed = case_when(
!is.na(Harga) ~ Harga,
is.na(Harga) & !is.na(mean_kab) ~ mean_kab,
is.na(Harga) & is.na(mean_kab) & !is.na(mean_jabar) ~ mean_jabar,
is.na(Harga) & is.na(mean_kab) & is.na(mean_jabar) & !is.na(mean_neighbor) ~ mean_neighbor,
TRUE ~ mean_nasional
)
)
# Cek apakah masih ada NA
sum(is.na(data_jabar_hewani_2025_imp$Harga_imputed))
## [1] 0
Hasilnya sudah 0 maka semua missing value sudah ditangani.
kab_produk_hewani_jabar <- data_jabar_hewani_2025_imp %>%
group_by(KabKot, Produk) %>%
summarise(
mean_harga = mean(Harga_imputed, na.rm = TRUE),
.groups = "drop"
) %>%
tidyr::pivot_wider(
names_from = Produk,
values_from = mean_harga
)
head(kab_produk_hewani_jabar)
## # A tibble: 6 × 4
## KabKot `Daging Ayam Ras` `Daging Sapi Murni` `Telur Ayam Ras`
## <chr> <dbl> <dbl> <dbl>
## 1 Kab. Bandung 34679 131454. 27782.
## 2 Kab. Bandung Barat 33448. 125424 27903.
## 3 Kab. Bekasi 41574. 132942. 29067.
## 4 Kab. Bogor 36507. 126500. 28030.
## 5 Kab. Ciamis 38696. 135300. 28216.
## 6 Kab. Cianjur 35699 133027. 29159.
library(dplyr)
library(tidyr)
library(ggplot2)
kab_long <- kab_produk_hewani_jabar |>
pivot_longer(
cols = -KabKot,
names_to = "Produk",
values_to = "Harga"
)
head(kab_long)
## # A tibble: 6 × 3
## KabKot Produk Harga
## <chr> <chr> <dbl>
## 1 Kab. Bandung Daging Ayam Ras 34679
## 2 Kab. Bandung Daging Sapi Murni 131454.
## 3 Kab. Bandung Telur Ayam Ras 27782.
## 4 Kab. Bandung Barat Daging Ayam Ras 33448.
## 5 Kab. Bandung Barat Daging Sapi Murni 125424
## 6 Kab. Bandung Barat Telur Ayam Ras 27903.
kab_long |>
group_by(Produk) |>
summarise(mean_harga = mean(Harga, na.rm = TRUE)) |>
ggplot(aes(x = reorder(Produk, mean_harga), y = mean_harga)) +
geom_col() +
coord_flip() +
labs(
title = "Rata-rata harga komoditas hewani\nJawa Barat setelah imputasi",
x = "Produk",
y = "Rata-rata harga"
)
Setelah dilakukan imputasi terhadap data yang hilang, grafik rata-rata
harga komoditas hewani di Jawa Barat menunjukkan bahwa pola harganya
tetap sama: daging sapi murni masih memiliki rata-rata
harga paling tinggi, daging ayam ras berada di posisi
menengah, dan telur ayam ras tetap menjadi komoditas
dengan rata-rata harga paling rendah. Perbedaan ketiga rata-rata
tersebut kini mencerminkan estimasi yang lebih lengkap dan andal karena
sudah mempertimbangkan nilai-nilai yang sebelumnya kosong dalam
data.
ggplot(kab_long,
aes(x = Produk, y = Harga)) +
geom_boxplot() +
labs(
title = "Distribusi harga komoditas hewani\nantar kabupaten di Jawa Barat setelah imputasi",
x = "Produk",
y = "Harga"
)
Setelah imputasi, boxplot menunjukkan bahwa distribusi harga komoditas
hewani antar kabupaten di Jawa Barat tetap mempertahankan pola awal:
daging sapi murni memiliki harga paling tinggi dengan
sebaran yang cukup lebar menandakan perbedaan harga yang cukup besar
antar kabupaten; daging ayam ras berada di tingkat
harga menengah dengan rentang yang relatif lebih sempit sehingga variasi
harganya moderat; sedangkan telur ayam ras tetap
menjadi komoditas termurah dengan sebaran harga paling sempit,
menunjukkan bahwa harga telur relatif paling stabil di berbagai
kabupaten meskipun data yang hilang telah diimputasi.
kabkot <- kab_produk_hewani_jabar$KabKot
X <- kab_produk_hewani_jabar %>%
select(-KabKot) %>%
as.data.frame()
# Cek kalau masih ada NA
colSums(is.na(X))
## Daging Ayam Ras Daging Sapi Murni Telur Ayam Ras
## 0 0 0
Sudah terisi semua.
Supaya semua produk hewani punya skala sebanding:
X_scaled <- scale(X)
summary(X_scaled)
## Daging Ayam Ras Daging Sapi Murni Telur Ayam Ras
## Min. :-1.75238 Min. :-1.8349 Min. :-2.13354
## 1st Qu.:-0.62506 1st Qu.:-0.6120 1st Qu.:-0.62708
## Median :-0.04615 Median :-0.1069 Median :-0.03067
## Mean : 0.00000 Mean : 0.0000 Mean : 0.00000
## 3rd Qu.: 0.66207 3rd Qu.: 0.4616 3rd Qu.: 0.48485
## Max. : 2.23863 Max. : 2.1900 Max. : 2.57649
fviz_nbclust(X_scaled, kmeans, method = "wss") +
ggtitle("Elbow Method - Kab/Kota Jabar 2025 (Produk Hewani)")
Titik siku (elbow) yang paling terlihat: k = 3 atau k = 4.
fviz_nbclust(X_scaled, kmeans, method = "silhouette") +
ggtitle("Silhouette Method - Kab/Kota Jabar 2025 (Produk Hewani)")
Menurut Silhouette, k = 7 adalah nilai terbaik.
library(cluster)
library(factoextra)
set.seed(123)
gap_stat <- clusGap(
X_scaled,
FUN = kmeans,
nstart = 25,
K.max = 10,
B = 100
)
# Tampilkan tabel gap statistic
print(gap_stat, method = "firstmax")
## Clustering Gap statistic ["clusGap"] from call:
## clusGap(x = X_scaled, FUNcluster = kmeans, K.max = 10, B = 100, nstart = 25)
## B=100 simulated reference sets, k = 1..10; spaceH0="scaledPCA"
## --> Number of clusters (method 'firstmax'): 1
## logW E.logW gap SE.sim
## [1,] 2.679937 2.815722 0.13578469 0.07037081
## [2,] 2.402820 2.516190 0.11336967 0.07072839
## [3,] 2.229286 2.282945 0.05365886 0.07005051
## [4,] 2.076377 2.106640 0.03026324 0.06920323
## [5,] 1.932607 1.962026 0.02941820 0.07290277
## [6,] 1.787801 1.831929 0.04412734 0.07405323
## [7,] 1.625319 1.709929 0.08461061 0.07552367
## [8,] 1.524241 1.591869 0.06762874 0.07823486
## [9,] 1.404968 1.476145 0.07117735 0.08053665
## [10,] 1.299160 1.363439 0.06427820 0.08129567
# Visualisasikan
fviz_gap_stat(gap_stat) +
ggtitle("Gap Statistic - Kab/Kota Jawa Barat 2025 (Produk Hewani)")
Menurut Gap Statistic nilai optimal k = 1 atau 2 karena memiliki gap
tertinggi 0.1357846 dan 0.11336967.
library(fpc)
## Warning: package 'fpc' was built under R version 4.4.3
set.seed(123)
k.max <- 10
ch <- numeric(k.max)
for (k in 2:k.max) {
km <- kmeans(X_scaled, centers = k, nstart = 25)
ch[k] <- calinhara(X_scaled, km$cluster, k) # Calinski–Harabasz
}
# Lihat nilai CH tiap k
ch
## [1] 0.00000 16.61720 15.69207 15.18459 15.29494 16.85159 18.55783 18.15479
## [9] 18.39191 18.11041
# Plot
plot(2:k.max, ch[2:k.max], type = "b",
xlab = "Number of clusters k",
ylab = "Calinski–Harabasz Index",
main = "CH Index - Kab/Kota Jabar 2025 (Produk Hewani)")
# k optimal (CH terbesar)
best_k <- which.max(ch)
best_k
## [1] 7
Calinski-Harabasz Index menunjukkan k = 7 sebagai nilai optimal.
library(NbClust)
set.seed(123)
res.ch <- NbClust(X_scaled,
distance = "euclidean",
min.nc = 2, max.nc = 10,
method = "kmeans",
index = "ch")
res.ch$Best.nc
## Number_clusters Value_Index
## 7.0000 18.5578
Menurut NbClust dengan CH Index, k = 7 adalah nilai terbaik.
set.seed(123)
k <- 7
km_7 <- kmeans(X_scaled, centers = k, nstart = 25)
# Lihat ukuran tiap cluster
km_7$size
## [1] 5 3 3 2 5 7 2
# Tambahkan label cluster ke kab/kota
cluster_kabkot_7 <- data.frame(
KabKot = kabkot,
Cluster = factor(km_7$cluster)
)
# Urutkan biar rapi
cluster_kabkot_7 <- cluster_kabkot_7 %>%
arrange(Cluster, KabKot)
cluster_kabkot_7
## KabKot Cluster
## 1 Kab. Ciamis 1
## 2 Kab. Majalengka 1
## 3 Kab. Sumedang 1
## 4 Kota Bekasi 1
## 5 Kota Depok 1
## 6 Kab. Indramayu 2
## 7 Kota Bandung 2
## 8 Kota Tasikmalaya 2
## 9 Kab. Bandung Barat 3
## 10 Kab. Garut 3
## 11 Kota Banjar 3
## 12 Kab. Bekasi 4
## 13 Kab. Pangandaran 4
## 14 Kab. Cianjur 5
## 15 Kab. Karawang 5
## 16 Kab. Subang 5
## 17 Kab. Sukabumi 5
## 18 Kota Cimahi 5
## 19 Kab. Bandung 6
## 20 Kab. Bogor 6
## 21 Kab. Kuningan 6
## 22 Kab. Purwakarta 6
## 23 Kab. Tasikmalaya 6
## 24 Kota Bogor 6
## 25 Kota Sukabumi 6
## 26 Kab. Cirebon 7
## 27 Kota Cirebon 7
table(cluster_kabkot_7$Cluster)
##
## 1 2 3 4 5 6 7
## 5 3 3 2 5 7 2
library(factoextra)
fviz_cluster(
km_7,
data = X_scaled,
geom = "point",
ellipse.type = "norm",
repel = TRUE,
main = "Cluster 7 Kelompok\nKab/Kota Jawa Barat 2025 (Produk Hewani, K-Means)"
) +
theme_minimal()
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
“Berdasarkan grafik PCA, terlihat bahwa pemisahan antar cluster cukup
jelas, terutama pada Dimensi 1 (55.4%) yang menggambarkan tingkat harga
produk hewani secara umum. Kabupaten/kota yang berada di sisi kanan
grafik cenderung memiliki harga daging dan telur yang lebih tinggi, yang
dikelompokkan dalam Cluster 1 dan Cluster 2. Sementara itu, wilayah yang
berada di sisi kiri grafik—yang sebagian besar masuk dalam Cluster 4 dan
Cluster 7—memiliki tingkat harga produk hewani yang lebih rendah.
Dimensi 2 (32.3%) memisahkan kabupaten/kota berdasarkan struktur harga antar komoditas, khususnya perbedaan pola harga antara daging sapi, daging ayam, dan telur ayam ras. Dengan demikian, kombinasi dua dimensi PCA mampu menjelaskan 87.7% keragaman data, menunjukkan bahwa pembentukan tujuh cluster melalui K-Means menghasilkan pengelompokan yang stabil dan terinterpretasi dengan baik.”
profil_cluster_7 <- kab_produk_hewani_jabar %>%
left_join(cluster_kabkot_7, by = "KabKot") %>%
group_by(Cluster) %>%
summarise(across(where(is.numeric), ~ mean(.x, na.rm = TRUE)))
profil_cluster_7
## # A tibble: 7 × 4
## Cluster `Daging Ayam Ras` `Daging Sapi Murni` `Telur Ayam Ras`
## <fct> <dbl> <dbl> <dbl>
## 1 1 39060. 136487. 28442.
## 2 2 35201. 141531. 28230.
## 3 3 32565. 125724. 28052.
## 4 4 40054. 131491. 29363.
## 5 5 35390. 131824. 28781.
## 6 6 35385. 129889. 28135.
## 7 7 31864. 132948. 27428.
library(cluster)
sil_7 <- silhouette(km_7$cluster, dist(X_scaled))
summary(sil_7)
## Silhouette of 27 units in 7 clusters from silhouette.default(x = km_7$cluster, dist = dist(X_scaled)) :
## Cluster sizes and average silhouette widths:
## 5 3 3 2 5 7 2
## 0.4126583 0.3425422 0.4052472 0.1256450 0.2663435 0.3793063 0.4914122
## Individual silhouette widths:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.02807 0.27336 0.38139 0.35288 0.47488 0.61904
library(cluster)
library(factoextra)
set.seed(123)
pam_7 <- pam(X_scaled, k = 7)
table(pam_7$clustering)
##
## 1 2 3 4 5 6 7
## 5 3 6 3 2 3 5
fviz_cluster(
pam_7,
geom = "point",
ellipse.type = "norm",
repel = TRUE,
main = "Clustering K-Medoids (k = 7) - Kab/Kota Jabar 2025"
)
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
# Buat dataframe hasil cluster PAM
cluster_pam_7 <- data.frame(
KabKot = kabkot,
Cluster = factor(pam_7$clustering)
)
# Hitung rata-rata harga produk hewani untuk setiap cluster
profil_cluster_pam7 <- kab_produk_hewani_jabar %>%
left_join(cluster_pam_7, by = "KabKot") %>%
group_by(Cluster) %>%
summarise(across(where(is.numeric), ~ mean(.x, na.rm = TRUE))) %>%
arrange(Cluster)
profil_cluster_pam7
## # A tibble: 7 × 4
## Cluster `Daging Ayam Ras` `Daging Sapi Murni` `Telur Ayam Ras`
## <fct> <dbl> <dbl> <dbl>
## 1 1 35303. 129387. 28061.
## 2 2 32565. 125724. 28052.
## 3 3 39479 135896. 28546.
## 4 4 36079. 130700. 29255.
## 5 5 31864. 132948. 27428.
## 6 6 35201. 141531. 28230.
## 7 7 35685. 131869. 28487.
sil_pam7 <- silhouette(pam_7$clustering, dist(X_scaled))
summary(sil_pam7)
## Silhouette of 27 units in 7 clusters from silhouette.default(x = pam_7$clustering, dist = dist(X_scaled)) :
## Cluster sizes and average silhouette widths:
## 5 3 6 3 2 3 5
## 0.23251163 0.37212633 0.25571152 0.01690787 0.48335611 0.37968385 0.35604491
## Individual silhouette widths:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -0.2184 0.2333 0.3444 0.2870 0.4125 0.5565
library(dplyr)
library(factoextra)
# Silhouette per cluster dari K-Means (k = 7)
sil_km_df <- fviz_silhouette(sil_7)$data %>%
group_by(cluster) %>%
summarise(
size = n(),
ave.sil.width = mean(sil_width)
)
## cluster size ave.sil.width
## 1 1 5 0.41
## 2 2 3 0.34
## 3 3 3 0.41
## 4 4 2 0.13
## 5 5 5 0.27
## 6 6 7 0.38
## 7 7 2 0.49
# Gabungkan dengan profil cluster
tabel_kmeans <- profil_cluster_7 %>%
rename(cluster = Cluster) %>%
left_join(sil_km_df, by = "cluster") %>%
mutate(Metode = "K-Means") %>%
select(Metode, cluster, size, ave.sil.width,
`Daging Ayam Ras`, `Daging Sapi Murni`, `Telur Ayam Ras`)
tabel_kmeans
## # A tibble: 7 × 7
## Metode cluster size ave.sil.width `Daging Ayam Ras` `Daging Sapi Murni`
## <chr> <fct> <int> <dbl> <dbl> <dbl>
## 1 K-Means 1 5 0.413 39060. 136487.
## 2 K-Means 2 3 0.343 35201. 141531.
## 3 K-Means 3 3 0.405 32565. 125724.
## 4 K-Means 4 2 0.126 40054. 131491.
## 5 K-Means 5 5 0.266 35390. 131824.
## 6 K-Means 6 7 0.379 35385. 129889.
## 7 K-Means 7 2 0.491 31864. 132948.
## # ℹ 1 more variable: `Telur Ayam Ras` <dbl>
# Silhouette per cluster dari K-Medoids (k = 7)
sil_pam_df <- fviz_silhouette(sil_pam7)$data %>%
group_by(cluster) %>%
summarise(
size = n(),
ave.sil.width = mean(sil_width)
)
## cluster size ave.sil.width
## 1 1 5 0.23
## 2 2 3 0.37
## 3 3 6 0.26
## 4 4 3 0.02
## 5 5 2 0.48
## 6 6 3 0.38
## 7 7 5 0.36
# Gabungkan dengan profil cluster PAM
tabel_pam <- profil_cluster_pam7 %>%
rename(cluster = Cluster) %>%
left_join(sil_pam_df, by = "cluster") %>%
mutate(Metode = "K-Medoids") %>%
select(Metode, cluster, size, ave.sil.width,
`Daging Ayam Ras`, `Daging Sapi Murni`, `Telur Ayam Ras`)
tabel_pam
## # A tibble: 7 × 7
## Metode cluster size ave.sil.width `Daging Ayam Ras` `Daging Sapi Murni`
## <chr> <fct> <int> <dbl> <dbl> <dbl>
## 1 K-Medoids 1 5 0.233 35303. 129387.
## 2 K-Medoids 2 3 0.372 32565. 125724.
## 3 K-Medoids 3 6 0.256 39479 135896.
## 4 K-Medoids 4 3 0.0169 36079. 130700.
## 5 K-Medoids 5 2 0.483 31864. 132948.
## 6 K-Medoids 6 3 0.380 35201. 141531.
## 7 K-Medoids 7 5 0.356 35685. 131869.
## # ℹ 1 more variable: `Telur Ayam Ras` <dbl>
tabel_perbandingan <- bind_rows(tabel_kmeans, tabel_pam) %>%
arrange(Metode, cluster)
tabel_perbandingan
## # A tibble: 14 × 7
## Metode cluster size ave.sil.width `Daging Ayam Ras` `Daging Sapi Murni`
## <chr> <fct> <int> <dbl> <dbl> <dbl>
## 1 K-Means 1 5 0.413 39060. 136487.
## 2 K-Means 2 3 0.343 35201. 141531.
## 3 K-Means 3 3 0.405 32565. 125724.
## 4 K-Means 4 2 0.126 40054. 131491.
## 5 K-Means 5 5 0.266 35390. 131824.
## 6 K-Means 6 7 0.379 35385. 129889.
## 7 K-Means 7 2 0.491 31864. 132948.
## 8 K-Medoids 1 5 0.233 35303. 129387.
## 9 K-Medoids 2 3 0.372 32565. 125724.
## 10 K-Medoids 3 6 0.256 39479 135896.
## 11 K-Medoids 4 3 0.0169 36079. 130700.
## 12 K-Medoids 5 2 0.483 31864. 132948.
## 13 K-Medoids 6 3 0.380 35201. 141531.
## 14 K-Medoids 7 5 0.356 35685. 131869.
## # ℹ 1 more variable: `Telur Ayam Ras` <dbl>
Berdasarkan hasil perbandingan Silhouette Score:
Metode K-Means menunjukkan kualitas klasterisasi yang lebih baik daripada K-Medoids. K-Means menghasilkan nilai silhouette yang lebih tinggi dan lebih konsisten antar cluster (0.34–0.49). Sedangkan K-Medoids memiliki variasi yang lebih ekstrem, termasuk satu cluster dengan kualitas sangat rendah (0.016).
Hal ini menunjukkan bahwa struktur data harga produk hewani Kabupaten/Kota di Jawa Barat tahun 2025 lebih sesuai dikelompokkan menggunakan algoritma berbasis centroid daripada algoritma berbasis medoid. Oleh karena itu, K-Means dipilih sebagai metode utama dalam penelitian ini.
Hasil clustering (7 cluster) menunjukkan:
Implikasi masalah: Kesenjangan daya beli masyarakat antar kabupaten/kota dan ketidakmerataan distribusi pasokan hewani.
Daging sapi menunjukkan variasi terbesar dibanding ayam dan telur:
Ini mengindikasikan ketidakmerataan distribusi daging sapi, termasuk ongkos logistik berbeda dan perbedaan rantai pasok
Ini mengindikasikan adanya ketidakseimbangan komposisi produksi ternak antar daerah, Pusat produksi telur berbeda dengan pusat produksi ayam atau sapi, dan kebijakan harus dilakukan berdasarkan komoditas, bukan hanya wilayah.