Email: zenr.prog@gmail.com
Github: https://github.com/Zen-Rofiqy
️Rpubs: https://rpubs.com/ZenR_Prog/
Kaggle: https://www.kaggle.com/zenrofiqy
Linkedin: https://www.linkedin.com/in/angga-fathan-rofiqy/
Angga Fathan Rofiqy adalah mahasiswa semester 6 di IPB University yang tengah menempuh studi di bidang Statistika. Untuk memenuhi tugas akhir mata kuliah Teknik Pembelajaran Mesin, Angga dan timnya melakukan penelitian berjudul “Perbandingan Metode Clustering dalam Analisis Kesejahteraan di Indonesia tahun 2021: K-Means, Fuzzy C-Means, dan Gaussian Mixture Model (GMM).” Penelitian ini dipublikasikan di RPubs dengan tujuan memberikan bahan pembelajaran yang bermanfaat bagi semua orang.
Kelompok 8 Pararel 2
| Nama | NIM |
|---|---|
| Angga Fathan Rofiqy | G1401211006 |
| Natasha Muti Hafiza | G1401211019 |
| Arfiah Kania Sektiaruni | G1401211023 |
| Naswa Nabila Zahrani | G1401211056 |
| Kamilah Nurul Azizah | G1401211073 |
| Angel Martha Pradina .P. | G1401211105 |
Data untuk analais bisa di dapatkan di data.github dan data kode provinsi ada di kode.github
raw.data <- read.csv("https://raw.githubusercontent.com/Zen-Rofiqy/STA1382-TPM/main/Project/Tugas%20Kelompok/Data.csv")
data <- raw.data # Untuk menjaga data awal
colnames(data) <- c("Prov","X1","X2",'X3','X4','X5','X6','X7')
kode <- import("https://raw.githubusercontent.com/Zen-Rofiqy/STA1382-TPM/main/Project/Tugas%20Kelompok/Kode%20Provinsi.csv")
datatable(raw.data, options = list(pageLength = 5))Cek tipe data
## 'data.frame': 34 obs. of 8 variables:
## $ Provinsi : chr "ACEH" "SUMATERA UTARA" "SUMATERA BARAT" "RIAU" ...
## $ uhh : num 70 69.2 69.6 71.7 71.2 ...
## $ puskesmas : int 363 618 282 238 212 352 185 310 65 92 ...
## $ imun : num 21.6 42.8 42.8 44.6 48.3 ...
## $ tenagamedis: int 2683 5611 2626 2634 1533 2464 787 2392 751 1188 ...
## $ bpjs : num 83.4 32 37.9 27.1 25 ...
## $ sanitasi : num 77.5 82 68.7 83.6 80.4 ...
## $ sumberair : num 88.8 90.9 83.4 89.8 79.7 ...
Cek data hilang
## Provinsi uhh puskesmas imun tenagamedis bpjs
## 0 0 0 0 0 0
## sanitasi sumberair
## 0 0
Tidak ada data hilang pada setiap kolom.
colors <- c("#0f2c3a","#357a87","#6ec1c1","#a9ded7","#9a3b1a","#ce572b","#e9865b")
titles <- c("\nX1 - UHH","\nX2 - Puskesmas","\nX3 - Imun","\nX4 - Tenaga Medis",
"\nX5 - BPJS", "\nX6 - Sanitasi","\nX7 - Sumber Air")
bin <- c(.8, 85, 10, 700, 7, 5, 6)
all_plots <- list()
for (i in 1:(ncol(data)-1) ) {
plots <- list()
# Histogram with density plot
p1 <- ggplot(data, aes(x = data[,1+i] )) +
geom_histogram(aes(y = ..density.., weight=data[,1+i] ),
binwidth = bin[i],
fill = colors[i], color = "black", lwd=1) +
geom_density(color = "black", lwd=2, fill = colors[i], alpha = .5) +
ylab("Density") + theme_void() +
xlab(colnames(data[,1+i])[i])
# Boxplot
p2 <- ggplot(data, aes(y = data[,1+i] )) +
geom_boxplot(fill = colors[i], color = "black",
outlier.size = 3, lwd=1, alpha=.5) +
xlab("Nilai") + theme_set(theme_void() + theme(axis.text.x = element_text())) +
coord_flip()
# Gabung plot
combined_plot <- plot_grid(p1, p2, ncol = 1, align = 'v',
rel_heights = c(1, 0.15))
# Menambahkan judul utama
title <- ggdraw() +
draw_label(titles[i], fontface = 'bold', x = 0.5,
hjust = 0.5, size = 30)
# Menampilkan plot dengan judul utama
plots <-
plot_grid(title, combined_plot, ncol = 1, rel_heights = c(0.1, 1))
all_plots[[i]] <- plots
}
chart <-
plot_grid(plotlist = all_plots, ncol=4)
chart#Export Chart
ggsave("Sebaran Data.png", chart, path = export.chart,
dpi = 300, height = 15, width = 30)Peubah X2, X4, dan X5 menyebar dengan menjulur ke kanan. Ini bisa dilihat dari density plot dan histogram nya yang menjulur ke kanan, serta dengan adanya outlier di sebelah kanan pada boxplotnya. Artinya mayoritas provinsi memiliki nilai yang jauh lebih sedikit daripada provinsi lainnya. Dalam kasus ini nilai yang dimaksud adalah banyaknya puskesmas, tenaga medis, dan persentase penerima BPJS.
Peubah X3, X6, dan X7 menyebar dengan menjulur ke kiri. Ini bisa dilihat dari density plot dan histogram nya yang menjulur ke kiri, serta dengan adanya outlier di sebelah kiri pada boxplotnya. Artinya masih ada beberapa provinsi yang nilai nya tertinggal jauh dari pada kebanyakan provinsi. Dalam kasus ini nilai yang dimaksud adalah Persentase balita sudah imunisasi dasar lengkap, Persentase rumah tangga dengan sanitasi layak, dan Persentase rumah tangga dengan pelayanan sumber air minum layak.
Sedangkan untuk umur harapan hidup nampak hampir simetris jika dilihat dari histogram, density plot dan boxplot nya. Artinya sebaran UHH di setiap provinsi terdistribusi secara merata di sekitar rata-rata, tanpa ada kemenjuluran yang signifikan ke arah tertentu.
# List of variable names (excluding Provinsi and Cluster)
variables <- names(raw.data)[!names(raw.data) %in% c("Provinsi")]
plots <- list()
for (var in variables) {
# Sort data based on the current variable
sorted_data <- raw.data %>%
arrange(!!sym(var)) %>%
mutate(Provinsi = factor(Provinsi, levels = Provinsi))
p <- ggplot(sorted_data, aes_string(x = var, y = "Provinsi")) +
geom_bar(stat = "identity", fill = "#357a87") +
labs(x = var, y = "Provinsi") +
theme_minimal()
plots[[var]] <- p
}
combined_plot <- plot_grid(plotlist = plots, ncol = 4)
combined_plot#Export Chart
ggsave("Bar Chart.png", combined_plot, path = export.chart,
dpi = 300, height = 15, width = 30)Untuk sebaran lebih detail nya seperti ini. Bisa dilihat bahwa selaras dengan yang sudah diinterpretasikan di plot sebelumnya, bahwa UHH hampir menyebar simetris, lalu X2, X4, dan X5 menyebar dengan menjulur ke kanan yang ditandai banyaknya bar yang kecil, lalu terakhir X3, X6, dan X7 menyebar dengan menjulur ke kiri yang ditandai dengan ada beberapa bar yang ukurannya lebih kecil dari mayoritas.
# Standarisasi Data
dt <- scale(data[,-1])
# Korelasi
pairs.panels(dt,
method = "pearson", # correlation method
hist.col = "#357a87", #Coloring histogram
density = TRUE, # show density plots
ellipses = TRUE, # show correlation ellipses
smooth = TRUE, #show loess smooths
pch = 20, #Scatter = cirlce / dot
rug = TRUE, #Rug under histogram
stars = TRUE #Significance of corr
)Jika kita melihat dari scatterplotnya, maka kita akan melihat bahwa pola hubungan antar peubah itu beragam, ada yang memilki hubungan linear ada juga yang nampaknya tidak meiliki hubungan linear. Jika dihitung hubungan linearnya dengan korelasi pearson, maka kita bisa melihat bahwa mayoritas hubungan antarr peubahnya itu lemah. Hubungan lineaer yang paling kuat adalah hubungan antara peubah X2 dan X4 dengan nilai 0.78. Bisa dilihat juga dari scatterplitnya yang memilki pola lurus positif. Ini didukung dnegan garis LOESS Smooth nya yang paling lurus dan paling 45 derajat diantara yang lain. Juga dari bentuk elips korelasinya yang nampak lancip nan bersudut 45 derajat. Yang mana ini tentu make sense karena Jumlah Puskesmas selaras dengan juumlah tenaga medis yang ada.
CekVIF <- function(data) {
corr = as.matrix(cor(data))
VIF = diag(solve(corr))
return(VIF)
}
CekVIF(data[,-1])## X1 X2 X3 X4 X5 X6 X7
## 2.027411 3.895705 1.356273 4.427064 1.131544 2.935106 1.892231
Pada setiap variabel tidak ada yang memiliki nilai VIF > 10 sehingga antar variabel tidak terjadi multikolinearitas.
Pemilihan banyak culster
Pada dasarnya nilai k optimum dapat ditentukan sendiri oleh peneliti, selain itu nilai k dapat ditentukan juga menggunakan bantuan nilai dari setiap sebaran gaussian yang dihasilkan dan dilihat mana yang memiliki nilai BIC terbesar. Tak harus melihat nilai dari sebarannya, ini juga bisa dibuat plot agar mudah untuk menentukan mana jumlah cluster yang optimal.
## Bayesian Information Criterion (BIC):
## EII VII EEI VEI EVI VVI EEE
## 1 -696.5206 -696.5206 -717.6788 -717.6788 -717.6788 -717.6788 -688.7975
## 2 -678.3782 -691.6535 -651.8682 -709.7373 -659.3102 -719.7595 -695.5856
## 3 -684.8992 -672.6377 -677.8125 -669.9904 -654.0443 -696.2913 -685.1682
## 4 -685.5860 -669.0659 -689.8244 -646.4406 -688.4053 -696.4109 -695.3764
## 5 -695.5070 -669.6889 -693.1522 -664.2876 -694.5112 -683.8182 -708.9387
## 6 -705.1183 -667.5226 -708.6766 -679.6809 -667.3445 -712.4262 -723.7749
## 7 -658.4365 NA -670.1641 NA NA NA -697.2630
## 8 -648.0953 NA -646.6228 NA NA NA -659.2519
## 9 -661.2521 NA -650.3789 NA NA NA -682.3787
## VEE EVE VVE EEV VEV EVV VVV
## 1 -688.7975 -688.7975 -688.7975 -688.7975 -688.7975 -688.7975 -688.7975
## 2 -683.4840 -633.3132 -683.4810 -664.2698 -717.8221 -742.4286 -715.2660
## 3 NA NA NA -729.0026 -739.9755 NA NA
## 4 NA NA NA -834.7233 -764.4534 NA NA
## 5 NA NA NA -858.6840 -797.5165 NA NA
## 6 NA NA NA -801.6111 -740.7355 NA NA
## 7 NA NA NA -889.6800 NA NA NA
## 8 NA NA NA NA NA NA NA
## 9 NA NA NA NA NA NA NA
##
## Top 3 models based on the BIC criterion:
## EVE,2 VEI,4 EEI,8
## -633.3132 -646.4406 -646.6228
## Optimal number of clusters: 2
Juumlah culster optimal adalah 2, ini bisa dilihat dengan mncari titik dengan nilai BIC terbesar. Dalam kasus ini niali BIC terbesar adalah model EVE dengan jumlah komponen 2.
Summary Jumlah Cluster optimal
## ----------------------------------------------------
## Gaussian finite mixture model fitted by EM algorithm
## ----------------------------------------------------
##
## Mclust EVE (ellipsoidal, equal volume and orientation) model with 2 components:
##
## log-likelihood n df BIC ICL
## -230.2607 34 49 -633.3132 -633.6239
##
## Clustering table:
## 1 2
## 8 26
##
## Mixing probabilities:
## 1 2
## 0.2371723 0.7628277
##
## Means:
## [,1] [,2]
## X1 0.1144555 -0.03558557
## X2 1.0713155 -0.33308480
## X3 -0.3672036 0.11416799
## X4 1.0983322 -0.34148459
## X5 0.6390915 -0.19870118
## X6 -0.3399775 0.10570305
## X7 0.1613344 -0.05016080
##
## Variances:
## [,,1]
## X1 X2 X3 X4 X5 X6 X7
## X1 1.1966799 0.5396505 0.3526419 0.7200114 0.2609832 1.0641955 1.0539213
## X2 0.5396505 1.6567542 0.2596593 0.6619644 -1.0051928 -0.5272227 0.1763555
## X3 0.3526419 0.2596593 2.4694787 0.3673152 -1.1227186 1.2063338 0.4237561
## X4 0.7200114 0.6619644 0.3673152 1.0466275 -0.2464518 0.3670720 0.6283520
## X5 0.2609832 -1.0051928 -1.1227186 -0.2464518 1.7777280 0.9367601 0.5730257
## X6 1.0641955 -0.5272227 1.2063338 0.3670720 0.9367601 2.7662602 1.6061668
## X7 1.0539213 0.1763555 0.4237561 0.6283520 0.5730257 1.6061668 1.2603627
## [,,2]
## X1 X2 X3 X4 X5 X6
## X1 0.60395032 -0.02468338 0.074122367 0.083040279 0.04273550 0.17955786
## X2 -0.02468338 0.32662187 -0.053175085 0.182971337 0.11459858 -0.02550871
## X3 0.07412237 -0.05317508 0.549237732 -0.007011136 0.16691270 0.19222887
## X4 0.08304028 0.18297134 -0.007011136 0.201864312 0.07161786 0.19500003
## X5 0.04273550 0.11459858 0.166912696 0.071617863 0.44924615 0.01653687
## X6 0.17955786 -0.02550871 0.192228868 0.195000033 0.01653687 0.83416164
## X7 0.10548568 -0.02111411 0.129677631 0.082658961 0.02383007 0.17123913
## X7
## X1 0.10548568
## X2 -0.02111411
## X3 0.12967763
## X4 0.08265896
## X5 0.02383007
## X6 0.17123913
## X7 0.71452709
Proporsi cluster
# Menghitung frekuensi observasi di setiap kluster
cluster_frequencies <- table(gmm_model2$classification)
# Mengurutkan kluster berdasarkan frekuensinya
sorted_clusters <- names(sort(cluster_frequencies, decreasing = TRUE))
# Membuat urutan kluster yang diinginkan (1, 2, 3, 4, 5)
new_order <- 1:length(sorted_clusters)
# Menukar isi kluster dengan urutan yang dihasilkan
gmm_model2$classification <- recode(gmm_model2$classification,
!!!setNames(as.character(new_order), sorted_clusters))
table(gmm_model2$classification)##
## 1 2
## 26 8
Proporsi jumlah cluster 1 dan 2 adalah 26 : 8.
Plot culster
colors <- c("1" = "#d3a83c", "2" = "#4fbaa9")
chart <-
fviz_cluster(gmm_model2, data = dt, repel = TRUE, labelsize =8) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartTerlihat bahwa GMM tidak membuat cluster berdararkan kedekatan titik, melainkan berdasarkan sebaran berbagai sebaran gaussian.
data.clust1 <- cbind(dt %>% as.data.frame() %>% mutate(across(everything(), as.numeric)),
Cluster = gmm_model2[["classification"]])
# Calculate the mean of each variable for each cluster
cluster_profiles1 <- aggregate(. ~ Cluster, data.clust1, mean)
# Print the cluster profiles
print(cluster_profiles1)## Cluster X1 X2 X3 X4 X5 X6
## 1 1 -0.04121201 -0.3346306 0.1121178 -0.3430521 -0.1977580 0.1031076
## 2 2 0.13393902 1.0875495 -0.3643828 1.1149194 0.6427135 -0.3350998
## X7
## 1 -0.05254404
## 2 0.17076813
# Convert the data to long format for plotting
cluster_profiles_long1 <- tidyr::pivot_longer(cluster_profiles1, -Cluster,
names_to = "Variable", values_to = "Value")
# Create the bar plot
chart <-
ggplot(cluster_profiles_long1, aes(x = Cluster, y = Value, fill = Variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(x = "Cluster", y = "Mean Value", fill = "Variable") +
theme_minimal() +
ggtitle("Cluster Profiles") +
scale_fill_brewer(palette = "GnBu")
chartTerlihat dari nilai yang sudah distandarisasi bahwa profil dari cuslter 2 memilki nilai yang hampir unggul dalam segala peubah dibandingan dengan cluster 1. Notes: adanya nilai negatif karena hasil dari standarisasi memang mengandung nilai positif dan negatif. Agar mudah perbandingannya, mari kita lihat dengan diagram spider web dibawah ini.
data.akhir1 <- cbind(raw.data, Cluster = gmm_model2[["classification"]]) %>%
relocate(Cluster, .before = 2)
# Radar Plot
chart <-
ggRadar(
data = data.akhir1,
mapping = aes(colours = Cluster)
) +
theme_light() +
theme(
text = element_text(size = 10), # Mengubah ukuran font global
title = element_text(size = 12), # Mengubah ukuran font judul
axis.text = element_text(size = 10), # Mengubah ukuran font label sumbu
legend.text = element_text(size = 8) # Mengubah ukuran font legenda
) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartSelaras dengan yang sudah saya sampaikan diatas, bahwa cluster 2 hampir unggul dalam segala aspek. Cluster 1 hanya bisa dunggul dalam sanitasi dan imun saja, sedangkan yang lainnya tidak mampu mengungguli atau bahkan tidak ada harapan untuk mengungguli cluster 2.
indo <- st_read(dsn= "C:/Users/Fathan/Documents/Obsidian Vault/2. Kuliah/Smt 5/8. Pengantar Sains Data/Tugas/Tugas Akhir/SHP Indonesia/prov.shp",
quiet = TRUE)data.map <- cbind(data.clust1, KODE=kode$KODE)
data.indo <- indo %>%
inner_join(data.map, by = c("KODE" = "KODE"))
chart <-
ggplot() +
geom_sf(data=data.indo, aes(fill=factor(`Cluster`))) +
scale_fill_manual(values=c("1" = "#e0c377", "2" = "#80cdc0"),
name = "Keterangan") +
labs(title = "GMM Clustering - Kesejahteraan \n pada Provinsi Indonesia 2021",
x = "Longitude",
y = "Latitude") +
theme_minimal() +
theme(legend.text = element_text(size=10),
legend.title = element_text(size=10, face="bold"),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size=12, face="bold", hjust = 0.5)) +
scale_x_continuous(labels = function(x) paste0(x, "°")) +
scale_y_continuous(labels = function(y) paste0(y, "°"))
chartAda yang aneh? ya memang. Kenapa bisa provinsi papua masuk kedalam cluster 2 yang sebelumnya disebut-sebut sebagai cluster yang unggul dalam segala aspek kesejahteraan. Mari kita telurusi lebih lanjut.
Tampilan Data dengan cluster
Jika anda ingin melihat bagaimana tampilan data dengan cluster nya. Atau lebih mudah dengan bar chart dibawah.
colors1 <- c("1" = "#e7dec5", "2" = "#7dcdc0")
# List of variable names (excluding Provinsi and Cluster)
variables <- names(data.akhir1)[!names(data.akhir1) %in% c("Provinsi", "Cluster")]
plots <- list()
for (var in variables) {
# Sort data based on the current variable
sorted_data <- data.akhir1 %>%
arrange(!!sym(var)) %>%
mutate(Provinsi = factor(Provinsi, levels = Provinsi))
p <- ggplot(sorted_data, aes_string(x = var, y = "Provinsi", fill = "factor(Cluster)")) +
geom_bar(stat = "identity") +
scale_fill_manual(values = colors1) +
labs(x = var, y = "Provinsi", fill = "Cluster") +
theme_minimal()
plots[[var]] <- p
}
combined_plot <- plot_grid(plotlist = plots, ncol = 4)
combined_plot# Eksport
ggsave("GMM Dist.png", combined_plot, path = export.chart,
dpi = 300, height = 15, width = 30)Memang terlihat keanehannya, bahwa salah satu anggota cluster 2 tidak bisa meungguli semua aspek kesejahteraan yang ada. Bahwakan kalah jauh daripada yang lain. Sepertinya memang clustering dengan GMM bukanlah ide yang tepat.
Menentukan jumlah klaster paling optimum untuk membagi 34 provinsi yang ada di Indonesia. Pada dasarnya nilai k optimum dapat ditentukan sendiri oleh peneliti, selain itu nilai k dapat ditentukan juga menggunakan bantuan grafik Elbow berikut. Dimana k minimum akan didapat ketika grafik sudah tidak bergerak menurun dengan tajam.
Dari hasil diatas didapatkan nilai K optimum adalah 2.
#calculate gap statistic for each number of clusters (up to 10 clusters)
gap_stat <- clusGap(dt, FUN = hcut, nstart = 25, K.max = 10, B = 50)
#produce plot of clusters vs. gap statistic
fviz_gap_stat(gap_stat)Dari hasil diatas didapatkan nilai K optimum adalah 1.
Untuk wss nampaknya agak sulit untuk melihat berapa jumlah cluster yang optimumnya, namun nampaknya 6 atau 2 merupakan jumlah cluster optimumnya.
## *** : The Hubert index is a graphical method of determining the number of clusters.
## In the plot of Hubert index, we seek a significant knee that corresponds to a
## significant increase of the value of the measure i.e the significant peak in Hubert
## index second differences plot.
##
## *** : The D index is a graphical method of determining the number of clusters.
## In the plot of D index, we seek a significant knee (the significant peak in Dindex
## second differences plot) that corresponds to a significant increase of the value of
## the measure.
##
## *******************************************************************
## * Among all indices:
## * 8 proposed 2 as the best number of clusters
## * 5 proposed 3 as the best number of clusters
## * 2 proposed 4 as the best number of clusters
## * 3 proposed 5 as the best number of clusters
## * 1 proposed 6 as the best number of clusters
## * 4 proposed 14 as the best number of clusters
## * 1 proposed 15 as the best number of clusters
##
## ***** Conclusion *****
##
## * According to the majority rule, the best number of clusters is 2
##
##
## *******************************************************************
Untuk hubert statistic dan dindex, jumlah cluster optimal yang disarankan adalah 2.
Beberapa metode untuk menentukan jumlah cluster memiliki jumlah cluster optimal yang cukup beragam. Namun 2 merupakan jumlah cluster yang nampaknya bisa diterima oleh semua metode yang ada. Sehingga jumlah cluster yang akan dicobakan adalah 2.
Mari kita tambahkan paramter nstart = 6 untuk menentukan
jumlah awalisasi acak yang akan dilakukan oleh algoritma K-means.
K-means adalah algoritma yang sensitif terhadap titik awal centroid yang
dipilih secara acak. Untuk mengurangi kemungkinan menemukan solusi yang
hanya merupakan minimum lokal (bukan global), sering kali beberapa
awalizasi acak dilakukan, dan hasil dengan total inersia (atau sum of
squared distances from points to their assigned cluster centroids)
terkecil dipilih sebagai hasil akhir.
set.seed(100)
data_kmeans <- eclust(dt, "kmeans", k = 2,
nstart = 6, graph = FALSE)
chart <-
fviz_cluster(object = data_kmeans, data=dt) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartProporsi cluster
##
## 1 2
## 30 4
Proporsi jumlah cluster 1 dan 2 adalah 30 : 4.
Silhouette
## cluster size ave.sil.width
## 1 1 30 0.39
## 2 2 4 0.41
Terlihat bahwa sudah tidak ada pengamatan dengan niali siluet negatif, sehingga seluruh pengamatan dikelompokkan secara tidak benar sudah kemunkinannya sudah kecil.
data.clust2 <- cbind(dt %>% as.data.frame() %>% mutate(across(everything(), as.numeric)),
Cluster = data_kmeans$cluster)
# Calculate the mean of each variable for each cluster
cluster_profiles2 <- aggregate(. ~ Cluster, data.clust2, mean)
# Print the cluster profiles
print(cluster_profiles2)## Cluster X1 X2 X3 X4 X5 X6
## 1 1 -0.1524433 -0.2679779 -0.04791201 -0.3412296 -0.009305985 -0.02421519
## 2 2 1.1433248 2.0098344 0.35934005 2.5592220 0.069794888 0.18161395
## X7
## 1 -0.138005
## 2 1.035037
# Convert the data to long format for plotting
cluster_profiles_long2 <- tidyr::pivot_longer(cluster_profiles2, -Cluster,
names_to = "Variable", values_to = "Value")
# Create the bar plot
chart <-
ggplot(cluster_profiles_long2, aes(x = Cluster, y = Value, fill = Variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(x = "Cluster", y = "Mean Value", fill = "Variable") +
theme_minimal() +
ggtitle("Cluster Profiles") +
scale_fill_brewer(palette = "GnBu")
chartBerlainan dengan hasil dari GMM, cluster 2 merupakan cluster dengan aspek kesejahteraan yang paling tinggi dibandingkan dengan cluster 1. Benar-benar unggul semua. Mari kita lihat lebih jelas dengan radar chart dibawah.
data.akhir2 <- cbind(raw.data, Cluster = data_kmeans$cluster) %>%
relocate(Cluster, .before = 2)
colors <- c("1" = "#e0c377", "2" = "#7dcdc0")
# Radar Plot
chart <-
ggRadar(
data = data.akhir2,
mapping = aes(colours = Cluster)
) +
theme_light() +
theme(
text = element_text(size = 10), # Mengubah ukuran font global
title = element_text(size = 12), # Mengubah ukuran font judul
axis.text = element_text(size = 10), # Mengubah ukuran font label sumbu
legend.text = element_text(size = 8) # Mengubah ukuran font legenda
) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chart# Eksport
ggsave("Kmeans Radar.png", chart, path = export.chart,
dpi = 300, height = 10, width = 10)Sejalan dengan yang saya bilang diatas, bahwa cluster 2 benar-benar mengungguli cluster 1.
data.map <- cbind(data.clust2, KODE=kode$KODE)
data.indo <- indo %>%
inner_join(data.map, by = c("KODE" = "KODE"))
chart <-
ggplot() +
geom_sf(data=data.indo, aes(fill=factor(`Cluster`))) +
scale_fill_manual(values=c("1" = "#e0c377", "2" = "#80cdc0"),
name = "Keterangan") +
labs(title = "K-means Clustering - Kesejahteraan \n pada Provinsi Indonesia 2021",
x = "Longitude",
y = "Latitude") +
theme_minimal() +
theme(legend.text = element_text(size=10),
legend.title = element_text(size=10, face="bold"),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size=12, face="bold", hjust = 0.5)) +
scale_x_continuous(labels = function(x) paste0(x, "°")) +
scale_y_continuous(labels = function(y) paste0(y, "°"))
chartBerbeda dengan GMM, hasil dari k-means itu lebih make sense, mari kita lihat keanggotaan clusternya.
Tampilan Data dengan cluster
# List of variable names (excluding Provinsi and Cluster)
variables <- names(data.akhir2)[!names(data.akhir2) %in% c("Provinsi", "Cluster")]
plots <- list()
for (var in variables) {
# Sort data based on the current variable
sorted_data <- data.akhir2 %>%
arrange(!!sym(var)) %>%
mutate(Provinsi = factor(Provinsi, levels = Provinsi))
p <- ggplot(sorted_data, aes_string(x = var, y = "Provinsi", fill = "factor(Cluster)")) +
geom_bar(stat = "identity") +
scale_fill_manual(values = colors1) +
labs(x = var, y = "Provinsi", fill = "Cluster") +
theme_minimal()
plots[[var]] <- p
}
combined_plot <- plot_grid(plotlist = plots, ncol = 4)
combined_plot# Eksport
ggsave("Kmeans Dist.png", combined_plot, path = export.chart,
dpi = 300, height = 15, width = 30)Bisa dilihat bahwa memang K-Means menghasilkan cluster yang lebih make sense daripada GMM. Karena hampir di semua aspek memang cluster 1 lebih unggul daripada cluster 2.
Untuk FCM pemilihan jumlah clusternya sama dengan K-Means, sehingga jumlah cluster yang akan digunakan adalah 2.
# clustering menggunakan fanny()
data_fcm <- fanny(x = dt, k = 2, metric = "euclidean")
chart <-
fviz_cluster(object = data_fcm, data=dt) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartProporsi Cluster
##
## 1 2
## 16 18
Berbeda dengan 2 metode sebelumnya, FCM menghasilkan proporsi jumlah cluster yang berbeda, yakni lebih proporsional antar clusternya yakni 16 : 18.
Dunn Index
## dunn_coeff normalized
## 5.000000e-01 1.998401e-15
Nilai Dunn index yang kita peroleh sebesar 0.5, sangat kecil tbh. Untuk mengetahui hasil cluster yang kita bentuk sudah baik berdasarkan nilai Dunn index yaitu dengan mendapatkan Dunn index yang semakin besar.
Kita perlu mengetahui berapa banyak cluster yang terbentuk dari nilai derajat keanggotaan yang ada.
Pengelompokkan
## [1] 1 2
Dari hasil pengelompokan menjadi 2 kelompok, ternyata 2 kelompok tersebut berhasil terisi. Artinya bahwa dengan menggunakan k=2, fuzzy c-means mampu menseparasikan data berdasarkan 2 kelompok yang berbeda. Sehingga juumlah cluster 2 merupakan jumlah cluster yang sudah tepat.
Silhouette
## cluster size ave.sil.width
## 1 1 16 0.03
## 2 2 18 0.31
Karena pengamatan dengan nilai siluet negatif yang dapat dilihat pada cluster 1 yang berwarna biru pada plot mengindikasikan bahwa pengamatan tersebut mungkin dikelompokkan secara tidak benar. Mari lihat angka indeks dari pengamatan tersebut.
## [1] "KEPULAUAN RIAU" "DKI JAKARTA" "JAWA BARAT" "JAWA TENGAH"
## [5] "D I YOGYAKARTA" "JAWA TIMUR" "BANTEN"
Terlihat bahwa 7 provinsi tersebut merupakan provinsi yang mungkin blm dapat dikelompokkan secara benar oleh FCM. Mari kita perbaiki.
data_fcm <- fanny(x = dt, k = 2, metric = "manhattan", memb.exp = 3)
chart <-
fviz_cluster(object = data_fcm, data=dt) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartProporsi Cluster
##
## 1 2
## 19 15
Berbeda dengan 2 metode sebelumnya, FCM menghasilkan proporsi jumlah cluster yang berbeda, yakni lebih proporsional antar clusternya yakni 19 : 15.
Dunn Index
## dunn_coeff normalized
## 0.5 0.0
Nilai Dunn index yang kita peroleh masih sebesar 0.5.
Dari hasil pengelompokan menjadi 2 kelompok, ternyata 2 kelompok tersebut berhasil terisi. Artinya bahwa dengan menggunakan k=2, fuzzy c-means mampu menseparasikan data berdasarkan 2 kelompok yang berbeda. Sehingga juumlah cluster 2 merupakan jumlah cluster yang sudah tepat.
Kita perlu mengetahui berapa banyak cluster yang terbentuk dari nilai derajat keanggotaan yang ada.
Pengelompokkan
## [1] 1 2
Dari hasil pengelompokan menjadi 2 kelompok, ternyata 2 kelompok tersebut berhasil terisi. Artinya bahwa dengan menggunakan k=2, fuzzy c-means mampu menseparasikan data berdasarkan 2 kelompok yang berbeda. Sehingga juumlah cluster 2 merupakan jumlah cluster yang sudah tepat.
## cluster size ave.sil.width
## 1 1 19 0.27
## 2 2 15 0.14
Masih ada pengamatan dengan nilai siluet negatif yang dapat dilihat pada cluster 1 yang berwarna kuning pada plot mengindikasikan bahwa pengamatan tersebut mungkin dikelompokkan secara tidak benar. Mari lihat angka indeks dari pengamatan tersebut.
## [1] "MALUKU UTARA" "PAPUA BARAT" "PAPUA"
Terlihat bahwa 3 provinsi tersebut merupakan provinsi yang mungkin blm dapat dikelompokkan secara benar oleh FCM. Namun saya rasa, saya sudah mencoba berbagai hal untuk memperbaikinya, dan ini adalah hasil terbaik dari FCM. Jadi ya, kita sudahi.
data.clust3 <- cbind(dt %>% as.data.frame() %>% mutate(across(everything(), as.numeric)),
Cluster = data_fcm$cluster)
# Calculate the mean of each variable for each cluster
cluster_profiles3 <- aggregate(. ~ Cluster, data.clust3, mean)
# Print the cluster profiles
print(cluster_profiles3)## Cluster X1 X2 X3 X4 X5 X6
## 1 1 -0.4986192 -0.1677914 -0.5238502 -0.3578339 -0.1385835 -0.4146049
## 2 2 0.6315843 0.2125358 0.6635436 0.4532563 0.1755392 0.5251663
## X7
## 1 -0.5125450
## 2 0.6492236
# Convert the data to long format for plotting
cluster_profiles_long3 <- tidyr::pivot_longer(cluster_profiles3, -Cluster,
names_to = "Variable", values_to = "Value")
# Create the bar plot
chart <-
ggplot(cluster_profiles_long3, aes(x = Cluster, y = Value, fill = Variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(x = "Cluster", y = "Mean Value", fill = "Variable") +
theme_minimal() +
ggtitle("Cluster Profiles") +
scale_fill_brewer(palette = "GnBu")
chartDari sini kita tahu bahwa cluster 1 dan cluster 2 cenderung memiliki bentuk bar yang mirip namun kebalik. Tidak tahu pasti apa artinya, namun cluster 2 merupakan cluster yang lebih unggul dalam segala aspek daripada cluster 1. Mari kita lihat radar chart nya.
data.akhir3 <- cbind(raw.data, Cluster = data_fcm$cluster) %>%
relocate(Cluster, .before = 2)
# Radar Plot
chart <-
ggRadar(
data = data.akhir3,
mapping = aes(colours = Cluster)
) +
theme_light() +
theme(
text = element_text(size = 10), # Mengubah ukuran font global
title = element_text(size = 12), # Mengubah ukuran font judul
axis.text = element_text(size = 10), # Mengubah ukuran font label sumbu
legend.text = element_text(size = 8) # Mengubah ukuran font legenda
) +
scale_colour_manual(values = colors) +
scale_fill_manual(values = colors)
chartSelaras dengan yang saya sampaikan di atas, bawahwa cluster 1 dan cluster 2 memang mirip, namun cluster 2 memiliki nilai yang lebih besar daripada cluster 1.
data.map <- cbind(data.clust3, KODE=kode$KODE)
data.indo <- indo %>%
inner_join(data.map, by = c("KODE" = "KODE"))
chart <-
ggplot() +
geom_sf(data=data.indo, aes(fill=factor(`Cluster`))) +
scale_fill_manual(values=c("1" = "#e0c377", "2" = "#80cdc0"),
name = "Keterangan") +
labs(title = "FCM Clustering - Kesejahteraan \n pada Provinsi Indonesia 2021",
x = "Longitude",
y = "Latitude") +
theme_minimal() +
theme(legend.text = element_text(size=10),
legend.title = element_text(size=10, face="bold"),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size=12, face="bold", hjust = 0.5)) +
scale_x_continuous(labels = function(x) paste0(x, "°")) +
scale_y_continuous(labels = function(y) paste0(y, "°"))
chartBeginilah penampakan dari hasil clustering FCM. Apakah lebih bagus daripada metode yang lain? Mari kita pastikan dengan melihat keanggotaan clusternya.
Tampilan Data dengan cluster
# List of variable names (excluding Provinsi and Cluster)
variables <- names(data.akhir3)[!names(data.akhir3) %in% c("Provinsi", "Cluster")]
plots <- list()
for (var in variables) {
# Sort data based on the current variable
sorted_data <- data.akhir3 %>%
arrange(!!sym(var)) %>%
mutate(Provinsi = factor(Provinsi, levels = Provinsi))
p <- ggplot(sorted_data, aes_string(x = var, y = "Provinsi", fill = "factor(Cluster)")) +
geom_bar(stat = "identity") +
scale_fill_manual(values = colors1) +
labs(x = var, y = "Provinsi", fill = "Cluster") +
theme_minimal()
plots[[var]] <- p
}
combined_plot <- plot_grid(plotlist = plots, ncol = 4)
combined_plot# Eksport
ggsave("FCM Dist.png", combined_plot, path = export.chart,
dpi = 300, height = 15, width = 30)Walaupun dalam validasi cluster dengan metode siluet masih ada yang bernilai negatif, namun saya rasa metode FCM mampu membuat cluster yang jauh lebih baik daripada yang lainnya. Tidak seperti K-means yang pada profil nya seolah berkata bahwa cluster 2 itu jauh lebih baik daripada cluster 1 di segala aspek. Namun pada saat kita tampilkan sebaran tiap peubah pada semua provinsi nya, cluster 2 tidak selalu berada di puncak.
Sedangkan untuk FCM itu sesuai dengan apa yang dikatakan oleh profil nya. Yakni clsuter 1 dan cluster 2 itu mirip, namun cluster 2 lebih tinggi daripada cluster 1. Ini juga sesuai dengan sebaran yang kita lihat di atas.