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"
)
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()`).
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.
ggplot(kab_long,
aes(x = KabKot, y = Harga, fill = Produk)) +
geom_col(position = "dodge") + # ganti "stack" kalau mau ditumpuk
coord_flip() +
labs(
title = "Harga komoditas hewani per kabupaten/kota\nJawa Barat",
x = "Kabupaten/Kota",
y = "Harga"
)
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",
x = "Produk",
y = "Rata-rata harga"
)
ggplot(kab_long,
aes(x = Produk, y = Harga)) +
geom_boxplot() +
labs(
title = "Distribusi harga komoditas hewani\nantar kabupaten di Jawa Barat",
x = "Produk",
y = "Harga"
)
ggplot(kab_long,
aes(x = KabKot, y = Harga)) +
geom_boxplot() +
coord_flip() +
labs(
title = "Distribusi harga komoditas hewani\nper kabupaten/kota di Jawa Barat",
x = "Kabupaten/Kota",
y = "Harga"
)
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, # jumlah cluster maksimum yang diuji
B = 100 # jumlah simulasi bootstrap (lebih besar = lebih akurat)
)
# 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 = 7 karena memiliki gap tertinggi
0.08461061.
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.
Cluster 1 : Harga ayam dan telur tinggi, sapi menengah Cluster 2 : Harga daging tertinggi Cluster 3 : Harga paling terendah (ayam dan sapi termurah) Cluster 4 : Harga paling mahal untuk semua produk hewani Cluster 5 : Harga menangah-tinggi (stabil ke arah tinggi) Cluster 6 : Harga menengah (normal) Cluster 7 : Harga telur paling murah, ayam rendah, sapi menengah
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: Ada kelompok wilayah yang konsisten memiliki harga sangat tinggi (Cluster 1, Cluster 2, dan Cluster 4), Ada wilayah dengan harga sangat rendah, dan (Cluster 3 dan sebagian Cluster 7). Ketimpangan harga ini cukup ekstrem, terutama pada daging sapi.
Implikasi masalah: Kesenjangan daya beli masyarakat antar kabupaten/kota dan ketidakmerataan distribusi pasokan hewani.
Daging sapi menunjukkan variasi terbesar dibanding ayam dan telur: Cluster 2 → harga sapi paling tinggi (141 ribu) dan Cluster 3 → harga sapi paling rendah (125 ribu)
Selisih bisa mencapai >15 ribu hanya antar kabupaten/kota
Ini mengindikasikan ketidakmerataan distribusi daging sapi, termasuk ongkos logistik berbeda dan perbedaan rantai pasok
Cluster 3 dan 7 menunjukkan bahwa: - Harga murah tidak berlaku untuk semua komoditas - Ada kabupaten/kota yang hanya murah untuk ayam tapi tidak untuk daging sapi - Atau hanya telur yang sangat murah
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.