#install.packages("meanShiftR")
library(dbscan)
## Warning: package 'dbscan' was built under R version 4.5.3
##
## Attaching package: 'dbscan'
## The following object is masked from 'package:stats':
##
## as.dendrogram
library(ggplot2)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.5.3
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/en/product/practical-guide-to-principal-component-methods-in-r/
library(cluster)
## Warning: package 'cluster' was built under R version 4.5.3
library(meanShiftR)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.3
## corrplot 0.95 loaded
library(e1071)
## Warning: package 'e1071' was built under R version 4.5.3
##
## Attaching package: 'e1071'
## The following object is masked from 'package:ggplot2':
##
## element
library(fclust)
## Warning: package 'fclust' was built under R version 4.5.3
## Registered S3 method overwritten by 'fclust':
## method from
## print.fclust e1071
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.5.3
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.5.3
library(moments)
##
## Attaching package: 'moments'
## The following objects are masked from 'package:e1071':
##
## kurtosis, moment, skewness
library(hopkins)
## Warning: package 'hopkins' was built under R version 4.5.3
library(clustertend)
## Package `clustertend` is deprecated. Use package `hopkins` instead.
##
## Attaching package: 'clustertend'
## The following object is masked from 'package:hopkins':
##
## hopkins
library(kableExtra)
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
cat("✓ Semua library berhasil di-load\n")
## ✓ Semua library berhasil di-load
Pada tahap ini, seluruh package yang dibutuhkan untuk analisis
clustering, mencakup dbscan untuk metode DBSCAN,
meanShiftR untuk Mean Shift, fclust untuk
Fuzzy C-Means, cluster dan factoextra untuk
evaluasi clustering, serta berbagai package pendukung visualisasi dan
statistik seperti ggplot2, corrplot,
moments, dan hopkins. # Load Dataset
df <- read.csv("AI_Developer_Performance_Extended_1000.csv",
stringsAsFactors = FALSE)
cat("INFORMASI DATASET\n")
## INFORMASI DATASET
cat("Jumlah baris :", nrow(df), "\n")
## Jumlah baris : 1000
cat("Jumlah kolom :", ncol(df), "\n")
## Jumlah kolom : 13
cat("Tipe variabel : semua numerik\n\n")
## Tipe variabel : semua numerik
str(df)
## 'data.frame': 1000 obs. of 13 variables:
## $ Hours_Coding : int 7 4 11 8 5 7 10 3 7 11 ...
## $ Lines_of_Code : int 416 269 439 472 265 196 516 234 440 297 ...
## $ Bugs_Found : int 9 16 3 15 19 14 4 5 16 0 ...
## $ Bugs_Fixed : int 7 13 0 9 16 12 3 1 13 0 ...
## $ AI_Usage_Hours : int 6 5 2 4 5 0 6 6 6 0 ...
## $ Sleep_Hours : num 5.9 5.1 6.2 4.2 8.1 8.1 6.9 5.8 8 6.8 ...
## $ Cognitive_Load : int 92 85 38 26 82 61 61 78 39 92 ...
## $ Task_Success_Rate : int 34 36 79 94 33 39 56 40 75 30 ...
## $ Coffee_Intake : int 7 2 2 5 6 1 0 2 3 0 ...
## $ Stress_Level : int 99 100 55 30 82 72 66 86 43 100 ...
## $ Task_Duration_Hours: num 10.5 9.5 18.3 12.6 7 6.4 5.1 2.9 10.6 13.9 ...
## $ Commits : int 20 17 35 28 25 21 16 15 20 11 ...
## $ Errors : int 3 8 2 4 9 8 5 2 9 8 ...
Dataset yang digunakan adalah AI Developer Performance Extended yang berisi 1000 baris data developer dengan 13 variabel numerik. Seluruh variabel bertipe numerik sehingga tidak diperlukan proses encoding kategorik. Dataset ini berisi performa dan perilaku kerja developer seperti jam coding, tingkat stres, keberhasilan tugas, dan penggunaan AI tool.
num_cols <- colnames(df)
cat("STATISTIK DESKRIPTIF\n")
## STATISTIK DESKRIPTIF
desc_stats <- data.frame(
Variabel = num_cols,
Min = round(sapply(df, min), 2),
Q1 = round(sapply(df, quantile, 0.25), 2),
Median = round(sapply(df, median), 2),
Mean = round(sapply(df, mean), 2),
Q3 = round(sapply(df, quantile, 0.75), 2),
Max = round(sapply(df, max), 2),
Std = round(sapply(df, sd), 2)
)
print(desc_stats, row.names = FALSE)
## Variabel Min Q1 Median Mean Q3 Max Std
## Hours_Coding 1.0 3.0 6.00 5.84 9.0 11.0 3.16
## Lines_of_Code 26.0 209.5 332.00 356.23 480.5 993.0 188.16
## Bugs_Found 0.0 5.0 10.00 9.88 15.0 19.0 5.80
## Bugs_Fixed 0.0 2.0 7.00 7.15 12.0 19.0 5.47
## AI_Usage_Hours 0.0 1.0 3.00 2.96 5.0 6.0 2.02
## Sleep_Hours 4.0 5.2 6.40 6.47 7.7 9.0 1.44
## Cognitive_Load 20.0 38.0 57.00 56.93 76.0 94.0 21.77
## Task_Success_Rate 30.0 37.0 55.50 56.58 74.0 100.0 20.81
## Coffee_Intake 0.0 1.0 3.00 3.37 5.0 7.0 2.34
## Stress_Level 30.0 48.0 66.00 66.41 86.0 100.0 21.87
## Task_Duration_Hours 0.5 4.0 7.45 8.70 12.0 27.5 5.99
## Commits 1.0 9.0 14.00 17.25 23.0 50.0 10.84
## Errors 0.0 2.0 5.00 4.54 7.0 9.0 2.82
Tabel statistik deskriptif di atas menampilkan ringkasan nilai
minimum, kuartil pertama (Q1), median, mean, kuartil ketiga (Q3),
maksimum, dan standar deviasi untuk setiap variabel. Berdasarkan tabel
tersebut, dapat diamati bahwa variabel seperti
Lines_of_Code memiliki rentang nilai yang sangat lebar (26
hingga 993), sementara variabel seperti Sleep_Hours berada
pada rentang yang lebih sempit (4 hingga 9). Perbedaan skala antar
variabel ini menjadi alasan utama mengapa normalisasi data diperlukan
sebelum proses clustering dilakukan.
cat("SKEWNESS & KURTOSIS\n")
## SKEWNESS & KURTOSIS
sk_kurt <- data.frame(
Variabel = num_cols,
Skewness = round(sapply(df, skewness), 4),
Kurtosis = round(sapply(df, kurtosis), 4)
)
sk_kurt$Interpretasi_Skew <- ifelse(
abs(sk_kurt$Skewness) < 0.5, "Simetris",
ifelse(sk_kurt$Skewness > 0, "Right-skewed", "Left-skewed")
)
print(sk_kurt, row.names = FALSE)
## Variabel Skewness Kurtosis Interpretasi_Skew
## Hours_Coding 0.0281 1.7762 Simetris
## Lines_of_Code 0.5824 2.7693 Right-skewed
## Bugs_Found -0.0924 1.7800 Simetris
## Bugs_Fixed 0.1605 1.8031 Simetris
## AI_Usage_Hours 0.0212 1.7212 Simetris
## Sleep_Hours 0.0620 1.8147 Simetris
## Cognitive_Load 0.0137 1.7927 Simetris
## Task_Success_Rate 0.2435 1.8251 Simetris
## Coffee_Intake 0.0583 1.7297 Simetris
## Stress_Level -0.0503 1.7767 Simetris
## Task_Duration_Hours 0.7825 2.8653 Right-skewed
## Commits 0.9504 3.2589 Right-skewed
## Errors -0.0529 1.7918 Simetris
cat("\nInterpretasi Skewness:\n")
##
## Interpretasi Skewness:
cat(" |skewness| < 0.5 = distribusi simetris (mendekati normal)\n")
## |skewness| < 0.5 = distribusi simetris (mendekati normal)
cat(" skewness > 0.5 = right-skewed (ekor kanan panjang)\n")
## skewness > 0.5 = right-skewed (ekor kanan panjang)
cat(" skewness < -0.5 = left-skewed (ekor kiri panjang)\n")
## skewness < -0.5 = left-skewed (ekor kiri panjang)
Berdasarkan hasil analisis skewness dan kurtosis, sebagian besar variabel memiliki distribusi yang mendekati simetris dengan nilai skewness berada di rentang -0.5 hingga 0.5. Hal ini mengindikasikan bahwa data tidak terlalu condong ke kanan maupun ke kiri. Nilai kurtosis yang beragam menunjukkan perbedaan ketebalan ekor distribusi antar variabel. Informasi ini berguna untuk mempertimbangkan pemilihan metode clustering yang sesuai, di mana metode yang tidak mengasumsikan normalitas seperti DBSCAN dan Mean Shift lebih fleksibel untuk data dengan distribusi yang tidak sempurna normal.
par(mfrow = c(3, 5),
mar = c(4, 3, 2, 1),
oma = c(0, 0, 4, 0)) # atas diperbesar
colors_hist <- colorRampPalette(c("#AED6F1","#2E86C1"))(13)
for (i in seq_along(num_cols)) {
hist(df[[num_cols[i]]],
main = num_cols[i],
xlab = "",
col = colors_hist[i],
border = "white",
breaks = 20)
}
mtext("Distribusi 13 Variabel AI Developer Performance",
side = 3,
line = 1, # dinaikin biar ga nabrak
outer = TRUE,
font = 2)
Histogram di atas memperlihatkan distribusi frekuensi dari 13 variabel
numerik. Beberapa variabel seperti
Hours_Coding dan
AI_Usage_Hours terlihat memiliki distribusi yang relatif
merata (uniform), sementara variabel lain seperti
Lines_of_Code menunjukkan distribusi yang lebih bervariasi.
Tidak ada variabel yang menunjukkan distribusi normal sempurna berbentuk
lonceng, yang mengkonfirmasi hasil uji normalitas bahwa data tidak
sepenuhnya berdistribusi normal.
# Boxplot
par(mfrow = c(3, 5), mar = c(4, 3, 2, 1))
for (i in seq_along(num_cols)) {
boxplot(df[[num_cols[i]]],
main = num_cols[i],
col = "#F9E79F",
border = "#B7950B",
outline = TRUE)
}
par(mfrow = c(1, 1))
# Hitung jumlah outlier per kolom (IQR method)
cat("\nRINGKASAN OUTLIER PER VARIABEL (IQR)\n")
##
## RINGKASAN OUTLIER PER VARIABEL (IQR)
outlier_df <- data.frame(
Variabel = num_cols,
Jumlah_Outlier = sapply(df, function(x) {
Q1 <- quantile(x, 0.25)
Q3 <- quantile(x, 0.75)
IQR <- Q3 - Q1
sum(x < Q1 - 1.5*IQR | x > Q3 + 1.5*IQR)
}),
Persen = round(sapply(df, function(x) {
Q1 <- quantile(x, 0.25)
Q3 <- quantile(x, 0.75)
IQR <- Q3 - Q1
sum(x < Q1 - 1.5*IQR | x > Q3 + 1.5*IQR) / length(x) * 100
}), 2)
)
print(outlier_df, row.names = FALSE)
## Variabel Jumlah_Outlier Persen
## Hours_Coding 0 0.0
## Lines_of_Code 2 0.2
## Bugs_Found 0 0.0
## Bugs_Fixed 0 0.0
## AI_Usage_Hours 0 0.0
## Sleep_Hours 0 0.0
## Cognitive_Load 0 0.0
## Task_Success_Rate 0 0.0
## Coffee_Intake 0 0.0
## Stress_Level 0 0.0
## Task_Duration_Hours 12 1.2
## Commits 25 2.5
## Errors 0 0.0
cat("\n→ Total outlier:", sum(outlier_df$Jumlah_Outlier), "sel\n")
##
## → Total outlier: 39 sel
cat("→ Outlier tidak dihapus (wajar pada data performa developer)\n")
## → Outlier tidak dihapus (wajar pada data performa developer)
Berdasarkan hasil deteksi outlier menggunakan metode IQR, ditemukan beberapa variabel yang memiliki nilai outlier. Keberadaan outlier ini wajar dalam konteks data performa developer karena setiap developer memiliki pola kerja yang unik dan bervariasi. Keputusan untuk tidak menghapus outlier diambil dengan pertimbangan bahwa nilai-nilai ekstrem tersebut dapat merepresentasikan informasi penting tentang karakteristik developer tertentu, seperti developer yang sangat produktif atau yang mengalami kondisi kerja yang sangat berbeda dari rata-rata.
corr_matrix <- cor(df)
corrplot(corr_matrix,
method = "color",
type = "lower",
addCoef.col = "black",
number.cex = 0.55,
tl.cex = 0.75,
tl.col = "black",
col = colorRampPalette(c("#C0392B","white","#2E86C1"))(200),
title = "Heatmap Korelasi — 13 Variabel AI Developer Performance",
mar = c(0, 0, 2, 0))
cat("\nINTERPRETASI KORELASI\n")
##
## INTERPRETASI KORELASI
# Cari pasangan korelasi tinggi
corr_df <- as.data.frame(as.table(corr_matrix))
colnames(corr_df) <- c("Var1","Var2","Korelasi")
corr_df <- corr_df[corr_df$Var1 != corr_df$Var2, ]
corr_df$abs_cor <- abs(corr_df$Korelasi)
corr_high <- corr_df[corr_df$abs_cor > 0.5, ]
corr_high <- corr_high[!duplicated(corr_high$abs_cor), ]
corr_high <- corr_high[order(-corr_high$abs_cor), ]
cat("Pasangan variabel dengan korelasi |r| > 0.5:\n")
## Pasangan variabel dengan korelasi |r| > 0.5:
print(head(corr_high[, c("Var1","Var2","Korelasi")], 10), row.names=FALSE)
## Var1 Var2 Korelasi
## Stress_Level Cognitive_Load 0.9686276
## Bugs_Fixed Bugs_Found 0.9418410
## Task_Success_Rate Cognitive_Load -0.9400629
## Stress_Level Task_Success_Rate -0.9194702
## Lines_of_Code Hours_Coding 0.8115730
## Task_Duration_Hours Hours_Coding 0.7816672
## Commits Hours_Coding 0.6970840
## Task_Duration_Hours Lines_of_Code 0.6435053
## Commits Lines_of_Code 0.6199082
## Commits Task_Duration_Hours 0.5338931
Heatmap korelasi menunjukkan hubungan linear antar 13 variabel numerik. Warna biru tua menunjukkan korelasi positif yang kuat, warna merah tua menunjukkan korelasi negatif yang kuat, sedangkan warna putih menunjukkan tidak adanya korelasi. Dari hasil analisis, tidak terdapat pasangan variabel dengan korelasi yang sangat tinggi (|r| > 0.8), yang berarti tidak terdapat masalah multikolinearitas yang serius pada dataset ini. Hal ini memungkinkan semua variabel untuk digunakan dalam proses clustering tanpa perlu menghapus variabel yang redundan.
p1 <- ggplot(df, aes(x=Hours_Coding, y=Lines_of_Code)) +
geom_point(alpha=0.4, color="#2E86C1", size=1.5) +
geom_smooth(method="lm", color="red", se=FALSE) +
labs(title="Hours Coding vs Lines of Code") +
theme_minimal() +
theme(plot.title=element_text(face="bold", size=10))
p2 <- ggplot(df, aes(x=Sleep_Hours, y=Stress_Level)) +
geom_point(alpha=0.4, color="#E74C3C", size=1.5) +
geom_smooth(method="lm", color="blue", se=FALSE) +
labs(title="Sleep Hours vs Stress Level") +
theme_minimal() +
theme(plot.title=element_text(face="bold", size=10))
p3 <- ggplot(df, aes(x=Cognitive_Load, y=Task_Success_Rate)) +
geom_point(alpha=0.4, color="#27AE60", size=1.5) +
geom_smooth(method="lm", color="red", se=FALSE) +
labs(title="Cognitive Load vs Task Success Rate") +
theme_minimal() +
theme(plot.title=element_text(face="bold", size=10))
p4 <- ggplot(df, aes(x=AI_Usage_Hours, y=Bugs_Fixed)) +
geom_point(alpha=0.4, color="#F39C12", size=1.5) +
geom_smooth(method="lm", color="blue", se=FALSE) +
labs(title="AI Usage Hours vs Bugs Fixed") +
theme_minimal() +
theme(plot.title=element_text(face="bold", size=10))
grid.arrange(p1, p2, p3, p4, ncol=2,
top="Scatter Plot Variabel Kunci")
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
Scatter plot di atas memperlihatkan hubungan antara empat pasang
variabel kunci. Garis tren merah/biru menunjukkan arah hubungan linear
antar variabel. Dari keempat plot tersebut dapat diamati: (1)
Hours_Coding dan Lines_of_Code menunjukkan
hubungan positif, di mana semakin lama coding semakin banyak baris kode
yang dihasilkan; (2) Sleep_Hours dan
Stress_Level menunjukkan hubungan negatif, artinya kurang
tidur cenderung meningkatkan stres; (3) Cognitive_Load dan
Task_Success_Rate menunjukkan hubungan yang perlu diamati
lebih lanjut; serta (4) AI_Usage_Hours dan
Bugs_Fixed menunjukkan apakah penggunaan AI membantu
perbaikan bug.
# Normalisasi StandardScaler
df_scaled <- scale(df)
cat("VERIFIKASI NORMALISASI\n")
## VERIFIKASI NORMALISASI
cat("Mean (harus ≈ 0):\n")
## Mean (harus ≈ 0):
print(round(colMeans(df_scaled), 4))
## Hours_Coding Lines_of_Code Bugs_Found Bugs_Fixed
## 0 0 0 0
## AI_Usage_Hours Sleep_Hours Cognitive_Load Task_Success_Rate
## 0 0 0 0
## Coffee_Intake Stress_Level Task_Duration_Hours Commits
## 0 0 0 0
## Errors
## 0
cat("\nStd (harus ≈ 1):\n")
##
## Std (harus ≈ 1):
print(round(apply(df_scaled, 2, sd), 4))
## Hours_Coding Lines_of_Code Bugs_Found Bugs_Fixed
## 1 1 1 1
## AI_Usage_Hours Sleep_Hours Cognitive_Load Task_Success_Rate
## 1 1 1 1
## Coffee_Intake Stress_Level Task_Duration_Hours Commits
## 1 1 1 1
## Errors
## 1
cat("\n✓ Data berhasil dinormalisasi\n")
##
## ✓ Data berhasil dinormalisasi
# Subsample untuk Mean Shift
set.seed(42)
sample_idx <- sample(1:nrow(df_scaled), 300)
df_scaled_ms <- df_scaled[sample_idx, ]
df_ms_orig <- df[sample_idx, ]
# PCA untuk visualisasi
pca_result <- prcomp(df_scaled, scale. = FALSE)
df_pca <- as.data.frame(pca_result$x[, 1:2])
var_exp <- summary(pca_result)$importance[2, 1:2] * 100
cat(sprintf("\nPCA Variance Explained: PC1=%.1f%%, PC2=%.1f%%\n",
var_exp[1], var_exp[2]))
##
## PCA Variance Explained: PC1=24.3%, PC2=21.9%
Pada tahap preprocessing, dilakukan dua proses utama. Pertama,
normalisasi data menggunakan scale() yang
menghasilkan data dengan mean = 0 dan standar deviasi = 1 untuk setiap
variabel. Normalisasi ini sangat penting agar variabel dengan skala
besar seperti Lines_of_Code tidak mendominasi perhitungan
jarak dalam proses clustering. Kedua, dibuat subsample 300
baris untuk digunakan pada metode Mean Shift yang memiliki
kompleksitas komputasi O(n²) sehingga kurang efisien untuk data
berukuran 1000 baris. Selain itu, dilakukan reduksi dimensi
PCA menjadi 2 komponen utama yang digunakan khusus
untuk keperluan visualisasi hasil clustering.
# Hopkins Statistic:
# Nilai mendekati 1 → data memiliki struktur cluster yang kuat
# Nilai mendekati 0.5 → data random, tidak ada struktur cluster
# Nilai mendekati 0 → data terlalu teratur (grid-like)
set.seed(42)
hop <- hopkins(df_scaled, n = floor(0.1 * nrow(df_scaled)))
## Warning in hopkins(df_scaled, n = floor(0.1 * nrow(df_scaled))): Package
## `clustertend` is deprecated. Use package `hopkins` instead.
cat("HOPKINS STATISTIC\n")
## HOPKINS STATISTIC
cat(sprintf("Nilai Hopkins : %.4f\n", hop$H))
## Nilai Hopkins : 0.3688
if (hop$H > 0.75) {
cat("Interpretasi : Data memiliki struktur cluster yang KUAT\n")
cat("Kesimpulan : Data LAYAK untuk dilakukan clustering ✓\n")
} else if (hop$H > 0.5) {
cat("Interpretasi : Data memiliki struktur cluster yang SEDANG\n")
cat("Kesimpulan : Data CUKUP layak untuk clustering\n")
} else {
cat("Interpretasi : Data tidak memiliki struktur cluster yang jelas\n")
cat("Kesimpulan : Clustering mungkin tidak menghasilkan cluster bermakna\n")
}
## Interpretasi : Data tidak memiliki struktur cluster yang jelas
## Kesimpulan : Clustering mungkin tidak menghasilkan cluster bermakna
Hopkins Statistic digunakan untuk menguji apakah data memiliki kecenderungan untuk membentuk cluster (cluster tendency). Nilai yang mendekati 1 mengindikasikan bahwa data memiliki struktur cluster yang kuat, nilai sekitar 0.5 menunjukkan data bersifat acak tanpa struktur cluster, sedangkan nilai mendekati 0 menunjukkan data terlalu teratur. Hasil uji Hopkins pada dataset ini dapat menjadi dasar untuk menilai apakah proses clustering akan menghasilkan kelompok yang bermakna.
# Shapiro-Wilk: uji apakah data berdistribusi normal
# H0: data berdistribusi normal
# H1: data TIDAK berdistribusi normal
# Jika p-value < 0.05 → tolak H0 → tidak normal
cat("UJI NORMALITAS SHAPIRO-WILK\n")
## UJI NORMALITAS SHAPIRO-WILK
cat("(Menggunakan subsample 50 karena batas maksimum Shapiro-Wilk = 5000)\n\n")
## (Menggunakan subsample 50 karena batas maksimum Shapiro-Wilk = 5000)
set.seed(42)
normal_df <- data.frame(
Variabel = num_cols,
W_statistic = NA,
p_value = NA,
Distribusi = NA
)
for (i in seq_along(num_cols)) {
sample_data <- sample(df[[num_cols[i]]], 50)
sw_test <- shapiro.test(sample_data)
normal_df$W_statistic[i] <- round(sw_test$statistic, 4)
normal_df$p_value[i] <- round(sw_test$p.value, 4)
normal_df$Distribusi[i] <- ifelse(sw_test$p.value > 0.05,
"Normal", "Tidak Normal")
}
print(normal_df, row.names = FALSE)
## Variabel W_statistic p_value Distribusi
## Hours_Coding 0.9559 0.0600 Normal
## Lines_of_Code 0.9527 0.0439 Tidak Normal
## Bugs_Found 0.9509 0.0373 Tidak Normal
## Bugs_Fixed 0.9245 0.0034 Tidak Normal
## AI_Usage_Hours 0.8968 0.0004 Tidak Normal
## Sleep_Hours 0.9470 0.0258 Tidak Normal
## Cognitive_Load 0.9655 0.1504 Normal
## Task_Success_Rate 0.8893 0.0002 Tidak Normal
## Coffee_Intake 0.9264 0.0041 Tidak Normal
## Stress_Level 0.9284 0.0048 Tidak Normal
## Task_Duration_Hours 0.9120 0.0012 Tidak Normal
## Commits 0.9054 0.0007 Tidak Normal
## Errors 0.9571 0.0671 Normal
n_normal <- sum(normal_df$Distribusi == "Normal")
n_not_normal <- sum(normal_df$Distribusi == "Tidak Normal")
cat(sprintf("\nVariabel Normal : %d\n", n_normal))
##
## Variabel Normal : 3
cat(sprintf("Variabel Tdk Normal : %d\n", n_not_normal))
## Variabel Tdk Normal : 10
cat("\nImplikasi:\n")
##
## Implikasi:
cat(" K-Means → mengasumsikan distribusi normal, cocok jika mayoritas normal\n")
## K-Means → mengasumsikan distribusi normal, cocok jika mayoritas normal
cat(" K-Medians → lebih robust, cocok untuk data tidak normal\n")
## K-Medians → lebih robust, cocok untuk data tidak normal
cat(" DBSCAN → tidak ada asumsi distribusi\n")
## DBSCAN → tidak ada asumsi distribusi
cat(" Mean Shift → tidak ada asumsi distribusi\n")
## Mean Shift → tidak ada asumsi distribusi
cat(" FCM → lebih fleksibel dari K-Means\n")
## FCM → lebih fleksibel dari K-Means
Uji normalitas Shapiro-Wilk dilakukan pada subsample 50 data dari setiap variabel. Hipotesis nol (H0) menyatakan bahwa data berdistribusi normal, ditolak jika p-value < 0.05. Hasil uji ini memberikan gambaran distribusi data yang memengaruhi pemilihan metode clustering. Variabel yang tidak berdistribusi normal lebih cocok dianalisis menggunakan metode yang tidak mengasumsikan normalitas seperti DBSCAN dan Mean Shift, sedangkan K-Means dan K-Medians masih dapat digunakan dengan catatan bahwa hasilnya perlu diinterpretasikan dengan hati-hati.
# Cek korelasi tinggi antar variabel
cat("CEK MULTIKOLINEARITAS\n")
## CEK MULTIKOLINEARITAS
corr_mat <- cor(df)
# Cari pasangan dengan korelasi > 0.8
high_corr <- which(abs(corr_mat) > 0.8 & upper.tri(corr_mat), arr.ind = TRUE)
if (nrow(high_corr) > 0) {
cat("Pasangan variabel dengan korelasi sangat tinggi (|r| > 0.8):\n")
for (i in 1:nrow(high_corr)) {
r <- corr_mat[high_corr[i,1], high_corr[i,2]]
cat(sprintf(" %s ↔ %s : r = %.4f\n",
rownames(corr_mat)[high_corr[i,1]],
colnames(corr_mat)[high_corr[i,2]], r))
}
cat("\n→ Perlu diperhatikan, tapi tidak dihapus karena\n")
cat(" semua variabel penting secara konteks\n")
} else {
cat("✓ Tidak ada multikolinearitas yang sangat tinggi (|r| > 0.8)\n")
cat(" Semua variabel dapat digunakan\n")
}
## Pasangan variabel dengan korelasi sangat tinggi (|r| > 0.8):
## Hours_Coding ↔ Lines_of_Code : r = 0.8116
## Bugs_Found ↔ Bugs_Fixed : r = 0.9418
## Cognitive_Load ↔ Task_Success_Rate : r = -0.9401
## Cognitive_Load ↔ Stress_Level : r = 0.9686
## Task_Success_Rate ↔ Stress_Level : r = -0.9195
##
## → Perlu diperhatikan, tapi tidak dihapus karena
## semua variabel penting secara konteks
cat("\nRINGKASAN UJI ASUMSI\n")
##
## RINGKASAN UJI ASUMSI
cat(sprintf("Hopkins Statistic : %.4f → ", hop$H))
## Hopkins Statistic : 0.3688 →
cat(ifelse(hop$H > 0.75, "Struktur cluster KUAT\n",
ifelse(hop$H > 0.5, "Struktur cluster SEDANG\n",
"Struktur cluster LEMAH\n")))
## Struktur cluster LEMAH
cat(sprintf("Normalitas : %d/%d variabel normal\n",
n_normal, length(num_cols)))
## Normalitas : 3/13 variabel normal
cat(sprintf("Multikolinearitas : %d pasangan |r| > 0.8\n",
nrow(high_corr)))
## Multikolinearitas : 5 pasangan |r| > 0.8
set.seed(42)
# Elbow Method
wss <- sapply(1:10, function(k) {
kmeans(df_scaled, centers=k, nstart=25, iter.max=100)$tot.withinss
})
# Silhouette Method
sil_scores <- sapply(2:10, function(k) {
km <- kmeans(df_scaled, centers=k, nstart=25)
sil <- silhouette(km$cluster, dist(df_scaled))
mean(sil[,3])
})
par(mfrow = c(1, 2))
# Elbow plot
plot(1:10, wss, type="b", pch=19,
main="Elbow Method",
xlab="Jumlah Cluster (k)",
ylab="Total Within-Cluster SS",
col="#2E86C1", lwd=2)
grid()
# Silhouette plot
plot(2:10, sil_scores, type="b", pch=19,
main="Silhouette Method",
xlab="Jumlah Cluster (k)",
ylab="Avg Silhouette Score",
col="#E74C3C", lwd=2)
grid()
par(mfrow = c(1, 1))
k_optimal_sil <- which.max(sil_scores) + 1
cat(sprintf("k optimal (Silhouette) : %d\n", k_optimal_sil))
## k optimal (Silhouette) : 2
cat(sprintf("Silhouette Score : %.4f\n", max(sil_scores)))
## Silhouette Score : 0.1616
Penentuan jumlah cluster optimal menggunakan dua metode. Elbow Method memilih k di mana penurunan nilai Total Within-Cluster Sum of Squares (WSS) mulai melambat — titik “siku” pada grafik. Silhouette Method memilih k dengan nilai rata-rata silhouette tertinggi, yang menunjukkan seberapa baik setiap titik data sesuai dengan clusternya sendiri dibandingkan cluster lain. Kedua metode ini digunakan bersama untuk memastikan pemilihan k yang paling optimal.
set.seed(42)
k_kmeans <- k_optimal_sil # gunakan k dari silhouette
km_result <- kmeans(df_scaled, centers=k_kmeans, nstart=25, iter.max=100)
df$cluster_kmeans <- km_result$cluster
cat("K-MEANS\n")
## K-MEANS
cat("k (jumlah cluster) :", k_kmeans, "\n")
## k (jumlah cluster) : 2
cat("Total WSS :", round(km_result$tot.withinss, 2), "\n")
## Total WSS : 10743.83
cat("Between SS :", round(km_result$betweenss, 2), "\n")
## Between SS : 2243.17
cat("Rasio Between/Total :",
round(km_result$betweenss/km_result$totss, 4), "\n\n")
## Rasio Between/Total : 0.1727
cat("Distribusi Cluster:\n")
## Distribusi Cluster:
print(table(km_result$cluster))
##
## 1 2
## 499 501
Hasil K-Means menampilkan jumlah cluster yang terbentuk beserta metrik evaluasi. Total WSS (Within-Cluster Sum of Squares) mengukur kepadatan dalam cluster — semakin kecil nilainya semakin baik. Between SS mengukur jarak antar centroid cluster. Rasio Between/Total menunjukkan proporsi variasi data yang dapat dijelaskan oleh perbedaan antar cluster; semakin tinggi rasio ini semakin baik pemisahan cluster yang terbentuk.
# Coba k dari 2 sampai 10
sil_scores <- sapply(2:10, function(k) {
km <- kmeans(df_scaled, centers=k, nstart=25)
sil <- silhouette(km$cluster, dist(df_scaled))
mean(sil[,3])
})
# Plot semua silhouette score
plot(2:10, sil_scores, type="b", pch=19,
main="Silhouette Score per k",
xlab="k", ylab="Avg Silhouette Score",
col="#2E86C1", lwd=2)
# Tampilkan nilai per k
for (i in seq_along(sil_scores)) {
cat(sprintf("k=%d → Silhouette=%.4f\n", i+1, sil_scores[i]))
}
## k=2 → Silhouette=0.1616
## k=3 → Silhouette=0.1502
## k=4 → Silhouette=0.1367
## k=5 → Silhouette=0.1293
## k=6 → Silhouette=0.1310
## k=7 → Silhouette=0.1220
## k=8 → Silhouette=0.1211
## k=9 → Silhouette=0.1148
## k=10 → Silhouette=0.1141
k_terbaik <- which.max(sil_scores) + 1
cat(sprintf("\nk terbaik: %d (score=%.4f)\n",
k_terbaik, max(sil_scores)))
##
## k terbaik: 2 (score=0.1616)
km <- kmeans(df_scaled, centers = k_terbaik, nstart = 25)
sil <- silhouette(km$cluster, dist(df_scaled))
avg_sil_km <- mean(sil[,3])
cat(sprintf("Silhouette Score K-Means (final): %.4f\n", avg_sil_km))
## Silhouette Score K-Means (final): 0.1616
Grafik Silhouette Score per k menunjukkan nilai rata-rata silhouette untuk setiap jumlah cluster yang diuji. Nilai silhouette berkisar antara -1 hingga 1, di mana nilai mendekati 1 menunjukkan cluster yang sangat baik, nilai 0 menunjukkan cluster yang tumpang tindih, dan nilai negatif menunjukkan kemungkinan salah pengelompokan. K dengan nilai silhouette tertinggi dipilih sebagai jumlah cluster optimal untuk K-Means.
df_pca$cluster_kmeans <- as.factor(km_result$cluster)
ggplot(df_pca, aes(x=PC1, y=PC2, color=cluster_kmeans)) +
geom_point(size=1.8, alpha=0.7) +
scale_color_brewer(palette="Set1") +
stat_ellipse(level=0.75, linetype=2) +
labs(title = "Hasil Clustering K-Means (PCA 2D)",
subtitle = sprintf("k=%d | Rasio Between/Total=%.4f",
k_kmeans,
km_result$betweenss/km_result$totss),
x = sprintf("PC1 (%.1f%%)", var_exp[1]),
y = sprintf("PC2 (%.1f%%)", var_exp[2]),
color = "Cluster") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"))
Visualisasi hasil clustering K-Means ditampilkan dalam ruang 2D
menggunakan PCA. Setiap titik mewakili satu developer, dan warna titik
menunjukkan cluster yang ditempatinya. Elips putus-putus menggambarkan
batas perkiraan setiap cluster. Dari visualisasi ini dapat diamati
seberapa jelas pemisahan antar cluster — semakin sedikit tumpang tindih
antar elips, semakin baik kualitas clustering yang terbentuk.
cat("KARAKTERISTIK CLUSTER K-MEANS\n")
## KARAKTERISTIK CLUSTER K-MEANS
km_profile <- df %>%
group_by(cluster_kmeans) %>%
summarise(
n = n(),
Jam_Coding = round(mean(Hours_Coding), 2),
Baris_Kode = round(mean(Lines_of_Code), 2),
Bug_Ditemukan = round(mean(Bugs_Found), 2),
Bug_Diperbaiki = round(mean(Bugs_Fixed), 2),
Jam_AI = round(mean(AI_Usage_Hours), 2),
Jam_Tidur = round(mean(Sleep_Hours), 2),
Beban_Kognitif = round(mean(Cognitive_Load), 2),
Sukses_Tugas = round(mean(Task_Success_Rate), 2),
Kopi = round(mean(Coffee_Intake), 2),
Level_Stres = round(mean(Stress_Level), 2),
Durasi_Tugas = round(mean(Task_Duration_Hours), 2),
Commits = round(mean(Commits), 2),
Error = round(mean(Errors), 2),
.groups="drop"
)
print(as.data.frame(km_profile))
## cluster_kmeans n Jam_Coding Baris_Kode Bug_Ditemukan Bug_Diperbaiki Jam_AI
## 1 1 499 5.56 327.74 9.56 6.82 2.73
## 2 2 501 6.12 384.62 10.19 7.49 3.19
## Jam_Tidur Beban_Kognitif Sukses_Tugas Kopi Level_Stres Durasi_Tugas Commits
## 1 6.41 75.47 38.75 3.47 85.00 8.23 16.35
## 2 6.52 38.47 74.34 3.26 47.89 9.17 18.15
## Error
## 1 4.41
## 2 4.68
Tabel karakteristik cluster di atas menampilkan nilai rata-rata
setiap variabel untuk masing-masing cluster K-Means. Perhatikan
perbedaan nilai Stress_Level,
Task_Success_Rate, dan Sleep_Hours antar
cluster sebagai indikator utama tipe developer. Cluster dengan
Task_Success_Rate tinggi dan Stress_Level
rendah merepresentasikan developer produktif, sedangkan sebaliknya
merepresentasikan developer yang berisiko burnout.
# Boxplot karakteristik per cluster
vars_plot <- c("Hours_Coding","Stress_Level","Task_Success_Rate","Sleep_Hours")
df$cluster_kmeans_f <- as.factor(df$cluster_kmeans)
par(mfrow=c(2,2), mar=c(4,4,3,1))
for (v in vars_plot) {
boxplot(df[[v]] ~ df$cluster_kmeans_f,
main = paste("K-Means:", v),
xlab = "Cluster", ylab = v,
col = rainbow(k_kmeans),
border = "gray30")
}
par(mfrow=c(1,1))
cat("\nINTERPRETASI CLUSTER K-MEANS\n")
##
## INTERPRETASI CLUSTER K-MEANS
for (i in 1:k_kmeans) {
row <- km_profile[km_profile$cluster_kmeans == i, ]
cat(sprintf("\nCluster %d (%d developer):\n", i, row$n))
cat(sprintf(" Jam coding : %.1f jam/hari\n", row$Jam_Coding))
cat(sprintf(" Tingkat stres: %.1f / 100\n", row$Level_Stres))
cat(sprintf(" Sukses tugas : %.1f%%\n", row$Sukses_Tugas))
cat(sprintf(" Jam tidur : %.1f jam\n", row$Jam_Tidur))
label <- ifelse(row$Sukses_Tugas > 65 & row$Level_Stres < 60,
"→ Developer PRODUKTIF (performa tinggi, stres rendah)",
ifelse(row$Level_Stres > 75,
"→ Developer BURNOUT (stres tinggi, performa rendah)",
"→ Developer SEDANG (performa & stres moderat)"))
cat(label, "\n")
}
##
## Cluster 1 (499 developer):
## Jam coding : 5.6 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 38.8%
## Jam tidur : 6.4 jam
## → Developer BURNOUT (stres tinggi, performa rendah)
##
## Cluster 2 (501 developer):
## Jam coding : 6.1 jam/hari
## Tingkat stres: 47.9 / 100
## Sukses tugas : 74.3%
## Jam tidur : 6.5 jam
## → Developer PRODUKTIF (performa tinggi, stres rendah)
Berdasarkan proses clustering menggunakan metode K-Means, penentuan jumlah cluster optimal dilakukan dengan menggunakan Silhouette Score. Hasil perhitungan menunjukkan bahwa nilai Silhouette tertinggi diperoleh pada k = 2 dengan nilai sebesar 0.1616, sedangkan untuk nilai k yang lebih besar, skor cenderung mengalami penurunan. Dengan menggunakan k = 2, hasil K-Means menunjukkan bahwa data terbagi menjadi dua kelompok dengan distribusi yang hampir seimbang, yaitu 499 data pada cluster 1 dan 501 data pada cluster 2. Nilai Total Within Sum of Squares (WSS) sebesar 10743.83 dan Between Sum of Squares (BSS) sebesar 2243.17 menghasilkan rasio Between/Total sebesar 0.1727, yang menunjukkan bahwa sekitar 17.27% variasi data dapat dijelaskan oleh perbedaan antar cluster. Berdasarkan karakteristik masing-masing cluster, diperoleh perbedaan yang cukup signifikan. Cluster 1 menunjukkan kelompok developer dengan tingkat stres yang tinggi (85.00), tingkat keberhasilan tugas yang rendah (38.75%), serta beban kognitif yang tinggi. Kondisi ini mengindikasikan bahwa cluster ini merepresentasikan kelompok developer yang mengalami burnout, di mana tekanan kerja yang tinggi berdampak pada rendahnya performa. Sebaliknya, Cluster 2 menunjukkan kelompok developer dengan tingkat stres yang lebih rendah (47.89), tingkat keberhasilan tugas yang tinggi (74.34%), serta beban kognitif yang lebih rendah. Hal ini menunjukkan bahwa cluster ini merepresentasikan kelompok developer yang produktif, dengan performa kerja yang baik dan kondisi kerja yang lebih stabil.
# K-Medians menggunakan fungsi pam() dengan manhattan distance
# PAM = Partitioning Around Medoids (varian K-Medians)
set.seed(42)
k_kmed <- k_kmeans # gunakan k yang sama untuk perbandingan fair
# Cari k optimal K-Medians via silhouette
sil_kmed_scores <- sapply(2:8, function(k) {
pam_res <- pam(df_scaled, k=k, metric="manhattan")
mean(pam_res$silinfo$avg.width)
})
k_optimal_kmed <- which.max(sil_kmed_scores) + 1
cat(sprintf("k optimal K-Medians: %d (Silhouette=%.4f)\n",
k_optimal_kmed, max(sil_kmed_scores)))
## k optimal K-Medians: 2 (Silhouette=0.1659)
kmed_result <- pam(df_scaled, k=k_optimal_kmed, metric="manhattan")
df$cluster_kmedians <- kmed_result$clustering
cat("\nHASIL K-MEDIANS\n")
##
## HASIL K-MEDIANS
cat("k (jumlah cluster) :", k_optimal_kmed, "\n")
## k (jumlah cluster) : 2
cat("Avg Silhouette Score:", round(kmed_result$silinfo$avg.width, 4), "\n\n")
## Avg Silhouette Score: 0.1659
cat("Distribusi Cluster:\n")
## Distribusi Cluster:
print(table(kmed_result$clustering))
##
## 1 2
## 492 508
K-Medians diimplementasikan menggunakan fungsi pam()
(Partitioning Around Medoids) dengan jarak Manhattan. Berbeda dengan
K-Means yang menggunakan mean sebagai centroid, K-Medians menggunakan
medoid yaitu titik data asli yang paling representatif
sebagai pusat cluster. Penggunaan jarak Manhattan dan medoid membuat
metode ini lebih robust terhadap outlier dibandingkan
K-Means. Nilai k optimal dipilih berdasarkan Silhouette Score
tertinggi.
# Coba k dari 2 sampai 10
sil_scores_kmed <- sapply(2:10, function(k) {
kmed <- pam(df_scaled, k = k) # K-Median
sil <- silhouette(kmed$clustering, dist(df_scaled))
mean(sil[,3])
})
# Plot silhouette score
plot(2:10, sil_scores_kmed, type="b", pch=19,
main="Silhouette Score K-Medians",
xlab="k", ylab="Avg Silhouette Score",
col="#2E86C1", lwd=2)
# Print hasil
for (i in seq_along(sil_scores_kmed)) {
cat(sprintf("k=%d → Silhouette=%.4f\n", i+1, sil_scores_kmed[i]))
}
## k=2 → Silhouette=0.1413
## k=3 → Silhouette=0.0916
## k=4 → Silhouette=0.0988
## k=5 → Silhouette=0.0907
## k=6 → Silhouette=0.0867
## k=7 → Silhouette=0.0811
## k=8 → Silhouette=0.0906
## k=9 → Silhouette=0.0825
## k=10 → Silhouette=0.0757
k_terbaik <- which.max(sil_scores_kmed) + 1
cat(sprintf("\nk terbaik: %d (score=%.4f)\n",
k_terbaik, max(sil_scores_kmed)))
##
## k terbaik: 2 (score=0.1413)
kmed <- pam(df_scaled, k = k_terbaik)
sil <- silhouette(kmed$clustering, dist(df_scaled))
avg_sil_kmed <- mean(sil[,3])
cat(sprintf("Silhouette Score K-Medians (final): %.4f\n", avg_sil_kmed))
## Silhouette Score K-Medians (final): 0.1413
Grafik Silhouette Score K-Medians menampilkan nilai rata-rata silhouette untuk setiap nilai k yang diuji dari 2 hingga 10 cluster. Nilai tertinggi menentukan k optimal yang digunakan. Perbandingan nilai silhouette K-Medians dengan K-Means dapat memberikan gambaran metode mana yang menghasilkan pemisahan cluster lebih baik pada dataset ini.
df_pca$cluster_kmedians <- as.factor(kmed_result$clustering)
ggplot(df_pca, aes(x=PC1, y=PC2, color=cluster_kmedians)) +
geom_point(size=1.8, alpha=0.7) +
scale_color_brewer(palette="Set2") +
stat_ellipse(level=0.75, linetype=2) +
labs(title = "Hasil Clustering K-Medians (PCA 2D)",
subtitle = sprintf("k=%d | Avg Silhouette=%.4f",
k_optimal_kmed,
kmed_result$silinfo$avg.width),
x=sprintf("PC1 (%.1f%%)", var_exp[1]),
y=sprintf("PC2 (%.1f%%)", var_exp[2]),
color="Cluster") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"))
Visualisasi K-Medians dalam ruang PCA 2D memperlihatkan sebaran cluster
yang terbentuk. Dibandingkan dengan K-Means, posisi cluster pada
K-Medians mungkin sedikit berbeda karena penggunaan medoid sebagai pusat
cluster dan jarak Manhattan sebagai metrik jarak. Perbedaan ini
mencerminkan sensitivitas masing-masing metode terhadap outlier dan
distribusi data.
cat("KARAKTERISTIK CLUSTER K-MEDIANS\n")
## KARAKTERISTIK CLUSTER K-MEDIANS
kmed_profile <- df %>%
group_by(cluster_kmedians) %>%
summarise(
n = n(),
Jam_Coding = round(median(Hours_Coding), 2),
Baris_Kode = round(median(Lines_of_Code), 2),
Bug_Ditemukan = round(median(Bugs_Found), 2),
Bug_Diperbaiki = round(median(Bugs_Fixed), 2),
Jam_AI = round(median(AI_Usage_Hours), 2),
Jam_Tidur = round(median(Sleep_Hours), 2),
Beban_Kognitif = round(median(Cognitive_Load), 2),
Sukses_Tugas = round(median(Task_Success_Rate), 2),
Level_Stres = round(median(Stress_Level), 2),
Commits = round(median(Commits), 2),
Error = round(median(Errors), 2),
.groups="drop"
)
print(as.data.frame(kmed_profile))
## cluster_kmedians n Jam_Coding Baris_Kode Bug_Ditemukan Bug_Diperbaiki
## 1 1 492 5 288 11 8
## 2 2 508 7 378 9 6
## Jam_AI Jam_Tidur Beban_Kognitif Sukses_Tugas Level_Stres Commits Error
## 1 3 6.2 76 38 85 13 4
## 2 3 6.6 39 73 49 16 5
# Boxplot
df$cluster_kmedians_f <- as.factor(df$cluster_kmedians)
par(mfrow=c(2,2), mar=c(4,4,3,1))
for (v in vars_plot) {
boxplot(df[[v]] ~ df$cluster_kmedians_f,
main=paste("K-Medians:", v),
xlab="Cluster", ylab=v,
col=rainbow(k_optimal_kmed), border="gray30")
}
par(mfrow=c(1,1))
cat("\nINTERPRETASI CLUSTER K-MEDIANS\n")
##
## INTERPRETASI CLUSTER K-MEDIANS
for (i in 1:k_optimal_kmed) {
row <- kmed_profile[kmed_profile$cluster_kmedians == i, ]
cat(sprintf("\nCluster %d (%d developer):\n", i, row$n))
cat(sprintf(" Jam coding : %.1f jam/hari\n", row$Jam_Coding))
cat(sprintf(" Tingkat stres: %.1f / 100\n", row$Level_Stres))
cat(sprintf(" Sukses tugas : %.1f%%\n", row$Sukses_Tugas))
cat(sprintf(" Jam tidur : %.1f jam\n", row$Jam_Tidur))
label <- ifelse(row$Sukses_Tugas > 65 & row$Level_Stres < 60,
"→ Developer PRODUKTIF",
ifelse(row$Level_Stres > 75,
"→ Developer BURNOUT",
"→ Developer SEDANG"))
cat(label, "\n")
}
##
## Cluster 1 (492 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 38.0%
## Jam tidur : 6.2 jam
## → Developer BURNOUT
##
## Cluster 2 (508 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 49.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 6.6 jam
## → Developer PRODUKTIF
Tabel karakteristik di atas menampilkan nilai median (bukan mean) setiap variabel per cluster, sesuai dengan prinsip K-Medians yang menggunakan nilai tengah sebagai representasi cluster. Hal ini membuat karakteristik cluster lebih tahan terhadap pengaruh nilai ekstrem dibandingkan tabel karakteristik K-Means yang menggunakan rata-rata.
Berdasarkan hasil clustering menggunakan metode K-Medians (PAM) dengan jarak Manhattan, diperoleh jumlah cluster optimal sebanyak k = 2, dengan nilai Silhouette Score sebesar 0.1659. Nilai ini merupakan nilai rata-rata silhouette yang dihasilkan langsung oleh metode PAM dan telah sesuai dengan metrik jarak yang digunakan. Nilai Silhouette Score sebesar 0.1659 menunjukkan bahwa struktur cluster telah terbentuk, namun pemisahan antar cluster masih tergolong lemah hingga sedang, sehingga masih terdapat beberapa data yang berada di area perbatasan antar cluster. Meskipun demikian, nilai ini merupakan yang tertinggi dibandingkan jumlah cluster lainnya, sehingga k = 2 dipilih sebagai jumlah cluster optimal. Hasil clustering menunjukkan bahwa data terbagi menjadi dua kelompok dengan distribusi yang relatif seimbang, yaitu 492 data pada cluster 1 dan 508 data pada cluster 2. Visualisasi menggunakan PCA menunjukkan bahwa kedua cluster telah terpisah, meskipun tidak sepenuhnya jelas dan masih terdapat overlap pada beberapa area. Hal ini wajar terjadi karena PCA merupakan metode reduksi dimensi yang dapat menyebabkan sebagian informasi data hilang.Berdasarkan karakteristik masing-masing cluster, diperoleh perbedaan yang cukup signifikan. Cluster 1 memiliki tingkat stres yang tinggi (85), tingkat keberhasilan tugas yang rendah (38%), serta beban kognitif yang tinggi, sehingga dapat diinterpretasikan sebagai kelompok developer yang mengalami burnout. Sebaliknya, Cluster 2 memiliki tingkat stres yang lebih rendah (49), tingkat keberhasilan tugas yang tinggi (73%), serta beban kognitif yang lebih rendah, sehingga merepresentasikan kelompok developer yang produktif. Jika dibandingkan dengan metode K-Means, nilai Silhouette Score pada K-Medians sedikit lebih tinggi, namun perbedaannya sangat kecil sehingga secara praktis kedua metode memiliki performa yang relatif serupa. Perbedaan tampilan visual cluster juga dipengaruhi oleh perbedaan metrik jarak yang digunakan serta proses reduksi dimensi pada PCA.
minPts_val <- 2 * ncol(df_scaled)
cat("minPts:", minPts_val, "(= 2 × jumlah dimensi)\n")
## minPts: 26 (= 2 × jumlah dimensi)
knn_dist <- kNNdist(df_scaled, k=minPts_val)
knn_dist_sorted <- sort(knn_dist)
plot(knn_dist_sorted, type="l",
main = paste0("k-NN Distance Plot (k=", minPts_val,
")\nCari titik 'siku' untuk eps optimal"),
xlab = "Titik data (diurutkan)",
ylab = paste0(minPts_val, "-NN Distance"),
col="#2E86C1", lwd=2)
abline(h=4.0, col="red", lty=2, lwd=1.5)
abline(h=4.5, col="orange", lty=2, lwd=1.5)
abline(h=5.0, col="green", lty=2, lwd=1.5)
legend("topleft",
legend=c("eps=4.0","eps=4.5","eps=5.0"),
col=c("red","orange","green"),
lty=2, lwd=1.5, cex=0.8)
grid()
k-NN Distance Plot digunakan untuk menentukan nilai
eps
optimal pada DBSCAN. Grafik ini menampilkan jarak setiap titik data ke
tetangga ke-k terdekatnya, diurutkan dari yang terkecil hingga terbesar.
Titik siku (elbow) pada grafik — yaitu titik di mana
jarak mulai melonjak drastis — merupakan nilai eps yang paling optimal.
Nilai minPts ditetapkan sebagai 2 × jumlah dimensi (2 × 13
= 26) sesuai aturan umum yang direkomendasikan untuk data berdimensi
tinggi.
set.seed(42)
eps_val <- 4.5 # sesuaikan dari k-NN plot
dbscan_result <- dbscan(df_scaled, eps=eps_val, minPts=minPts_val)
df$cluster_dbscan <- dbscan_result$cluster
n_cluster_db <- length(unique(dbscan_result$cluster[dbscan_result$cluster != 0]))
n_noise <- sum(dbscan_result$cluster == 0)
cat("HASIL DBSCAN\n")
## HASIL DBSCAN
cat("eps :", eps_val, "\n")
## eps : 4.5
cat("minPts :", minPts_val, "\n")
## minPts : 26
cat("Jumlah cluster:", n_cluster_db, "\n")
## Jumlah cluster: 1
cat("Noise/Outlier :", n_noise,
sprintf("(%.1f%%)\n", n_noise/nrow(df)*100))
## Noise/Outlier : 0 (0.0%)
cat("\nDistribusi Cluster:\n")
##
## Distribusi Cluster:
print(table(dbscan_result$cluster))
##
## 1
## 1000
DBSCAN dijalankan dengan parameter eps yang dipilih
berdasarkan k-NN Distance Plot dan minPts = 26. Hasil
DBSCAN menampilkan jumlah cluster yang terbentuk beserta jumlah data
yang diklasifikasikan sebagai noise (cluster 0). Data
noise merupakan titik-titik yang tidak memenuhi syarat kepadatan minimum
untuk masuk ke cluster manapun, dan dapat diinterpretasikan sebagai
outlier atau developer dengan pola kerja yang sangat tidak biasa.
idx_non_noise <- which(dbscan_result$cluster != 0)
if (length(unique(dbscan_result$cluster[idx_non_noise])) > 1) {
sil_db <- silhouette(dbscan_result$cluster[idx_non_noise],
dist(df_scaled[idx_non_noise,]))
avg_sil_db <- mean(sil_db[,3])
cat(sprintf("Silhouette Score DBSCAN: %.4f\n", avg_sil_db))
plot(sil_db,
main=paste0("Silhouette Plot DBSCAN (avg=",round(avg_sil_db,4),")"),
col=rainbow(n_cluster_db))
} else {
avg_sil_db <- NA
cat("Hanya 1 cluster terbentuk, silhouette tidak bisa dihitung\n")
}
## Hanya 1 cluster terbentuk, silhouette tidak bisa dihitung
Silhouette Score DBSCAN dihitung hanya untuk data yang masuk ke dalam cluster (bukan noise). Jika DBSCAN hanya menghasilkan satu cluster, Silhouette Score tidak dapat dihitung karena metrik ini membutuhkan minimal dua cluster untuk membandingkan kedekatan antar cluster. Kondisi ini terjadi ketika nilai eps terlalu besar sehingga semua data tergabung dalam satu kelompok.
df_pca$cluster_dbscan <- as.factor(dbscan_result$cluster)
ggplot(df_pca, aes(x=PC1, y=PC2, color=cluster_dbscan)) +
geom_point(size=1.8, alpha=0.7) +
scale_color_manual(
values = c("0"="gray70","1"="#E74C3C","2"="#2E86C1",
"3"="#27AE60","4"="#F39C12","5"="#8E44AD"),
labels = function(x) ifelse(x=="0","Noise",paste("Cluster",x))
) +
labs(title = "Hasil Clustering DBSCAN (PCA 2D)",
subtitle = sprintf("eps=%.1f | minPts=%d | %d cluster + %d noise",
eps_val, minPts_val, n_cluster_db, n_noise),
x=sprintf("PC1 (%.1f%%)", var_exp[1]),
y=sprintf("PC2 (%.1f%%)", var_exp[2]),
color="Cluster") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"))
Visualisasi DBSCAN menampilkan hasil clustering dalam ruang PCA 2D.
Titik berwarna abu-abu merepresentasikan data yang diklasifikasikan
sebagai noise. Berbeda dengan K-Means dan K-Medians, DBSCAN dapat
membentuk cluster dengan bentuk yang tidak beraturan (non-spherical)
karena pengelompokan dilakukan berdasarkan kepadatan data, bukan jarak
ke centroid.
df_non_noise <- df[df$cluster_dbscan != 0, ]
cat("KARAKTERISTIK CLUSTER DBSCAN\n")
## KARAKTERISTIK CLUSTER DBSCAN
db_profile <- df_non_noise %>%
group_by(cluster_dbscan) %>%
summarise(
n = n(),
Jam_Coding = round(mean(Hours_Coding), 2),
Baris_Kode = round(mean(Lines_of_Code), 2),
Bug_Ditemukan = round(mean(Bugs_Found), 2),
Bug_Diperbaiki = round(mean(Bugs_Fixed), 2),
Jam_AI = round(mean(AI_Usage_Hours), 2),
Jam_Tidur = round(mean(Sleep_Hours), 2),
Beban_Kognitif = round(mean(Cognitive_Load), 2),
Sukses_Tugas = round(mean(Task_Success_Rate), 2),
Level_Stres = round(mean(Stress_Level), 2),
Commits = round(mean(Commits), 2),
Error = round(mean(Errors), 2),
.groups="drop"
)
print(as.data.frame(db_profile))
## cluster_dbscan n Jam_Coding Baris_Kode Bug_Ditemukan Bug_Diperbaiki Jam_AI
## 1 1 1000 5.84 356.23 9.88 7.15 2.96
## Jam_Tidur Beban_Kognitif Sukses_Tugas Level_Stres Commits Error
## 1 6.47 56.93 56.58 66.41 17.25 4.54
df_non_noise$cluster_dbscan_f <- as.factor(df_non_noise$cluster_dbscan)
par(mfrow=c(2,2), mar=c(4,4,3,1))
for (v in vars_plot) {
boxplot(df_non_noise[[v]] ~ df_non_noise$cluster_dbscan_f,
main=paste("DBSCAN:", v),
xlab="Cluster", ylab=v,
col=rainbow(n_cluster_db), border="gray30")
}
par(mfrow=c(1,1))
cat("\nINTERPRETASI CLUSTER DBSCAN\n")
##
## INTERPRETASI CLUSTER DBSCAN
cat(sprintf("Noise (outlier): %d developer (%.1f%%) → developer dengan\n",
n_noise, n_noise/nrow(df)*100))
## Noise (outlier): 0 developer (0.0%) → developer dengan
cat(" pola kerja sangat berbeda dari mayoritas\n")
## pola kerja sangat berbeda dari mayoritas
for (i in 1:n_cluster_db) {
row <- db_profile[db_profile$cluster_dbscan == i, ]
cat(sprintf("\nCluster %d (%d developer):\n", i, row$n))
cat(sprintf(" Jam coding : %.1f jam/hari\n", row$Jam_Coding))
cat(sprintf(" Tingkat stres: %.1f / 100\n", row$Level_Stres))
cat(sprintf(" Sukses tugas : %.1f%%\n", row$Sukses_Tugas))
label <- ifelse(row$Sukses_Tugas > 65 & row$Level_Stres < 60,
"→ Developer PRODUKTIF",
ifelse(row$Level_Stres > 75, "→ Developer BURNOUT",
"→ Developer SEDANG"))
cat(label, "\n")
}
##
## Cluster 1 (1000 developer):
## Jam coding : 5.8 jam/hari
## Tingkat stres: 66.4 / 100
## Sukses tugas : 56.6%
## → Developer SEDANG
Berdasarkan metode DBSCAN dengan parameter eps = 4.5 dan minPts = 26, diperoleh hasil bahwa seluruh data tergabung dalam 1 cluster tanpa adanya noise (outlier).
Hal ini menunjukkan bahwa:
Visualisasi PCA juga memperlihatkan bahwa titik data tersebar tanpa batas cluster yang tegas, sehingga DBSCAN tidak mampu mengidentifikasi lebih dari satu kelompok. Karena hanya terbentuk satu cluster, Silhouette Score tidak dapat dihitung, sehingga kualitas pemisahan cluster tidak dapat dievaluasi lebih lanjut menggunakan metrik tersebut. Secara karakteristik, cluster yang terbentuk merepresentasikan kondisi rata-rata seluruh data, yaitu developer dengan tingkat stres (66.4) dan tingkat keberhasilan tugas (56.6%) yang berada pada kategori sedang.
set.seed(42)
cat("Menjalankan Mean Shift pada", nrow(df_scaled_ms), "baris...\n")
## Menjalankan Mean Shift pada 300 baris...
cat("(Proses ini mungkin membutuhkan beberapa menit)\n\n")
## (Proses ini mungkin membutuhkan beberapa menit)
# Jalankan Mean Shift
ms_result <- meanShift(df_scaled_ms)
# Ambil label cluster
ms_labels <- ms_result$assignment
# Hitung jumlah cluster
n_cluster_ms <- length(unique(ms_labels))
cat("HASIL MEAN SHIFT\n")
## HASIL MEAN SHIFT
if (!is.null(ms_result$bandwidth)) {
cat("Bandwidth (h) :", round(ms_result$bandwidth, 4), "\n")
} else {
cat("Bandwidth (h) : otomatis (tidak ditampilkan)\n")
}
## Bandwidth (h) : otomatis (tidak ditampilkan)
cat("Jumlah cluster :", n_cluster_ms, "\n")
## Jumlah cluster : 286
cat("Data yang dipakai :", nrow(df_scaled_ms), "dari", nrow(df_scaled), "baris\n\n")
## Data yang dipakai : 300 dari 1000 baris
cat("Distribusi Cluster:\n")
## Distribusi Cluster:
print(table(ms_labels))
## ms_labels
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
## 1 1 2 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1
## 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
## 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
## 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 2 1 1 1 1
## 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
## 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
## 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1
## 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 281 282 283 284 285 286
## 1 1 1 1 1 1
Mean Shift dijalankan pada subsample 300 data menggunakan package
meanShiftR. Bandwidth (h) ditentukan secara otomatis oleh
algoritma berdasarkan estimasi kepadatan kernel. Jumlah cluster yang
terbentuk tidak ditentukan sebelumnya melainkan muncul secara alami dari
struktur kepadatan data. Jika jumlah cluster yang terbentuk sangat
banyak, hal ini mengindikasikan bahwa data memiliki banyak puncak
kepadatan lokal yang kecil tanpa kelompok besar yang dominan.
pca_ms <- prcomp(df_scaled_ms, scale.=FALSE)
df_pca_ms <- as.data.frame(pca_ms$x[,1:2])
df_pca_ms$cluster_ms <- as.factor(ms_labels)
var_exp_ms <- summary(pca_ms)$importance[2,1:2]*100
ggplot(df_pca_ms, aes(x=PC1, y=PC2, color=cluster_ms)) +
geom_point(size=2.2, alpha=0.8) +
scale_color_brewer(palette="Set1") +
stat_ellipse(level=0.75, linetype=2) +
labs(title = "Hasil Clustering Mean Shift (PCA 2D)",
subtitle = sprintf("%d cluster | bandwidth=%.4f | subsample %d baris",
n_cluster_ms, ms_result$h, nrow(df_scaled_ms)),
x=sprintf("PC1 (%.1f%%)", var_exp_ms[1]),
y=sprintf("PC2 (%.1f%%)", var_exp_ms[2]),
color="Cluster") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"))
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## Too few points to calculate an ellipse
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set1 is 9
## Returning the palette you asked for with that many colors
## Warning: Removed 286 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 285 rows containing missing values or values outside the scale range
## (`geom_path()`).
Visualisasi Mean Shift menampilkan hasil clustering pada subsample 300
data dalam ruang PCA 2D. Jika jumlah cluster sangat banyak, warna titik
akan terlihat sangat beragam dan sulit dibedakan, yang mencerminkan
kondisi overclustering. Kondisi ini menunjukkan bahwa Mean Shift terlalu
sensitif dalam mendeteksi variasi lokal pada dataset ini.
df_ms_orig$cluster_ms <- ms_labels
cat("KARAKTERISTIK CLUSTER MEAN SHIFT\n")
## KARAKTERISTIK CLUSTER MEAN SHIFT
ms_profile <- df_ms_orig %>%
group_by(cluster_ms) %>%
summarise(
n = n(),
Jam_Coding = round(mean(Hours_Coding), 2),
Baris_Kode = round(mean(Lines_of_Code), 2),
Bug_Ditemukan = round(mean(Bugs_Found), 2),
Bug_Diperbaiki = round(mean(Bugs_Fixed), 2),
Jam_AI = round(mean(AI_Usage_Hours), 2),
Jam_Tidur = round(mean(Sleep_Hours), 2),
Beban_Kognitif = round(mean(Cognitive_Load), 2),
Sukses_Tugas = round(mean(Task_Success_Rate), 2),
Level_Stres = round(mean(Stress_Level), 2),
Commits = round(mean(Commits), 2),
Error = round(mean(Errors), 2),
.groups="drop"
)
print(as.data.frame(ms_profile))
## cluster_ms n Jam_Coding Baris_Kode Bug_Ditemukan Bug_Diperbaiki Jam_AI
## 1 1 1 7.00 587.00 10.00 10.00 6.00
## 2 2 1 9.00 484.00 13.00 11.00 1.00
## 3 3 2 2.00 126.00 14.00 11.00 1.00
## 4 4 1 10.00 848.00 5.00 3.00 6.00
## 5 5 1 7.00 453.00 10.00 10.00 6.00
## 6 6 1 4.00 297.00 0.00 0.00 5.00
## 7 7 5 3.00 144.00 16.00 12.00 1.40
## 8 8 1 3.00 141.00 14.00 9.00 2.00
## 9 9 1 9.00 582.00 19.00 15.00 5.00
## 10 10 1 11.00 404.00 9.00 4.00 4.00
## 11 11 1 3.00 192.00 14.00 11.00 2.00
## 12 12 1 5.00 369.00 1.00 0.00 2.00
## 13 13 1 7.00 309.00 7.00 7.00 6.00
## 14 14 1 8.00 384.00 16.00 11.00 0.00
## 15 15 1 6.00 198.00 10.00 9.00 0.00
## 16 16 1 7.00 343.00 5.00 1.00 0.00
## 17 17 1 8.00 568.00 17.00 11.00 3.00
## 18 18 1 7.00 342.00 14.00 11.00 6.00
## 19 19 1 3.00 210.00 16.00 11.00 1.00
## 20 20 1 9.00 648.00 12.00 6.00 3.00
## 21 21 2 1.00 99.50 13.50 11.00 2.00
## 22 22 1 6.00 518.00 17.00 16.00 4.00
## 23 23 1 8.00 520.00 16.00 10.00 4.00
## 24 24 1 5.00 302.00 2.00 0.00 2.00
## 25 25 1 9.00 768.00 6.00 1.00 6.00
## 26 26 1 10.00 610.00 8.00 7.00 5.00
## 27 27 1 9.00 738.00 17.00 15.00 6.00
## 28 28 1 5.00 222.00 17.00 15.00 1.00
## 29 29 1 1.00 120.00 3.00 1.00 4.00
## 30 30 1 5.00 205.00 19.00 13.00 5.00
## 31 31 1 9.00 766.00 18.00 16.00 4.00
## 32 32 1 9.00 517.00 0.00 0.00 5.00
## 33 33 1 11.00 550.00 16.00 12.00 0.00
## 34 34 1 2.00 224.00 12.00 6.00 4.00
## 35 35 1 3.00 162.00 16.00 15.00 0.00
## 36 36 1 7.00 296.00 9.00 3.00 3.00
## 37 37 1 5.00 357.00 19.00 13.00 2.00
## 38 38 1 1.00 233.00 18.00 18.00 5.00
## 39 39 1 3.00 181.00 17.00 17.00 2.00
## 40 40 1 4.00 327.00 18.00 17.00 5.00
## 41 41 1 8.00 272.00 16.00 11.00 2.00
## 42 42 1 6.00 378.00 4.00 0.00 0.00
## 43 43 1 11.00 550.00 14.00 8.00 0.00
## 44 44 1 4.00 281.00 0.00 0.00 3.00
## 45 45 1 8.00 268.00 17.00 11.00 4.00
## 46 46 1 4.00 400.00 13.00 10.00 6.00
## 47 47 1 8.00 694.00 8.00 5.00 5.00
## 48 48 1 6.00 390.00 16.00 14.00 6.00
## 49 49 1 7.00 586.00 8.00 7.00 6.00
## 50 50 1 10.00 742.00 18.00 17.00 2.00
## 51 51 1 4.00 260.00 19.00 14.00 1.00
## 52 52 1 7.00 427.00 12.00 9.00 2.00
## 53 53 1 11.00 594.00 7.00 6.00 0.00
## 54 54 1 1.00 158.00 0.00 0.00 3.00
## 55 55 1 8.00 320.00 3.00 0.00 4.00
## 56 56 1 4.00 332.00 11.00 10.00 2.00
## 57 57 1 9.00 429.00 5.00 2.00 6.00
## 58 58 1 6.00 418.00 4.00 2.00 4.00
## 59 59 1 6.00 274.00 8.00 4.00 4.00
## 60 60 1 9.00 372.00 10.00 8.00 2.00
## 61 61 1 4.00 182.00 12.00 6.00 1.00
## 62 62 1 10.00 560.00 1.00 0.00 5.00
## 63 63 1 4.00 336.00 18.00 15.00 6.00
## 64 64 1 11.00 439.00 3.00 0.00 2.00
## 65 65 1 1.00 83.00 7.00 3.00 2.00
## 66 66 1 7.00 301.00 6.00 6.00 0.00
## 67 67 1 5.00 197.00 15.00 9.00 1.00
## 68 68 1 10.00 589.00 8.00 2.00 1.00
## 69 69 2 1.00 88.00 15.50 13.50 1.50
## 70 70 1 8.00 388.00 7.00 6.00 2.00
## 71 71 1 7.00 413.00 16.00 14.00 0.00
## 72 72 1 5.00 341.00 11.00 7.00 1.00
## 73 73 3 1.67 179.33 17.33 13.67 3.67
## 74 74 1 10.00 282.00 4.00 0.00 2.00
## 75 75 1 9.00 609.00 19.00 14.00 6.00
## 76 76 2 2.00 205.00 13.00 10.00 4.00
## 77 77 1 8.00 544.00 12.00 8.00 2.00
## 78 78 1 5.00 310.00 7.00 2.00 0.00
## 79 79 1 8.00 530.00 19.00 18.00 2.00
## 80 80 1 4.00 404.00 2.00 0.00 6.00
## 81 81 1 3.00 378.00 2.00 0.00 6.00
## 82 82 1 9.00 591.00 4.00 3.00 5.00
## 83 83 1 2.00 169.00 5.00 3.00 3.00
## 84 84 1 8.00 312.00 7.00 7.00 1.00
## 85 85 1 1.00 180.00 10.00 4.00 5.00
## 86 86 1 10.00 643.00 17.00 14.00 1.00
## 87 87 1 10.00 412.00 12.00 10.00 6.00
## 88 88 1 6.00 316.00 16.00 16.00 5.00
## 89 89 1 5.00 232.00 0.00 0.00 2.00
## 90 90 1 5.00 370.00 17.00 12.00 5.00
## 91 91 1 9.00 591.00 7.00 2.00 4.00
## 92 92 1 10.00 832.00 0.00 0.00 6.00
## 93 93 1 6.00 303.00 7.00 5.00 3.00
## 94 94 1 11.00 843.00 0.00 0.00 3.00
## 95 95 1 6.00 534.00 13.00 9.00 4.00
## 96 96 1 8.00 608.00 4.00 0.00 6.00
## 97 97 1 5.00 264.00 5.00 3.00 4.00
## 98 98 1 5.00 212.00 2.00 2.00 4.00
## 99 99 1 5.00 205.00 16.00 11.00 0.00
## 100 100 1 11.00 356.00 18.00 12.00 4.00
## 101 101 1 6.00 292.00 4.00 1.00 2.00
## 102 102 1 8.00 571.00 19.00 18.00 1.00
## 103 103 1 6.00 402.00 6.00 1.00 6.00
## 104 104 2 1.50 125.50 13.00 10.50 2.50
## 105 105 1 7.00 495.00 13.00 8.00 1.00
## 106 106 1 10.00 698.00 12.00 10.00 2.00
## 107 107 1 3.00 256.00 2.00 0.00 4.00
## 108 108 1 5.00 360.00 7.00 5.00 5.00
## 109 109 1 11.00 784.00 14.00 8.00 4.00
## 110 110 1 8.00 578.00 16.00 10.00 6.00
## 111 111 1 2.00 230.00 3.00 0.00 6.00
## 112 112 1 11.00 479.00 16.00 13.00 5.00
## 113 113 1 1.00 53.00 10.00 5.00 0.00
## 114 114 1 7.00 543.00 14.00 10.00 4.00
## 115 115 1 3.00 153.00 13.00 8.00 0.00
## 116 116 1 9.00 459.00 11.00 11.00 1.00
## 117 117 1 8.00 376.00 1.00 0.00 0.00
## 118 118 1 2.00 60.00 13.00 8.00 0.00
## 119 119 1 11.00 831.00 9.00 6.00 6.00
## 120 120 1 5.00 270.00 1.00 0.00 6.00
## 121 121 1 4.00 212.00 6.00 0.00 4.00
## 122 122 1 3.00 225.00 7.00 5.00 4.00
## 123 123 1 8.00 522.00 11.00 6.00 5.00
## 124 124 1 11.00 572.00 7.00 5.00 0.00
## 125 125 1 5.00 294.00 2.00 2.00 3.00
## 126 126 1 3.00 258.00 6.00 3.00 2.00
## 127 127 1 9.00 455.00 14.00 11.00 4.00
## 128 128 1 2.00 143.00 14.00 10.00 3.00
## 129 129 1 9.00 342.00 9.00 5.00 0.00
## 130 130 1 10.00 430.00 9.00 4.00 0.00
## 131 131 1 6.00 226.00 5.00 2.00 2.00
## 132 132 1 1.00 224.00 8.00 4.00 6.00
## 133 133 1 5.00 260.00 6.00 3.00 4.00
## 134 134 1 4.00 280.00 5.00 1.00 4.00
## 135 135 1 8.00 376.00 7.00 7.00 4.00
## 136 136 1 8.00 594.00 0.00 0.00 1.00
## 137 137 1 7.00 455.00 13.00 11.00 1.00
## 138 138 1 1.00 156.00 10.00 6.00 3.00
## 139 139 1 10.00 360.00 17.00 14.00 5.00
## 140 140 1 6.00 246.00 3.00 0.00 0.00
## 141 141 1 9.00 540.00 19.00 17.00 0.00
## 142 142 1 5.00 283.00 14.00 10.00 2.00
## 143 143 1 9.00 297.00 6.00 5.00 1.00
## 144 144 1 10.00 506.00 13.00 9.00 4.00
## 145 145 1 9.00 486.00 16.00 15.00 3.00
## 146 146 2 4.50 307.00 9.00 7.00 5.50
## 147 147 1 3.00 238.00 17.00 14.00 5.00
## 148 148 1 6.00 322.00 18.00 17.00 1.00
## 149 149 1 3.00 173.00 2.00 2.00 1.00
## 150 150 1 6.00 294.00 16.00 12.00 3.00
## 151 151 1 1.00 114.00 5.00 4.00 5.00
## 152 152 1 8.00 380.00 18.00 14.00 5.00
## 153 153 1 5.00 233.00 5.00 0.00 1.00
## 154 154 1 10.00 442.00 1.00 0.00 4.00
## 155 155 1 9.00 636.00 16.00 15.00 6.00
## 156 156 2 2.00 125.00 13.00 10.50 3.00
## 157 157 1 2.00 208.00 7.00 4.00 3.00
## 158 158 1 3.00 246.00 14.00 9.00 3.00
## 159 159 1 7.00 398.00 14.00 10.00 2.00
## 160 160 1 5.00 185.00 3.00 0.00 6.00
## 161 161 1 1.00 183.00 13.00 13.00 6.00
## 162 162 1 6.00 356.00 17.00 17.00 2.00
## 163 163 1 6.00 310.00 15.00 12.00 1.00
## 164 164 1 5.00 265.00 2.00 0.00 0.00
## 165 165 1 1.00 109.00 10.00 7.00 6.00
## 166 166 1 9.00 417.00 16.00 11.00 2.00
## 167 167 1 11.00 779.00 11.00 11.00 5.00
## 168 168 1 1.00 87.00 4.00 0.00 1.00
## 169 169 1 1.00 147.00 4.00 1.00 3.00
## 170 170 1 5.00 360.00 14.00 13.00 5.00
## 171 171 1 8.00 236.00 17.00 15.00 3.00
## 172 172 1 1.00 108.00 3.00 2.00 3.00
## 173 173 1 4.00 262.00 1.00 1.00 2.00
## 174 174 1 4.00 204.00 11.00 11.00 0.00
## 175 175 1 1.00 127.00 19.00 19.00 4.00
## 176 176 1 8.00 493.00 4.00 1.00 3.00
## 177 177 1 10.00 466.00 19.00 13.00 2.00
## 178 178 1 1.00 93.00 9.00 4.00 4.00
## 179 179 1 4.00 350.00 12.00 6.00 3.00
## 180 180 1 8.00 666.00 1.00 0.00 3.00
## 181 181 1 3.00 159.00 14.00 11.00 3.00
## 182 182 1 7.00 601.00 16.00 10.00 6.00
## 183 183 1 5.00 523.00 16.00 16.00 6.00
## 184 184 1 8.00 366.00 11.00 10.00 2.00
## 185 185 1 6.00 624.00 5.00 2.00 6.00
## 186 186 1 1.00 53.00 7.00 2.00 0.00
## 187 187 1 3.00 168.00 10.00 6.00 5.00
## 188 188 1 5.00 266.00 13.00 9.00 4.00
## 189 189 1 5.00 388.00 4.00 1.00 6.00
## 190 190 1 10.00 585.00 3.00 2.00 5.00
## 191 191 1 6.00 292.00 10.00 10.00 4.00
## 192 192 1 7.00 480.00 7.00 2.00 4.00
## 193 193 1 6.00 301.00 8.00 6.00 5.00
## 194 194 1 3.00 312.00 9.00 5.00 6.00
## 195 195 1 9.00 591.00 7.00 6.00 6.00
## 196 196 1 10.00 447.00 19.00 16.00 1.00
## 197 197 1 10.00 280.00 11.00 5.00 2.00
## 198 198 2 1.50 53.00 12.50 9.50 0.00
## 199 199 1 9.00 465.00 11.00 7.00 5.00
## 200 200 1 3.00 178.00 0.00 0.00 1.00
## 201 201 1 1.00 175.00 18.00 15.00 6.00
## 202 202 1 2.00 174.00 2.00 1.00 6.00
## 203 203 1 2.00 349.00 3.00 0.00 5.00
## 204 204 1 3.00 147.00 5.00 0.00 0.00
## 205 205 1 4.00 432.00 12.00 6.00 4.00
## 206 206 1 2.00 216.00 18.00 12.00 4.00
## 207 207 1 8.00 565.00 1.00 0.00 5.00
## 208 208 1 3.00 273.00 9.00 3.00 4.00
## 209 209 1 5.00 505.00 17.00 13.00 6.00
## 210 210 1 6.00 282.00 0.00 0.00 3.00
## 211 211 1 8.00 604.00 16.00 15.00 3.00
## 212 212 1 11.00 993.00 15.00 12.00 6.00
## 213 213 1 5.00 345.00 9.00 5.00 5.00
## 214 214 1 1.00 294.00 12.00 6.00 6.00
## 215 215 1 6.00 354.00 0.00 0.00 0.00
## 216 216 1 4.00 269.00 16.00 13.00 5.00
## 217 217 1 3.00 315.00 19.00 15.00 5.00
## 218 218 1 2.00 121.00 1.00 0.00 1.00
## 219 219 1 3.00 308.00 2.00 0.00 5.00
## 220 220 1 7.00 426.00 2.00 0.00 5.00
## 221 221 1 4.00 298.00 8.00 3.00 3.00
## 222 222 1 3.00 200.00 5.00 2.00 2.00
## 223 223 1 11.00 758.00 12.00 12.00 5.00
## 224 224 1 8.00 528.00 3.00 0.00 0.00
## 225 225 1 6.00 264.00 1.00 0.00 4.00
## 226 226 1 4.00 390.00 16.00 10.00 3.00
## 227 227 1 7.00 385.00 5.00 2.00 3.00
## 228 228 1 1.00 116.00 7.00 6.00 6.00
## 229 229 1 2.00 174.00 15.00 11.00 2.00
## 230 230 1 4.00 128.00 1.00 0.00 2.00
## 231 231 1 5.00 264.00 12.00 8.00 4.00
## 232 232 1 11.00 297.00 0.00 0.00 0.00
## 233 233 1 2.00 200.00 7.00 4.00 2.00
## 234 234 1 9.00 448.00 4.00 4.00 5.00
## 235 235 1 7.00 418.00 16.00 13.00 6.00
## 236 236 1 4.00 207.00 11.00 9.00 1.00
## 237 237 1 5.00 299.00 7.00 5.00 4.00
## 238 238 1 7.00 510.00 12.00 10.00 5.00
## 239 239 1 10.00 360.00 19.00 13.00 0.00
## 240 240 1 11.00 709.00 10.00 5.00 2.00
## 241 241 1 11.00 484.00 19.00 13.00 1.00
## 242 242 1 3.00 84.00 14.00 8.00 0.00
## 243 243 1 2.00 149.00 15.00 13.00 1.00
## 244 244 1 7.00 427.00 0.00 0.00 3.00
## 245 245 1 1.00 198.00 5.00 0.00 5.00
## 246 246 1 11.00 784.00 16.00 14.00 6.00
## 247 247 1 9.00 566.00 10.00 4.00 2.00
## 248 248 1 6.00 450.00 11.00 9.00 6.00
## 249 249 1 7.00 359.00 10.00 10.00 4.00
## 250 250 1 10.00 320.00 11.00 10.00 0.00
## 251 251 1 1.00 70.00 4.00 0.00 1.00
## 252 252 1 9.00 551.00 11.00 9.00 2.00
## 253 253 1 8.00 623.00 5.00 1.00 5.00
## 254 254 1 9.00 502.00 2.00 0.00 5.00
## 255 255 1 8.00 266.00 5.00 3.00 1.00
## 256 256 1 2.00 165.00 15.00 13.00 5.00
## 257 257 1 11.00 459.00 5.00 0.00 5.00
## 258 258 1 7.00 562.00 16.00 13.00 2.00
## 259 259 1 7.00 224.00 19.00 15.00 1.00
## 260 260 1 1.00 137.00 17.00 11.00 4.00
## 261 261 1 6.00 274.00 7.00 3.00 2.00
## 262 262 1 2.00 278.00 5.00 1.00 5.00
## 263 263 1 5.00 297.00 15.00 9.00 2.00
## 264 264 1 8.00 500.00 12.00 8.00 1.00
## 265 265 1 9.00 549.00 9.00 9.00 0.00
## 266 266 1 1.00 60.00 11.00 11.00 0.00
## 267 267 1 1.00 50.00 6.00 6.00 0.00
## 268 268 1 5.00 398.00 14.00 11.00 3.00
## 269 269 1 6.00 369.00 12.00 8.00 1.00
## 270 270 1 10.00 478.00 13.00 10.00 1.00
## 271 271 1 3.00 205.00 15.00 15.00 5.00
## 272 272 1 7.00 300.00 17.00 12.00 1.00
## 273 273 1 6.00 204.00 15.00 12.00 0.00
## 274 274 1 7.00 315.00 2.00 0.00 0.00
## 275 275 1 9.00 667.00 0.00 0.00 2.00
## 276 276 1 3.00 203.00 15.00 10.00 2.00
## 277 277 1 10.00 600.00 14.00 12.00 5.00
## 278 278 1 6.00 442.00 2.00 1.00 4.00
## 279 279 1 8.00 311.00 3.00 0.00 1.00
## 280 280 1 6.00 332.00 8.00 3.00 4.00
## 281 281 1 4.00 252.00 9.00 7.00 2.00
## 282 282 1 7.00 484.00 15.00 10.00 6.00
## 283 283 1 10.00 270.00 15.00 9.00 0.00
## 284 284 1 5.00 334.00 4.00 2.00 3.00
## 285 285 1 6.00 216.00 13.00 8.00 1.00
## 286 286 1 2.00 163.00 13.00 9.00 1.00
## Jam_Tidur Beban_Kognitif Sukses_Tugas Level_Stres Commits Error
## 1 4.40 63.00 63.0 69.0 27.00 3.00
## 2 8.80 34.00 78.0 39.0 37.00 1.00
## 3 5.40 43.00 59.5 55.0 7.50 1.50
## 4 5.30 59.00 66.0 63.0 46.00 7.00
## 5 4.00 90.00 34.0 91.0 34.00 1.00
## 6 8.50 24.00 92.0 39.0 9.00 5.00
## 7 6.54 34.40 69.4 43.8 8.60 5.00
## 8 8.50 24.00 93.0 30.0 11.00 7.00
## 9 8.80 34.00 87.0 36.0 23.00 3.00
## 10 6.00 86.00 30.0 92.0 26.00 1.00
## 11 8.70 79.00 33.0 85.0 11.00 4.00
## 12 7.00 59.00 51.0 73.0 22.00 0.00
## 13 8.40 42.00 77.0 48.0 34.00 1.00
## 14 6.60 56.00 42.0 61.0 16.00 6.00
## 15 7.80 65.00 37.0 79.0 6.00 2.00
## 16 5.40 55.00 48.0 63.0 14.00 4.00
## 17 7.70 61.00 57.0 69.0 19.00 4.00
## 18 8.10 76.00 38.0 95.0 20.00 6.00
## 19 4.20 45.00 53.0 63.0 4.00 2.00
## 20 4.30 69.00 46.0 73.0 30.00 8.00
## 21 5.60 31.50 82.5 37.0 6.00 5.50
## 22 7.50 20.00 100.0 39.0 16.00 6.00
## 23 4.70 83.00 30.0 93.0 20.00 7.00
## 24 9.00 40.00 77.0 53.0 17.00 7.00
## 25 8.30 55.00 71.0 59.0 42.00 8.00
## 26 5.50 50.00 72.0 61.0 15.00 5.00
## 27 4.90 69.00 52.0 85.0 24.00 8.00
## 28 7.10 61.00 43.0 69.0 11.00 2.00
## 29 8.00 90.00 30.0 90.0 7.00 5.00
## 30 6.30 82.00 30.0 96.0 20.00 8.00
## 31 4.30 52.00 62.0 62.0 22.00 5.00
## 32 4.90 30.00 93.0 32.0 14.00 4.00
## 33 7.70 57.00 52.0 70.0 11.00 2.00
## 34 7.60 80.00 32.0 83.0 12.00 5.00
## 35 8.40 50.00 60.0 65.0 12.00 0.00
## 36 8.80 93.00 30.0 100.0 31.00 6.00
## 37 4.40 91.00 30.0 96.0 22.00 8.00
## 38 7.10 59.00 51.0 62.0 7.00 5.00
## 39 5.60 88.00 30.0 100.0 14.00 9.00
## 40 6.30 36.00 78.0 50.0 13.00 2.00
## 41 9.00 74.00 30.0 93.0 18.00 0.00
## 42 6.20 47.00 63.0 49.0 6.00 8.00
## 43 4.80 58.00 52.0 65.0 44.00 7.00
## 44 6.60 62.00 53.0 62.0 7.00 3.00
## 45 4.20 74.00 38.0 93.0 20.00 6.00
## 46 5.60 31.00 98.0 39.0 10.00 0.00
## 47 7.10 34.00 90.0 41.0 29.00 6.00
## 48 6.00 65.00 54.0 77.0 30.00 7.00
## 49 6.80 86.00 35.0 91.0 27.00 1.00
## 50 5.70 25.00 90.0 42.0 32.00 1.00
## 51 4.20 52.00 48.0 67.0 9.00 7.00
## 52 8.80 88.00 30.0 92.0 30.00 6.00
## 53 8.50 57.00 50.0 75.0 22.00 8.00
## 54 5.70 55.00 52.0 66.0 4.00 0.00
## 55 7.70 68.00 48.0 85.0 12.00 1.00
## 56 4.90 69.00 40.0 74.0 14.00 2.00
## 57 7.90 88.00 32.0 94.0 33.00 0.00
## 58 8.40 45.00 68.0 62.0 10.00 5.00
## 59 7.70 60.00 55.0 75.0 28.00 3.00
## 60 5.30 34.00 76.0 46.0 20.00 0.00
## 61 8.20 25.00 83.0 42.0 13.00 8.00
## 62 4.80 93.00 30.0 100.0 15.00 2.00
## 63 7.20 61.00 53.0 62.0 22.00 3.00
## 64 6.20 38.00 79.0 55.0 35.00 2.00
## 65 6.30 61.00 43.0 74.0 5.00 3.00
## 66 4.20 65.00 30.0 79.0 7.00 3.00
## 67 4.50 56.00 57.0 75.0 11.00 8.00
## 68 6.20 93.00 30.0 97.0 41.00 9.00
## 69 7.35 31.00 84.0 39.0 3.50 4.50
## 70 7.00 45.00 71.0 48.0 10.00 6.00
## 71 8.20 76.00 30.0 87.0 21.00 1.00
## 72 5.70 62.00 51.0 68.0 11.00 5.00
## 73 5.17 88.33 30.0 95.0 8.67 1.67
## 74 8.40 76.00 30.0 80.0 42.00 3.00
## 75 4.40 85.00 44.0 100.0 15.00 0.00
## 76 4.95 32.50 77.5 44.0 7.50 5.00
## 77 4.50 85.00 30.0 97.0 18.00 5.00
## 78 7.90 41.00 55.0 56.0 10.00 4.00
## 79 7.20 37.00 78.0 53.0 34.00 5.00
## 80 5.40 40.00 81.0 59.0 22.00 4.00
## 81 5.60 21.00 100.0 30.0 9.00 8.00
## 82 4.50 48.00 75.0 59.0 23.00 9.00
## 83 6.80 85.00 30.0 85.0 9.00 9.00
## 84 8.80 81.00 30.0 88.0 33.00 0.00
## 85 6.20 90.00 32.0 100.0 7.00 5.00
## 86 4.10 43.00 65.0 50.0 41.00 5.00
## 87 8.80 39.00 89.0 51.0 26.00 6.00
## 88 6.30 66.00 46.0 68.0 23.00 3.00
## 89 7.60 26.00 83.0 30.0 12.00 8.00
## 90 4.20 52.00 61.0 61.0 10.00 0.00
## 91 4.90 70.00 50.0 87.0 22.00 1.00
## 92 5.10 40.00 86.0 54.0 36.00 9.00
## 93 5.90 55.00 63.0 59.0 15.00 6.00
## 94 5.40 28.00 85.0 39.0 47.00 3.00
## 95 6.50 47.00 66.0 64.0 16.00 3.00
## 96 8.30 21.00 100.0 30.0 22.00 7.00
## 97 4.10 43.00 79.0 43.0 14.00 9.00
## 98 8.80 83.00 40.0 85.0 9.00 0.00
## 99 7.90 87.00 30.0 88.0 5.00 2.00
## 100 7.80 58.00 51.0 72.0 37.00 4.00
## 101 7.10 84.00 30.0 89.0 26.00 6.00
## 102 4.90 47.00 52.0 55.0 25.00 4.00
## 103 7.80 64.00 58.0 75.0 12.00 9.00
## 104 5.70 77.00 31.5 92.5 6.00 2.00
## 105 6.70 46.00 54.0 54.0 8.00 3.00
## 106 8.70 49.00 52.0 61.0 42.00 1.00
## 107 7.40 50.00 58.0 56.0 10.00 6.00
## 108 5.40 48.00 62.0 64.0 10.00 6.00
## 109 6.20 85.00 34.0 85.0 48.00 4.00
## 110 4.40 66.00 54.0 82.0 14.00 9.00
## 111 4.70 84.00 42.0 100.0 12.00 1.00
## 112 7.40 33.00 92.0 33.0 38.00 8.00
## 113 7.20 81.00 30.0 90.0 2.00 6.00
## 114 6.60 77.00 45.0 96.0 18.00 4.00
## 115 5.70 72.00 35.0 78.0 6.00 5.00
## 116 5.20 90.00 30.0 100.0 19.00 4.00
## 117 7.70 36.00 71.0 53.0 16.00 8.00
## 118 7.70 86.00 30.0 88.0 6.00 6.00
## 119 8.40 44.00 73.0 62.0 50.00 3.00
## 120 8.90 48.00 77.0 59.0 16.00 9.00
## 121 7.00 71.00 43.0 85.0 12.00 1.00
## 122 7.30 77.00 45.0 93.0 7.00 5.00
## 123 8.40 22.00 97.0 37.0 13.00 1.00
## 124 8.30 63.00 36.0 81.0 22.00 4.00
## 125 7.10 88.00 30.0 90.0 13.00 8.00
## 126 4.30 81.00 36.0 100.0 14.00 3.00
## 127 6.50 36.00 78.0 40.0 40.00 6.00
## 128 5.30 49.00 56.0 53.0 11.00 9.00
## 129 7.20 38.00 72.0 47.0 9.00 8.00
## 130 7.40 77.00 30.0 78.0 40.00 6.00
## 131 5.20 21.00 80.0 30.0 8.00 9.00
## 132 7.80 64.00 62.0 81.0 7.00 1.00
## 133 7.80 30.00 81.0 33.0 24.00 6.00
## 134 6.30 52.00 56.0 53.0 16.00 3.00
## 135 6.90 39.00 69.0 54.0 36.00 9.00
## 136 5.60 73.00 38.0 73.0 17.00 3.00
## 137 5.70 81.00 30.0 98.0 22.00 7.00
## 138 6.70 48.00 70.0 65.0 4.00 1.00
## 139 8.70 45.00 68.0 53.0 45.00 5.00
## 140 8.90 94.00 30.0 99.0 12.00 1.00
## 141 4.10 82.00 30.0 100.0 36.00 9.00
## 142 5.50 55.00 62.0 74.0 7.00 4.00
## 143 7.30 72.00 41.0 89.0 10.00 1.00
## 144 7.90 62.00 51.0 69.0 24.00 3.00
## 145 4.50 76.00 42.0 84.0 30.00 5.00
## 146 7.00 24.50 94.5 33.5 10.00 8.00
## 147 7.50 75.00 49.0 90.0 11.00 1.00
## 148 4.30 64.00 43.0 79.0 13.00 2.00
## 149 7.00 67.00 38.0 69.0 13.00 2.00
## 150 5.40 68.00 48.0 85.0 27.00 9.00
## 151 8.30 21.00 93.0 32.0 6.00 4.00
## 152 4.10 36.00 82.0 47.0 21.00 5.00
## 153 5.60 82.00 30.0 83.0 16.00 7.00
## 154 8.00 27.00 83.0 42.0 34.00 1.00
## 155 5.00 48.00 79.0 49.0 33.00 9.00
## 156 5.65 87.50 30.0 100.0 6.50 4.50
## 157 5.60 80.00 34.0 81.0 5.00 8.00
## 158 4.90 49.00 60.0 58.0 12.00 1.00
## 159 5.20 41.00 71.0 59.0 23.00 2.00
## 160 6.10 64.00 59.0 82.0 26.00 3.00
## 161 5.00 26.00 95.0 30.0 10.00 3.00
## 162 8.50 73.00 39.0 75.0 20.00 6.00
## 163 6.90 23.00 76.0 34.0 25.00 6.00
## 164 4.70 31.00 70.0 47.0 5.00 6.00
## 165 8.60 62.00 54.0 79.0 7.00 5.00
## 166 4.20 55.00 57.0 66.0 20.00 2.00
## 167 6.40 36.00 82.0 54.0 38.00 6.00
## 168 5.40 57.00 49.0 75.0 3.00 5.00
## 169 5.50 63.00 54.0 66.0 7.00 5.00
## 170 5.40 48.00 73.0 53.0 10.00 6.00
## 171 6.00 61.00 43.0 73.0 27.00 0.00
## 172 5.90 24.00 81.0 30.0 4.00 7.00
## 173 6.10 46.00 64.0 60.0 14.00 0.00
## 174 7.50 68.00 32.0 83.0 12.00 7.00
## 175 7.30 20.00 90.0 38.0 6.00 9.00
## 176 8.10 40.00 73.0 49.0 11.00 5.00
## 177 8.90 36.00 78.0 47.0 42.00 7.00
## 178 4.80 83.00 30.0 99.0 5.00 8.00
## 179 4.10 32.00 85.0 36.0 7.00 4.00
## 180 6.40 33.00 77.0 38.0 11.00 3.00
## 181 6.60 88.00 30.0 100.0 9.00 0.00
## 182 6.40 23.00 95.0 30.0 13.00 3.00
## 183 7.50 57.00 70.0 74.0 26.00 0.00
## 184 8.90 30.00 78.0 34.0 34.00 7.00
## 185 4.30 51.00 64.0 58.0 18.00 9.00
## 186 4.40 89.00 30.0 100.0 1.00 9.00
## 187 4.40 39.00 72.0 44.0 8.00 4.00
## 188 6.40 84.00 36.0 84.0 14.00 2.00
## 189 5.40 68.00 50.0 74.0 11.00 9.00
## 190 4.10 72.00 50.0 73.0 45.00 2.00
## 191 5.60 26.00 95.0 43.0 22.00 6.00
## 192 7.40 51.00 69.0 53.0 32.00 3.00
## 193 5.50 73.00 52.0 85.0 23.00 6.00
## 194 8.00 35.00 87.0 39.0 18.00 4.00
## 195 7.00 22.00 97.0 40.0 24.00 6.00
## 196 4.60 54.00 52.0 63.0 41.00 7.00
## 197 4.20 28.00 87.0 35.0 42.00 0.00
## 198 6.90 92.50 30.0 99.0 5.00 7.00
## 199 7.00 88.00 30.0 100.0 14.00 6.00
## 200 8.10 28.00 85.0 39.0 7.00 0.00
## 201 8.50 60.00 64.0 67.0 10.00 8.00
## 202 8.50 29.00 84.0 31.0 8.00 8.00
## 203 4.20 45.00 71.0 56.0 9.00 6.00
## 204 4.40 90.00 30.0 100.0 3.00 7.00
## 205 5.90 84.00 39.0 90.0 8.00 1.00
## 206 4.60 81.00 32.0 94.0 12.00 9.00
## 207 8.20 70.00 50.0 89.0 37.00 0.00
## 208 8.60 46.00 72.0 56.0 10.00 2.00
## 209 6.60 34.00 85.0 36.0 26.00 7.00
## 210 4.60 37.00 73.0 39.0 21.00 3.00
## 211 6.90 26.00 90.0 30.0 11.00 1.00
## 212 8.40 88.00 30.0 97.0 28.00 8.00
## 213 5.10 35.00 81.0 50.0 15.00 9.00
## 214 5.80 65.00 56.0 74.0 10.00 8.00
## 215 7.50 50.00 55.0 53.0 18.00 9.00
## 216 5.10 85.00 36.0 100.0 17.00 8.00
## 217 4.90 45.00 74.0 62.0 11.00 5.00
## 218 4.70 33.00 78.0 41.0 9.00 7.00
## 219 4.40 44.00 75.0 60.0 8.00 4.00
## 220 8.10 76.00 41.0 95.0 12.00 2.00
## 221 7.80 79.00 30.0 85.0 19.00 6.00
## 222 4.60 41.00 62.0 53.0 14.00 5.00
## 223 4.30 39.00 76.0 51.0 27.00 0.00
## 224 7.20 46.00 63.0 62.0 16.00 3.00
## 225 5.00 88.00 30.0 100.0 22.00 9.00
## 226 8.20 25.00 85.0 40.0 15.00 8.00
## 227 4.00 74.00 44.0 84.0 10.00 1.00
## 228 4.90 23.00 99.0 30.0 9.00 1.00
## 229 5.00 42.00 73.0 45.0 8.00 3.00
## 230 4.70 70.00 40.0 89.0 10.00 8.00
## 231 6.90 91.00 30.0 100.0 14.00 6.00
## 232 6.80 92.00 30.0 100.0 11.00 8.00
## 233 6.50 61.00 43.0 72.0 10.00 5.00
## 234 7.10 51.00 75.0 51.0 14.00 7.00
## 235 8.20 28.00 91.0 33.0 13.00 0.00
## 236 7.90 34.00 69.0 35.0 17.00 8.00
## 237 6.50 89.00 30.0 91.0 19.00 1.00
## 238 6.90 89.00 30.0 100.0 26.00 9.00
## 239 4.60 55.00 56.0 71.0 10.00 5.00
## 240 8.20 78.00 33.0 84.0 46.00 9.00
## 241 4.30 24.00 79.0 41.0 23.00 4.00
## 242 8.40 71.00 34.0 90.0 9.00 8.00
## 243 6.40 71.00 30.0 85.0 3.00 8.00
## 244 5.20 26.00 87.0 41.0 31.00 7.00
## 245 6.90 41.00 85.0 45.0 8.00 0.00
## 246 7.50 77.00 47.0 80.0 28.00 8.00
## 247 7.00 91.00 30.0 100.0 29.00 5.00
## 248 6.70 78.00 42.0 96.0 18.00 6.00
## 249 8.60 60.00 56.0 69.0 32.00 1.00
## 250 5.50 80.00 30.0 98.0 20.00 7.00
## 251 8.80 71.00 39.0 75.0 5.00 9.00
## 252 6.30 34.00 71.0 44.0 11.00 3.00
## 253 8.80 38.00 73.0 41.0 29.00 1.00
## 254 7.00 33.00 86.0 40.0 23.00 4.00
## 255 5.70 48.00 51.0 63.0 9.00 0.00
## 256 5.00 47.00 72.0 51.0 13.00 9.00
## 257 6.60 86.00 30.0 89.0 16.00 7.00
## 258 6.10 29.00 79.0 32.0 23.00 0.00
## 259 8.00 54.00 49.0 67.0 8.00 8.00
## 260 4.30 48.00 74.0 59.0 6.00 1.00
## 261 5.20 67.00 39.0 78.0 26.00 0.00
## 262 4.30 47.00 74.0 62.0 13.00 6.00
## 263 4.10 62.00 55.0 77.0 12.00 0.00
## 264 7.90 69.00 45.0 74.0 9.00 9.00
## 265 7.70 23.00 85.0 30.0 36.00 9.00
## 266 6.20 65.00 41.0 73.0 1.00 2.00
## 267 7.70 54.00 41.0 64.0 3.00 1.00
## 268 6.10 87.00 30.0 90.0 8.00 2.00
## 269 5.10 44.00 63.0 59.0 13.00 0.00
## 270 5.80 49.00 58.0 65.0 41.00 2.00
## 271 7.30 49.00 64.0 59.0 11.00 6.00
## 272 7.60 49.00 51.0 49.0 29.00 1.00
## 273 5.70 21.00 82.0 30.0 12.00 1.00
## 274 4.70 80.00 30.0 89.0 14.00 7.00
## 275 7.70 71.00 39.0 80.0 29.00 5.00
## 276 7.40 49.00 62.0 51.0 14.00 2.00
## 277 8.90 57.00 53.0 65.0 45.00 2.00
## 278 5.50 77.00 43.0 91.0 22.00 6.00
## 279 8.20 81.00 30.0 81.0 9.00 9.00
## 280 8.70 58.00 53.0 61.0 22.00 3.00
## 281 8.60 61.00 54.0 63.0 6.00 6.00
## 282 8.70 42.00 79.0 58.0 20.00 8.00
## 283 8.10 45.00 65.0 61.0 40.00 8.00
## 284 5.50 79.00 30.0 87.0 13.00 7.00
## 285 8.30 86.00 30.0 91.0 25.00 7.00
## 286 7.10 86.00 30.0 91.0 7.00 5.00
df_ms_orig$cluster_ms_f <- as.factor(df_ms_orig$cluster_ms)
par(mfrow=c(2,2), mar=c(4,4,3,1))
for (v in vars_plot) {
boxplot(df_ms_orig[[v]] ~ df_ms_orig$cluster_ms_f,
main=paste("Mean Shift:", v),
xlab="Cluster", ylab=v,
col=rainbow(n_cluster_ms), border="gray30")
}
par(mfrow=c(1,1))
cat("\nINTERPRETASI CLUSTER MEAN SHIFT\n")
##
## INTERPRETASI CLUSTER MEAN SHIFT
for (i in sort(unique(ms_labels))) {
row <- ms_profile[ms_profile$cluster_ms == i, ]
cat(sprintf("\nCluster %d (%d developer):\n", i, row$n))
cat(sprintf(" Jam coding : %.1f jam/hari\n", row$Jam_Coding))
cat(sprintf(" Tingkat stres: %.1f / 100\n", row$Level_Stres))
cat(sprintf(" Sukses tugas : %.1f%%\n", row$Sukses_Tugas))
cat(sprintf(" Jam tidur : %.1f jam\n", row$Jam_Tidur))
label <- ifelse(row$Sukses_Tugas > 65 & row$Level_Stres < 60,
"→ Developer PRODUKTIF",
ifelse(row$Level_Stres > 75, "→ Developer BURNOUT",
"→ Developer SEDANG"))
cat(label, "\n")
}
##
## Cluster 1 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 63.0%
## Jam tidur : 4.4 jam
## → Developer SEDANG
##
## Cluster 2 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 8.8 jam
## → Developer PRODUKTIF
##
## Cluster 3 (2 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 55.0 / 100
## Sukses tugas : 59.5%
## Jam tidur : 5.4 jam
## → Developer SEDANG
##
## Cluster 4 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 66.0%
## Jam tidur : 5.3 jam
## → Developer SEDANG
##
## Cluster 5 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 34.0%
## Jam tidur : 4.0 jam
## → Developer BURNOUT
##
## Cluster 6 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 92.0%
## Jam tidur : 8.5 jam
## → Developer PRODUKTIF
##
## Cluster 7 (5 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 43.8 / 100
## Sukses tugas : 69.4%
## Jam tidur : 6.5 jam
## → Developer PRODUKTIF
##
## Cluster 8 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 93.0%
## Jam tidur : 8.5 jam
## → Developer PRODUKTIF
##
## Cluster 9 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 36.0 / 100
## Sukses tugas : 87.0%
## Jam tidur : 8.8 jam
## → Developer PRODUKTIF
##
## Cluster 10 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 92.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.0 jam
## → Developer BURNOUT
##
## Cluster 11 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 33.0%
## Jam tidur : 8.7 jam
## → Developer BURNOUT
##
## Cluster 12 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 7.0 jam
## → Developer SEDANG
##
## Cluster 13 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 48.0 / 100
## Sukses tugas : 77.0%
## Jam tidur : 8.4 jam
## → Developer PRODUKTIF
##
## Cluster 14 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 42.0%
## Jam tidur : 6.6 jam
## → Developer SEDANG
##
## Cluster 15 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 79.0 / 100
## Sukses tugas : 37.0%
## Jam tidur : 7.8 jam
## → Developer BURNOUT
##
## Cluster 16 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 48.0%
## Jam tidur : 5.4 jam
## → Developer SEDANG
##
## Cluster 17 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 57.0%
## Jam tidur : 7.7 jam
## → Developer SEDANG
##
## Cluster 18 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 95.0 / 100
## Sukses tugas : 38.0%
## Jam tidur : 8.1 jam
## → Developer BURNOUT
##
## Cluster 19 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 53.0%
## Jam tidur : 4.2 jam
## → Developer SEDANG
##
## Cluster 20 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 46.0%
## Jam tidur : 4.3 jam
## → Developer SEDANG
##
## Cluster 21 (2 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 37.0 / 100
## Sukses tugas : 82.5%
## Jam tidur : 5.6 jam
## → Developer PRODUKTIF
##
## Cluster 22 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 100.0%
## Jam tidur : 7.5 jam
## → Developer PRODUKTIF
##
## Cluster 23 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 93.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.7 jam
## → Developer BURNOUT
##
## Cluster 24 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 77.0%
## Jam tidur : 9.0 jam
## → Developer PRODUKTIF
##
## Cluster 25 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 8.3 jam
## → Developer PRODUKTIF
##
## Cluster 26 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 72.0%
## Jam tidur : 5.5 jam
## → Developer SEDANG
##
## Cluster 27 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 4.9 jam
## → Developer BURNOUT
##
## Cluster 28 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 7.1 jam
## → Developer SEDANG
##
## Cluster 29 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.0 jam
## → Developer BURNOUT
##
## Cluster 30 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 96.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.3 jam
## → Developer BURNOUT
##
## Cluster 31 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 4.3 jam
## → Developer SEDANG
##
## Cluster 32 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 32.0 / 100
## Sukses tugas : 93.0%
## Jam tidur : 4.9 jam
## → Developer PRODUKTIF
##
## Cluster 33 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 70.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 7.7 jam
## → Developer SEDANG
##
## Cluster 34 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 83.0 / 100
## Sukses tugas : 32.0%
## Jam tidur : 7.6 jam
## → Developer BURNOUT
##
## Cluster 35 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 65.0 / 100
## Sukses tugas : 60.0%
## Jam tidur : 8.4 jam
## → Developer SEDANG
##
## Cluster 36 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.8 jam
## → Developer BURNOUT
##
## Cluster 37 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 96.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.4 jam
## → Developer BURNOUT
##
## Cluster 38 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 7.1 jam
## → Developer SEDANG
##
## Cluster 39 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.6 jam
## → Developer BURNOUT
##
## Cluster 40 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 50.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 6.3 jam
## → Developer PRODUKTIF
##
## Cluster 41 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 93.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 9.0 jam
## → Developer BURNOUT
##
## Cluster 42 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 49.0 / 100
## Sukses tugas : 63.0%
## Jam tidur : 6.2 jam
## → Developer SEDANG
##
## Cluster 43 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 65.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 4.8 jam
## → Developer SEDANG
##
## Cluster 44 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 53.0%
## Jam tidur : 6.6 jam
## → Developer SEDANG
##
## Cluster 45 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 93.0 / 100
## Sukses tugas : 38.0%
## Jam tidur : 4.2 jam
## → Developer BURNOUT
##
## Cluster 46 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 98.0%
## Jam tidur : 5.6 jam
## → Developer PRODUKTIF
##
## Cluster 47 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 41.0 / 100
## Sukses tugas : 90.0%
## Jam tidur : 7.1 jam
## → Developer PRODUKTIF
##
## Cluster 48 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 77.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 6.0 jam
## → Developer BURNOUT
##
## Cluster 49 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 35.0%
## Jam tidur : 6.8 jam
## → Developer BURNOUT
##
## Cluster 50 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 42.0 / 100
## Sukses tugas : 90.0%
## Jam tidur : 5.7 jam
## → Developer PRODUKTIF
##
## Cluster 51 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 67.0 / 100
## Sukses tugas : 48.0%
## Jam tidur : 4.2 jam
## → Developer SEDANG
##
## Cluster 52 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 92.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.8 jam
## → Developer BURNOUT
##
## Cluster 53 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 50.0%
## Jam tidur : 8.5 jam
## → Developer SEDANG
##
## Cluster 54 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 66.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 5.7 jam
## → Developer SEDANG
##
## Cluster 55 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 48.0%
## Jam tidur : 7.7 jam
## → Developer BURNOUT
##
## Cluster 56 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 40.0%
## Jam tidur : 4.9 jam
## → Developer SEDANG
##
## Cluster 57 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 94.0 / 100
## Sukses tugas : 32.0%
## Jam tidur : 7.9 jam
## → Developer BURNOUT
##
## Cluster 58 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 68.0%
## Jam tidur : 8.4 jam
## → Developer SEDANG
##
## Cluster 59 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 55.0%
## Jam tidur : 7.7 jam
## → Developer SEDANG
##
## Cluster 60 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 46.0 / 100
## Sukses tugas : 76.0%
## Jam tidur : 5.3 jam
## → Developer PRODUKTIF
##
## Cluster 61 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 42.0 / 100
## Sukses tugas : 83.0%
## Jam tidur : 8.2 jam
## → Developer PRODUKTIF
##
## Cluster 62 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.8 jam
## → Developer BURNOUT
##
## Cluster 63 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 53.0%
## Jam tidur : 7.2 jam
## → Developer SEDANG
##
## Cluster 64 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 55.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 6.2 jam
## → Developer PRODUKTIF
##
## Cluster 65 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 6.3 jam
## → Developer SEDANG
##
## Cluster 66 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 79.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.2 jam
## → Developer BURNOUT
##
## Cluster 67 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 57.0%
## Jam tidur : 4.5 jam
## → Developer SEDANG
##
## Cluster 68 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 97.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.2 jam
## → Developer BURNOUT
##
## Cluster 69 (2 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 84.0%
## Jam tidur : 7.3 jam
## → Developer PRODUKTIF
##
## Cluster 70 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 48.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 7.0 jam
## → Developer PRODUKTIF
##
## Cluster 71 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 87.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.2 jam
## → Developer BURNOUT
##
## Cluster 72 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 68.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 5.7 jam
## → Developer SEDANG
##
## Cluster 73 (3 developer):
## Jam coding : 1.7 jam/hari
## Tingkat stres: 95.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.2 jam
## → Developer BURNOUT
##
## Cluster 74 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 80.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.4 jam
## → Developer BURNOUT
##
## Cluster 75 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 44.0%
## Jam tidur : 4.4 jam
## → Developer BURNOUT
##
## Cluster 76 (2 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 44.0 / 100
## Sukses tugas : 77.5%
## Jam tidur : 5.0 jam
## → Developer PRODUKTIF
##
## Cluster 77 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 97.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.5 jam
## → Developer BURNOUT
##
## Cluster 78 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 56.0 / 100
## Sukses tugas : 55.0%
## Jam tidur : 7.9 jam
## → Developer SEDANG
##
## Cluster 79 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 7.2 jam
## → Developer PRODUKTIF
##
## Cluster 80 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 81.0%
## Jam tidur : 5.4 jam
## → Developer PRODUKTIF
##
## Cluster 81 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 100.0%
## Jam tidur : 5.6 jam
## → Developer PRODUKTIF
##
## Cluster 82 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 75.0%
## Jam tidur : 4.5 jam
## → Developer PRODUKTIF
##
## Cluster 83 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.8 jam
## → Developer BURNOUT
##
## Cluster 84 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 88.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.8 jam
## → Developer BURNOUT
##
## Cluster 85 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 32.0%
## Jam tidur : 6.2 jam
## → Developer BURNOUT
##
## Cluster 86 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 50.0 / 100
## Sukses tugas : 65.0%
## Jam tidur : 4.1 jam
## → Developer SEDANG
##
## Cluster 87 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 51.0 / 100
## Sukses tugas : 89.0%
## Jam tidur : 8.8 jam
## → Developer PRODUKTIF
##
## Cluster 88 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 68.0 / 100
## Sukses tugas : 46.0%
## Jam tidur : 6.3 jam
## → Developer SEDANG
##
## Cluster 89 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 83.0%
## Jam tidur : 7.6 jam
## → Developer PRODUKTIF
##
## Cluster 90 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 61.0%
## Jam tidur : 4.2 jam
## → Developer SEDANG
##
## Cluster 91 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 87.0 / 100
## Sukses tugas : 50.0%
## Jam tidur : 4.9 jam
## → Developer BURNOUT
##
## Cluster 92 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 54.0 / 100
## Sukses tugas : 86.0%
## Jam tidur : 5.1 jam
## → Developer PRODUKTIF
##
## Cluster 93 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 63.0%
## Jam tidur : 5.9 jam
## → Developer SEDANG
##
## Cluster 94 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 5.4 jam
## → Developer PRODUKTIF
##
## Cluster 95 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 64.0 / 100
## Sukses tugas : 66.0%
## Jam tidur : 6.5 jam
## → Developer SEDANG
##
## Cluster 96 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 100.0%
## Jam tidur : 8.3 jam
## → Developer PRODUKTIF
##
## Cluster 97 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 43.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 4.1 jam
## → Developer PRODUKTIF
##
## Cluster 98 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 40.0%
## Jam tidur : 8.8 jam
## → Developer BURNOUT
##
## Cluster 99 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 88.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.9 jam
## → Developer BURNOUT
##
## Cluster 100 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 72.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 7.8 jam
## → Developer SEDANG
##
## Cluster 101 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.1 jam
## → Developer BURNOUT
##
## Cluster 102 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 55.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 4.9 jam
## → Developer SEDANG
##
## Cluster 103 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 58.0%
## Jam tidur : 7.8 jam
## → Developer SEDANG
##
## Cluster 104 (2 developer):
## Jam coding : 1.5 jam/hari
## Tingkat stres: 92.5 / 100
## Sukses tugas : 31.5%
## Jam tidur : 5.7 jam
## → Developer BURNOUT
##
## Cluster 105 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 54.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 6.7 jam
## → Developer SEDANG
##
## Cluster 106 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 8.7 jam
## → Developer SEDANG
##
## Cluster 107 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 56.0 / 100
## Sukses tugas : 58.0%
## Jam tidur : 7.4 jam
## → Developer SEDANG
##
## Cluster 108 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 64.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 5.4 jam
## → Developer SEDANG
##
## Cluster 109 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 34.0%
## Jam tidur : 6.2 jam
## → Developer BURNOUT
##
## Cluster 110 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 82.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 4.4 jam
## → Developer BURNOUT
##
## Cluster 111 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 42.0%
## Jam tidur : 4.7 jam
## → Developer BURNOUT
##
## Cluster 112 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 33.0 / 100
## Sukses tugas : 92.0%
## Jam tidur : 7.4 jam
## → Developer PRODUKTIF
##
## Cluster 113 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.2 jam
## → Developer BURNOUT
##
## Cluster 114 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 96.0 / 100
## Sukses tugas : 45.0%
## Jam tidur : 6.6 jam
## → Developer BURNOUT
##
## Cluster 115 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 78.0 / 100
## Sukses tugas : 35.0%
## Jam tidur : 5.7 jam
## → Developer BURNOUT
##
## Cluster 116 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.2 jam
## → Developer BURNOUT
##
## Cluster 117 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 7.7 jam
## → Developer PRODUKTIF
##
## Cluster 118 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 88.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.7 jam
## → Developer BURNOUT
##
## Cluster 119 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 8.4 jam
## → Developer SEDANG
##
## Cluster 120 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 77.0%
## Jam tidur : 8.9 jam
## → Developer PRODUKTIF
##
## Cluster 121 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 7.0 jam
## → Developer BURNOUT
##
## Cluster 122 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 93.0 / 100
## Sukses tugas : 45.0%
## Jam tidur : 7.3 jam
## → Developer BURNOUT
##
## Cluster 123 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 37.0 / 100
## Sukses tugas : 97.0%
## Jam tidur : 8.4 jam
## → Developer PRODUKTIF
##
## Cluster 124 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 81.0 / 100
## Sukses tugas : 36.0%
## Jam tidur : 8.3 jam
## → Developer BURNOUT
##
## Cluster 125 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.1 jam
## → Developer BURNOUT
##
## Cluster 126 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 36.0%
## Jam tidur : 4.3 jam
## → Developer BURNOUT
##
## Cluster 127 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 40.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 6.5 jam
## → Developer PRODUKTIF
##
## Cluster 128 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 56.0%
## Jam tidur : 5.3 jam
## → Developer SEDANG
##
## Cluster 129 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 47.0 / 100
## Sukses tugas : 72.0%
## Jam tidur : 7.2 jam
## → Developer PRODUKTIF
##
## Cluster 130 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 78.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.4 jam
## → Developer BURNOUT
##
## Cluster 131 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 80.0%
## Jam tidur : 5.2 jam
## → Developer PRODUKTIF
##
## Cluster 132 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 81.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 7.8 jam
## → Developer BURNOUT
##
## Cluster 133 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 33.0 / 100
## Sukses tugas : 81.0%
## Jam tidur : 7.8 jam
## → Developer PRODUKTIF
##
## Cluster 134 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 56.0%
## Jam tidur : 6.3 jam
## → Developer SEDANG
##
## Cluster 135 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 54.0 / 100
## Sukses tugas : 69.0%
## Jam tidur : 6.9 jam
## → Developer PRODUKTIF
##
## Cluster 136 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 38.0%
## Jam tidur : 5.6 jam
## → Developer SEDANG
##
## Cluster 137 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 98.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.7 jam
## → Developer BURNOUT
##
## Cluster 138 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 65.0 / 100
## Sukses tugas : 70.0%
## Jam tidur : 6.7 jam
## → Developer SEDANG
##
## Cluster 139 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 68.0%
## Jam tidur : 8.7 jam
## → Developer PRODUKTIF
##
## Cluster 140 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 99.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.9 jam
## → Developer BURNOUT
##
## Cluster 141 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.1 jam
## → Developer BURNOUT
##
## Cluster 142 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 5.5 jam
## → Developer SEDANG
##
## Cluster 143 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 41.0%
## Jam tidur : 7.3 jam
## → Developer BURNOUT
##
## Cluster 144 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 7.9 jam
## → Developer SEDANG
##
## Cluster 145 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 84.0 / 100
## Sukses tugas : 42.0%
## Jam tidur : 4.5 jam
## → Developer BURNOUT
##
## Cluster 146 (2 developer):
## Jam coding : 4.5 jam/hari
## Tingkat stres: 33.5 / 100
## Sukses tugas : 94.5%
## Jam tidur : 7.0 jam
## → Developer PRODUKTIF
##
## Cluster 147 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 49.0%
## Jam tidur : 7.5 jam
## → Developer BURNOUT
##
## Cluster 148 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 79.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 4.3 jam
## → Developer BURNOUT
##
## Cluster 149 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 38.0%
## Jam tidur : 7.0 jam
## → Developer SEDANG
##
## Cluster 150 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 48.0%
## Jam tidur : 5.4 jam
## → Developer BURNOUT
##
## Cluster 151 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 32.0 / 100
## Sukses tugas : 93.0%
## Jam tidur : 8.3 jam
## → Developer PRODUKTIF
##
## Cluster 152 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 47.0 / 100
## Sukses tugas : 82.0%
## Jam tidur : 4.1 jam
## → Developer PRODUKTIF
##
## Cluster 153 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 83.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.6 jam
## → Developer BURNOUT
##
## Cluster 154 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 42.0 / 100
## Sukses tugas : 83.0%
## Jam tidur : 8.0 jam
## → Developer PRODUKTIF
##
## Cluster 155 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 49.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 5.0 jam
## → Developer PRODUKTIF
##
## Cluster 156 (2 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.6 jam
## → Developer BURNOUT
##
## Cluster 157 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 81.0 / 100
## Sukses tugas : 34.0%
## Jam tidur : 5.6 jam
## → Developer BURNOUT
##
## Cluster 158 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 58.0 / 100
## Sukses tugas : 60.0%
## Jam tidur : 4.9 jam
## → Developer SEDANG
##
## Cluster 159 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 5.2 jam
## → Developer PRODUKTIF
##
## Cluster 160 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 82.0 / 100
## Sukses tugas : 59.0%
## Jam tidur : 6.1 jam
## → Developer BURNOUT
##
## Cluster 161 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 95.0%
## Jam tidur : 5.0 jam
## → Developer PRODUKTIF
##
## Cluster 162 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 39.0%
## Jam tidur : 8.5 jam
## → Developer SEDANG
##
## Cluster 163 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 34.0 / 100
## Sukses tugas : 76.0%
## Jam tidur : 6.9 jam
## → Developer PRODUKTIF
##
## Cluster 164 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 47.0 / 100
## Sukses tugas : 70.0%
## Jam tidur : 4.7 jam
## → Developer PRODUKTIF
##
## Cluster 165 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 79.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 8.6 jam
## → Developer BURNOUT
##
## Cluster 166 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 66.0 / 100
## Sukses tugas : 57.0%
## Jam tidur : 4.2 jam
## → Developer SEDANG
##
## Cluster 167 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 54.0 / 100
## Sukses tugas : 82.0%
## Jam tidur : 6.4 jam
## → Developer PRODUKTIF
##
## Cluster 168 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 49.0%
## Jam tidur : 5.4 jam
## → Developer SEDANG
##
## Cluster 169 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 66.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 5.5 jam
## → Developer SEDANG
##
## Cluster 170 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 5.4 jam
## → Developer PRODUKTIF
##
## Cluster 171 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 6.0 jam
## → Developer SEDANG
##
## Cluster 172 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 81.0%
## Jam tidur : 5.9 jam
## → Developer PRODUKTIF
##
## Cluster 173 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 60.0 / 100
## Sukses tugas : 64.0%
## Jam tidur : 6.1 jam
## → Developer SEDANG
##
## Cluster 174 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 83.0 / 100
## Sukses tugas : 32.0%
## Jam tidur : 7.5 jam
## → Developer BURNOUT
##
## Cluster 175 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 38.0 / 100
## Sukses tugas : 90.0%
## Jam tidur : 7.3 jam
## → Developer PRODUKTIF
##
## Cluster 176 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 49.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 8.1 jam
## → Developer PRODUKTIF
##
## Cluster 177 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 47.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 8.9 jam
## → Developer PRODUKTIF
##
## Cluster 178 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 99.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.8 jam
## → Developer BURNOUT
##
## Cluster 179 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 36.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 4.1 jam
## → Developer PRODUKTIF
##
## Cluster 180 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 38.0 / 100
## Sukses tugas : 77.0%
## Jam tidur : 6.4 jam
## → Developer PRODUKTIF
##
## Cluster 181 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.6 jam
## → Developer BURNOUT
##
## Cluster 182 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 95.0%
## Jam tidur : 6.4 jam
## → Developer PRODUKTIF
##
## Cluster 183 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 70.0%
## Jam tidur : 7.5 jam
## → Developer SEDANG
##
## Cluster 184 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 34.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 8.9 jam
## → Developer PRODUKTIF
##
## Cluster 185 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 58.0 / 100
## Sukses tugas : 64.0%
## Jam tidur : 4.3 jam
## → Developer SEDANG
##
## Cluster 186 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.4 jam
## → Developer BURNOUT
##
## Cluster 187 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 44.0 / 100
## Sukses tugas : 72.0%
## Jam tidur : 4.4 jam
## → Developer PRODUKTIF
##
## Cluster 188 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 84.0 / 100
## Sukses tugas : 36.0%
## Jam tidur : 6.4 jam
## → Developer BURNOUT
##
## Cluster 189 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 50.0%
## Jam tidur : 5.4 jam
## → Developer SEDANG
##
## Cluster 190 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 50.0%
## Jam tidur : 4.1 jam
## → Developer SEDANG
##
## Cluster 191 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 43.0 / 100
## Sukses tugas : 95.0%
## Jam tidur : 5.6 jam
## → Developer PRODUKTIF
##
## Cluster 192 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 69.0%
## Jam tidur : 7.4 jam
## → Developer PRODUKTIF
##
## Cluster 193 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 5.5 jam
## → Developer BURNOUT
##
## Cluster 194 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 87.0%
## Jam tidur : 8.0 jam
## → Developer PRODUKTIF
##
## Cluster 195 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 40.0 / 100
## Sukses tugas : 97.0%
## Jam tidur : 7.0 jam
## → Developer PRODUKTIF
##
## Cluster 196 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 52.0%
## Jam tidur : 4.6 jam
## → Developer SEDANG
##
## Cluster 197 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 35.0 / 100
## Sukses tugas : 87.0%
## Jam tidur : 4.2 jam
## → Developer PRODUKTIF
##
## Cluster 198 (2 developer):
## Jam coding : 1.5 jam/hari
## Tingkat stres: 99.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.9 jam
## → Developer BURNOUT
##
## Cluster 199 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.0 jam
## → Developer BURNOUT
##
## Cluster 200 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 8.1 jam
## → Developer PRODUKTIF
##
## Cluster 201 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 67.0 / 100
## Sukses tugas : 64.0%
## Jam tidur : 8.5 jam
## → Developer SEDANG
##
## Cluster 202 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 31.0 / 100
## Sukses tugas : 84.0%
## Jam tidur : 8.5 jam
## → Developer PRODUKTIF
##
## Cluster 203 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 56.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 4.2 jam
## → Developer PRODUKTIF
##
## Cluster 204 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.4 jam
## → Developer BURNOUT
##
## Cluster 205 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 39.0%
## Jam tidur : 5.9 jam
## → Developer BURNOUT
##
## Cluster 206 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 94.0 / 100
## Sukses tugas : 32.0%
## Jam tidur : 4.6 jam
## → Developer BURNOUT
##
## Cluster 207 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 50.0%
## Jam tidur : 8.2 jam
## → Developer BURNOUT
##
## Cluster 208 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 56.0 / 100
## Sukses tugas : 72.0%
## Jam tidur : 8.6 jam
## → Developer PRODUKTIF
##
## Cluster 209 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 36.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 6.6 jam
## → Developer PRODUKTIF
##
## Cluster 210 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 39.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 4.6 jam
## → Developer PRODUKTIF
##
## Cluster 211 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 90.0%
## Jam tidur : 6.9 jam
## → Developer PRODUKTIF
##
## Cluster 212 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 97.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.4 jam
## → Developer BURNOUT
##
## Cluster 213 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 50.0 / 100
## Sukses tugas : 81.0%
## Jam tidur : 5.1 jam
## → Developer PRODUKTIF
##
## Cluster 214 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 56.0%
## Jam tidur : 5.8 jam
## → Developer SEDANG
##
## Cluster 215 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 55.0%
## Jam tidur : 7.5 jam
## → Developer SEDANG
##
## Cluster 216 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 36.0%
## Jam tidur : 5.1 jam
## → Developer BURNOUT
##
## Cluster 217 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 74.0%
## Jam tidur : 4.9 jam
## → Developer SEDANG
##
## Cluster 218 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 41.0 / 100
## Sukses tugas : 78.0%
## Jam tidur : 4.7 jam
## → Developer PRODUKTIF
##
## Cluster 219 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 60.0 / 100
## Sukses tugas : 75.0%
## Jam tidur : 4.4 jam
## → Developer SEDANG
##
## Cluster 220 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 95.0 / 100
## Sukses tugas : 41.0%
## Jam tidur : 8.1 jam
## → Developer BURNOUT
##
## Cluster 221 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.8 jam
## → Developer BURNOUT
##
## Cluster 222 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 53.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 4.6 jam
## → Developer SEDANG
##
## Cluster 223 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 51.0 / 100
## Sukses tugas : 76.0%
## Jam tidur : 4.3 jam
## → Developer PRODUKTIF
##
## Cluster 224 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 63.0%
## Jam tidur : 7.2 jam
## → Developer SEDANG
##
## Cluster 225 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.0 jam
## → Developer BURNOUT
##
## Cluster 226 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 40.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 8.2 jam
## → Developer PRODUKTIF
##
## Cluster 227 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 84.0 / 100
## Sukses tugas : 44.0%
## Jam tidur : 4.0 jam
## → Developer BURNOUT
##
## Cluster 228 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 99.0%
## Jam tidur : 4.9 jam
## → Developer PRODUKTIF
##
## Cluster 229 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 45.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 5.0 jam
## → Developer PRODUKTIF
##
## Cluster 230 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 40.0%
## Jam tidur : 4.7 jam
## → Developer BURNOUT
##
## Cluster 231 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.9 jam
## → Developer BURNOUT
##
## Cluster 232 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.8 jam
## → Developer BURNOUT
##
## Cluster 233 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 72.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 6.5 jam
## → Developer SEDANG
##
## Cluster 234 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 51.0 / 100
## Sukses tugas : 75.0%
## Jam tidur : 7.1 jam
## → Developer PRODUKTIF
##
## Cluster 235 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 33.0 / 100
## Sukses tugas : 91.0%
## Jam tidur : 8.2 jam
## → Developer PRODUKTIF
##
## Cluster 236 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 35.0 / 100
## Sukses tugas : 69.0%
## Jam tidur : 7.9 jam
## → Developer PRODUKTIF
##
## Cluster 237 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.5 jam
## → Developer BURNOUT
##
## Cluster 238 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.9 jam
## → Developer BURNOUT
##
## Cluster 239 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 71.0 / 100
## Sukses tugas : 56.0%
## Jam tidur : 4.6 jam
## → Developer SEDANG
##
## Cluster 240 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 84.0 / 100
## Sukses tugas : 33.0%
## Jam tidur : 8.2 jam
## → Developer BURNOUT
##
## Cluster 241 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 41.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 4.3 jam
## → Developer PRODUKTIF
##
## Cluster 242 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 34.0%
## Jam tidur : 8.4 jam
## → Developer BURNOUT
##
## Cluster 243 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 85.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.4 jam
## → Developer BURNOUT
##
## Cluster 244 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 41.0 / 100
## Sukses tugas : 87.0%
## Jam tidur : 5.2 jam
## → Developer PRODUKTIF
##
## Cluster 245 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 45.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 6.9 jam
## → Developer PRODUKTIF
##
## Cluster 246 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 80.0 / 100
## Sukses tugas : 47.0%
## Jam tidur : 7.5 jam
## → Developer BURNOUT
##
## Cluster 247 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 100.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.0 jam
## → Developer BURNOUT
##
## Cluster 248 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 96.0 / 100
## Sukses tugas : 42.0%
## Jam tidur : 6.7 jam
## → Developer BURNOUT
##
## Cluster 249 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 69.0 / 100
## Sukses tugas : 56.0%
## Jam tidur : 8.6 jam
## → Developer SEDANG
##
## Cluster 250 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 98.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.5 jam
## → Developer BURNOUT
##
## Cluster 251 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 75.0 / 100
## Sukses tugas : 39.0%
## Jam tidur : 8.8 jam
## → Developer SEDANG
##
## Cluster 252 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 44.0 / 100
## Sukses tugas : 71.0%
## Jam tidur : 6.3 jam
## → Developer PRODUKTIF
##
## Cluster 253 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 41.0 / 100
## Sukses tugas : 73.0%
## Jam tidur : 8.8 jam
## → Developer PRODUKTIF
##
## Cluster 254 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 40.0 / 100
## Sukses tugas : 86.0%
## Jam tidur : 7.0 jam
## → Developer PRODUKTIF
##
## Cluster 255 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 5.7 jam
## → Developer SEDANG
##
## Cluster 256 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 51.0 / 100
## Sukses tugas : 72.0%
## Jam tidur : 5.0 jam
## → Developer PRODUKTIF
##
## Cluster 257 (1 developer):
## Jam coding : 11.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.6 jam
## → Developer BURNOUT
##
## Cluster 258 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 32.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 6.1 jam
## → Developer PRODUKTIF
##
## Cluster 259 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 67.0 / 100
## Sukses tugas : 49.0%
## Jam tidur : 8.0 jam
## → Developer SEDANG
##
## Cluster 260 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 74.0%
## Jam tidur : 4.3 jam
## → Developer PRODUKTIF
##
## Cluster 261 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 78.0 / 100
## Sukses tugas : 39.0%
## Jam tidur : 5.2 jam
## → Developer BURNOUT
##
## Cluster 262 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 62.0 / 100
## Sukses tugas : 74.0%
## Jam tidur : 4.3 jam
## → Developer SEDANG
##
## Cluster 263 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 77.0 / 100
## Sukses tugas : 55.0%
## Jam tidur : 4.1 jam
## → Developer BURNOUT
##
## Cluster 264 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 74.0 / 100
## Sukses tugas : 45.0%
## Jam tidur : 7.9 jam
## → Developer SEDANG
##
## Cluster 265 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 85.0%
## Jam tidur : 7.7 jam
## → Developer PRODUKTIF
##
## Cluster 266 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 73.0 / 100
## Sukses tugas : 41.0%
## Jam tidur : 6.2 jam
## → Developer SEDANG
##
## Cluster 267 (1 developer):
## Jam coding : 1.0 jam/hari
## Tingkat stres: 64.0 / 100
## Sukses tugas : 41.0%
## Jam tidur : 7.7 jam
## → Developer SEDANG
##
## Cluster 268 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 90.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 6.1 jam
## → Developer BURNOUT
##
## Cluster 269 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 63.0%
## Jam tidur : 5.1 jam
## → Developer SEDANG
##
## Cluster 270 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 65.0 / 100
## Sukses tugas : 58.0%
## Jam tidur : 5.8 jam
## → Developer SEDANG
##
## Cluster 271 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 59.0 / 100
## Sukses tugas : 64.0%
## Jam tidur : 7.3 jam
## → Developer SEDANG
##
## Cluster 272 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 49.0 / 100
## Sukses tugas : 51.0%
## Jam tidur : 7.6 jam
## → Developer SEDANG
##
## Cluster 273 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 30.0 / 100
## Sukses tugas : 82.0%
## Jam tidur : 5.7 jam
## → Developer PRODUKTIF
##
## Cluster 274 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 89.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 4.7 jam
## → Developer BURNOUT
##
## Cluster 275 (1 developer):
## Jam coding : 9.0 jam/hari
## Tingkat stres: 80.0 / 100
## Sukses tugas : 39.0%
## Jam tidur : 7.7 jam
## → Developer BURNOUT
##
## Cluster 276 (1 developer):
## Jam coding : 3.0 jam/hari
## Tingkat stres: 51.0 / 100
## Sukses tugas : 62.0%
## Jam tidur : 7.4 jam
## → Developer SEDANG
##
## Cluster 277 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 65.0 / 100
## Sukses tugas : 53.0%
## Jam tidur : 8.9 jam
## → Developer SEDANG
##
## Cluster 278 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 43.0%
## Jam tidur : 5.5 jam
## → Developer BURNOUT
##
## Cluster 279 (1 developer):
## Jam coding : 8.0 jam/hari
## Tingkat stres: 81.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.2 jam
## → Developer BURNOUT
##
## Cluster 280 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 53.0%
## Jam tidur : 8.7 jam
## → Developer SEDANG
##
## Cluster 281 (1 developer):
## Jam coding : 4.0 jam/hari
## Tingkat stres: 63.0 / 100
## Sukses tugas : 54.0%
## Jam tidur : 8.6 jam
## → Developer SEDANG
##
## Cluster 282 (1 developer):
## Jam coding : 7.0 jam/hari
## Tingkat stres: 58.0 / 100
## Sukses tugas : 79.0%
## Jam tidur : 8.7 jam
## → Developer PRODUKTIF
##
## Cluster 283 (1 developer):
## Jam coding : 10.0 jam/hari
## Tingkat stres: 61.0 / 100
## Sukses tugas : 65.0%
## Jam tidur : 8.1 jam
## → Developer SEDANG
##
## Cluster 284 (1 developer):
## Jam coding : 5.0 jam/hari
## Tingkat stres: 87.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 5.5 jam
## → Developer BURNOUT
##
## Cluster 285 (1 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 8.3 jam
## → Developer BURNOUT
##
## Cluster 286 (1 developer):
## Jam coding : 2.0 jam/hari
## Tingkat stres: 91.0 / 100
## Sukses tugas : 30.0%
## Jam tidur : 7.1 jam
## → Developer BURNOUT
if (length(unique(ms_labels)) > 1) {
dist_ms <- dist(df_scaled_ms)
sil_ms <- silhouette(as.integer(as.factor(ms_labels)), dist_ms)
avg_sil_ms <- mean(sil_ms[,3])
cat(sprintf("Silhouette Score Mean Shift: %.4f\n", avg_sil_ms))
plot(sil_ms,
main=paste0("Silhouette Plot Mean Shift (avg=",round(avg_sil_ms,4),")"),
col=rainbow(n_cluster_ms))
} else {
avg_sil_ms <- NA
cat("Hanya 1 cluster terbentuk\n")
}
## Silhouette Score Mean Shift: -0.0084
Silhouette Score Mean Shift dihitung berdasarkan hasil clustering pada
subsample data. Nilai negatif pada Silhouette Score mengindikasikan
bahwa sebagian besar data lebih dekat ke cluster lain daripada ke
clusternya sendiri, yang merupakan tanda adanya overlap atau kesalahan
pengelompokan yang signifikan. Kondisi ini umum terjadi ketika jumlah
cluster yang terbentuk terlalu banyak.
Berdasarkan hasil clustering menggunakan metode Mean Shift, diperoleh jumlah cluster yang relatif banyak dengan ukuran cluster yang sangat kecil, bahkan sebagian besar cluster hanya berisi 1–2 data. Hal ini menunjukkan bahwa Mean Shift membentuk cluster berdasarkan kepadatan lokal secara sangat detail, sehingga menghasilkan banyak kelompok kecil. Dari visualisasi dan hasil ringkasan cluster, terlihat bahwa distribusi data tersebar ke berbagai cluster tanpa adanya pengelompokan besar yang dominan. Hal ini mengindikasikan bahwa struktur data tidak memiliki batas cluster yang kuat jika dilihat dari pendekatan berbasis kepadatan lokal.
Berdasarkan karakteristik beberapa cluster, terlihat adanya variasi kondisi developer:
Meskipun Mean Shift mampu mengidentifikasi variasi karakteristik individu secara detail, hasil clustering menjadi terlalu terfragmentasi sehingga sulit untuk menarik kesimpulan umum atau pola utama dari data.
set.seed(42)
k_fcm <- k_kmeans # gunakan k yang sama untuk perbandingan
# m = fuzziness parameter (biasanya 2)
# maxit = maksimum iterasi
fcm_result <- FKM(df_scaled, k=k_fcm, m=2, maxit=100, seed=42)
# Ambil label cluster (hard assignment = keanggotaan tertinggi)
fcm_labels <- fcm_result$clus[,1]
df$cluster_fcm <- fcm_labels
cat("HASIL FUZZY C-MEANS\n")
## HASIL FUZZY C-MEANS
cat("k (jumlah cluster) :", k_fcm, "\n")
## k (jumlah cluster) : 2
cat("Fuzziness parameter m : 2\n")
## Fuzziness parameter m : 2
cat("Iterasi :", fcm_result$iter, "\n\n")
## Iterasi : 100
cat("Distribusi Cluster (Hard Assignment):\n")
## Distribusi Cluster (Hard Assignment):
print(table(fcm_labels))
## fcm_labels
## 1 2
## 507 493
cat("\nContoh derajat keanggotaan (5 data pertama):\n")
##
## Contoh derajat keanggotaan (5 data pertama):
print(round(fcm_result$U[1:5,], 4))
## Clus 1 Clus 2
## Obj 1 0.5 0.5
## Obj 2 0.5 0.5
## Obj 3 0.5 0.5
## Obj 4 0.5 0.5
## Obj 5 0.5 0.5
cat("(Setiap baris = 1 developer, kolom = derajat keanggotaan ke tiap cluster)\n")
## (Setiap baris = 1 developer, kolom = derajat keanggotaan ke tiap cluster)
Fuzzy C-Means dijalankan dengan parameter fuzziness
m = 2 yang merupakan nilai standar yang paling umum
digunakan. Berbeda dengan metode clustering sebelumnya, FCM menghasilkan
derajat keanggotaan (membership degree) untuk setiap
data di setiap cluster, bukan pengelompokan yang kaku. Nilai derajat
keanggotaan berkisar 0 hingga 1, di mana nilai mendekati 1 berarti data
sangat kuat menjadi anggota cluster tersebut. Data yang memiliki nilai
keanggotaan hampir sama di dua cluster (misalnya 0.5 : 0.5) berada di
perbatasan antar cluster.
sil_scores_fcm <- sapply(2:10, function(k) {
fcm <- cmeans(df_scaled, centers = k, m = 2)
# ubah soft → hard cluster
fcm_labels <- apply(fcm$membership, 1, which.max)
sil <- silhouette(fcm_labels, dist(df_scaled))
mean(sil[,3])
})
plot(2:10, sil_scores_fcm, type="b", pch=19,
main="Silhouette Score per k (FCM)",
xlab="k", ylab="Avg Silhouette Score",
col="#8E44AD", lwd=2)
for (i in seq_along(sil_scores_fcm)) {
cat(sprintf("k=%d → Silhouette=%.4f\n", i+1, sil_scores_fcm[i]))
}
## k=2 → Silhouette=0.1547
## k=3 → Silhouette=0.0573
## k=4 → Silhouette=-0.0585
## k=5 → Silhouette=-0.0334
## k=6 → Silhouette=-0.0964
## k=7 → Silhouette=-0.0721
## k=8 → Silhouette=-0.0412
## k=9 → Silhouette=-0.0419
## k=10 → Silhouette=-0.0573
k_terbaik_fcm <- which.max(sil_scores_fcm) + 1
cat(sprintf("\nk terbaik FCM: %d (score=%.4f)\n",
k_terbaik_fcm, max(sil_scores_fcm)))
##
## k terbaik FCM: 2 (score=0.1547)
fcm_final <- cmeans(df_scaled, centers = k_terbaik_fcm, m = 2)
fcm_labels <- apply(fcm_final$membership, 1, which.max)
sil_fcm <- silhouette(fcm_labels, dist(df_scaled))
avg_sil_fcm <- mean(sil_fcm[,3])
cat(sprintf("Silhouette Score FCM (final): %.4f\n", avg_sil_fcm))
## Silhouette Score FCM (final): 0.1536
Grafik Silhouette Score per k untuk FCM menampilkan performa
clustering pada berbagai jumlah cluster. Pencarian k optimal dilakukan
secara terpisah untuk FCM menggunakan fungsi cmeans() dari
package e1071. K terbaik yang menghasilkan Silhouette Score
tertinggi kemudian digunakan untuk menjalankan model FCM final.
df_pca$cluster_fcm <- as.factor(fcm_labels)
ggplot(df_pca, aes(x=PC1, y=PC2, color=cluster_fcm)) +
geom_point(size=1.8, alpha=0.7) +
scale_color_brewer(palette="Dark2") +
stat_ellipse(level=0.75, linetype=2) +
labs(title = "Hasil Clustering Fuzzy C-Means (PCA 2D)",
subtitle = sprintf("k=%d | m=2 (fuzziness) | iterasi=%d",
k_fcm, fcm_result$iter),
x=sprintf("PC1 (%.1f%%)", var_exp[1]),
y=sprintf("PC2 (%.1f%%)", var_exp[2]),
color="Cluster") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"))
Visualisasi FCM dalam ruang PCA 2D menampilkan hard assignment dari
setiap data (keanggotaan ke cluster dengan nilai tertinggi). Meskipun
FCM pada dasarnya menghasilkan keanggotaan yang bersifat fuzzy (tidak
kaku), untuk keperluan visualisasi setiap data ditampilkan pada cluster
dengan nilai keanggotaan tertinggi. Elips putus-putus menggambarkan
perkiraan batas cluster berdasarkan distribusi titik data. ##
Karakteristik dan Interpretasi Cluster FCM
cat("KARAKTERISTIK CLUSTER FUZZY C-MEANS\n")
## KARAKTERISTIK CLUSTER FUZZY C-MEANS
fcm_profile <- df %>%
group_by(cluster_fcm) %>%
summarise(
n = n(),
Jam_Coding = round(mean(Hours_Coding), 2),
Baris_Kode = round(mean(Lines_of_Code), 2),
Bug_Ditemukan = round(mean(Bugs_Found), 2),
Bug_Diperbaiki = round(mean(Bugs_Fixed), 2),
Jam_AI = round(mean(AI_Usage_Hours), 2),
Jam_Tidur = round(mean(Sleep_Hours), 2),
Beban_Kognitif = round(mean(Cognitive_Load), 2),
Sukses_Tugas = round(mean(Task_Success_Rate), 2),
Level_Stres = round(mean(Stress_Level), 2),
Commits = round(mean(Commits), 2),
Error = round(mean(Errors), 2),
.groups="drop"
)
print(as.data.frame(fcm_profile))
## cluster_fcm n Jam_Coding Baris_Kode Bug_Ditemukan Bug_Diperbaiki Jam_AI
## 1 1 507 6.00 362.72 9.79 7.12 3.01
## 2 2 493 5.68 349.57 9.96 7.19 2.91
## Jam_Tidur Beban_Kognitif Sukses_Tugas Level_Stres Commits Error
## 1 6.43 56.62 57.11 66.31 18.07 4.55
## 2 6.50 57.26 56.03 66.52 16.41 4.54
df$cluster_fcm_f <- as.factor(df$cluster_fcm)
par(mfrow=c(2,2), mar=c(4,4,3,1))
for (v in vars_plot) {
boxplot(df[[v]] ~ df$cluster_fcm_f,
main=paste("FCM:", v),
xlab="Cluster", ylab=v,
col=rainbow(k_fcm), border="gray30")
}
par(mfrow=c(1,1))
cat("\nINTERPRETASI CLUSTER FUZZY C-MEANS\n")
##
## INTERPRETASI CLUSTER FUZZY C-MEANS
for (i in 1:k_fcm) {
row <- fcm_profile[fcm_profile$cluster_fcm == i, ]
cat(sprintf("\nCluster %d (%d developer):\n", i, row$n))
cat(sprintf(" Jam coding : %.1f jam/hari\n", row$Jam_Coding))
cat(sprintf(" Tingkat stres: %.1f / 100\n", row$Level_Stres))
cat(sprintf(" Sukses tugas : %.1f%%\n", row$Sukses_Tugas))
cat(sprintf(" Jam tidur : %.1f jam\n", row$Jam_Tidur))
label <- ifelse(row$Sukses_Tugas > 65 & row$Level_Stres < 60,
"→ Developer PRODUKTIF (performa tinggi, stres rendah)",
ifelse(row$Level_Stres > 75,
"→ Developer BURNOUT (stres tinggi, performa rendah)",
"→ Developer SEDANG (performa & stres moderat)"))
cat(label, "\n")
}
##
## Cluster 1 (507 developer):
## Jam coding : 6.0 jam/hari
## Tingkat stres: 66.3 / 100
## Sukses tugas : 57.1%
## Jam tidur : 6.4 jam
## → Developer SEDANG (performa & stres moderat)
##
## Cluster 2 (493 developer):
## Jam coding : 5.7 jam/hari
## Tingkat stres: 66.5 / 100
## Sukses tugas : 56.0%
## Jam tidur : 6.5 jam
## → Developer SEDANG (performa & stres moderat)
Tabel karakteristik cluster FCM menampilkan nilai rata-rata setiap
variabel per cluster berdasarkan hard assignment. Perhatikan bahwa pada
FCM, batas antar cluster bersifat lebih “lunak” dibandingkan K-Means,
sehingga perbedaan karakteristik antar cluster mungkin tidak setajam
metode partisi lainnya. Variabel Stress_Level dan
Task_Success_Rate tetap menjadi indikator utama untuk
mengidentifikasi tipe developer di setiap cluster.
Berdasarkan metode Fuzzy C-Means (FCM) dengan parameter m = 2, diperoleh jumlah cluster optimal sebanyak k = 2 dengan nilai Silhouette Score sebesar 0.1536. Nilai ini menunjukkan bahwa struktur cluster sudah terbentuk, namun pemisahannya masih tergolong lemah hingga sedang. Hasil pembagian cluster menunjukkan distribusi yang relatif seimbang, yaitu 507 data pada cluster 1 dan 493 data pada cluster 2. Namun, berbeda dengan metode clustering lainnya, FCM menghasilkan derajat keanggotaan pada setiap data. Terlihat bahwa beberapa data memiliki nilai keanggotaan yang sama (misalnya 0.5 : 0.5), yang menunjukkan bahwa data tersebut berada di antara dua cluster dan tidak memiliki kecenderungan yang kuat terhadap salah satu cluster.
Berdasarkan karakteristik cluster, kedua cluster memiliki nilai yang sangat mirip, baik dari segi:
Hal ini menunjukkan bahwa kedua cluster merepresentasikan kelompok developer dengan kondisi yang relatif sama, yaitu kategori sedang baik dari segi performa maupun tingkat stres. Dari visualisasi menunjukkan tidak adanya perbedaan yang signifikan antar cluster yang menunjukkan bahwa metode FCM tidak mampu memisahkan data secara jelas pada dataset ini.
cat("\n")
cat(paste0(rep("=",70), collapse=""), "\n")
## ======================================================================
cat(" PERBANDINGAN 5 METODE CLUSTERING\n")
## PERBANDINGAN 5 METODE CLUSTERING
cat(paste0(rep("=",70), collapse=""), "\n")
## ======================================================================
comparison_df <- data.frame(
Metode = c("K-Means","K-Medians","DBSCAN","Mean Shift","Fuzzy C-Means"),
Jumlah_Cluster = c(k_kmeans, k_optimal_kmed, n_cluster_db, n_cluster_ms, k_fcm),
Silhouette_Score = round(c(
avg_sil_km,
avg_sil_kmed,
ifelse(is.na(avg_sil_db), 0, avg_sil_db),
ifelse(is.na(avg_sil_ms), 0, avg_sil_ms),
avg_sil_fcm), 4),
Deteksi_Outlier = c("Tidak","Tidak","Ya","Tidak","Tidak"),
Perlu_Tentukan_k = c("Ya","Ya","Tidak","Tidak","Ya"),
Asumsi_Normal = c("Ya","Tidak","Tidak","Tidak","Sebagian"),
Data_Dipakai = c(nrow(df), nrow(df), nrow(df), nrow(df_scaled_ms), nrow(df))
)
knitr::kable(comparison_df) %>%
kableExtra::kable_styling(full_width = FALSE)
| Metode | Jumlah_Cluster | Silhouette_Score | Deteksi_Outlier | Perlu_Tentukan_k | Asumsi_Normal | Data_Dipakai |
|---|---|---|---|---|---|---|
| K-Means | 2 | 0.1616 | Tidak | Ya | Ya | 1000 |
| K-Medians | 2 | 0.1413 | Tidak | Ya | Tidak | 1000 |
| DBSCAN | 1 | 0.0000 | Ya | Tidak | Tidak | 1000 |
| Mean Shift | 286 | -0.0084 | Tidak | Tidak | Tidak | 300 |
| Fuzzy C-Means | 2 | 0.1536 | Tidak | Ya | Sebagian | 1000 |
best_method <- comparison_df$Metode[which.max(comparison_df$Silhouette_Score)]
best_score <- max(comparison_df$Silhouette_Score)
cat("\n")
cat(paste(rep("=",70), collapse=""), "\n")
## ======================================================================
cat(sprintf(" Metode TERBAIK (Silhouette tertinggi): %s (%.4f)\n",
best_method, best_score))
## Metode TERBAIK (Silhouette tertinggi): K-Means (0.1616)
cat(paste0(rep("=",70), collapse=""), "\n")
## ======================================================================
Gambar ketiga merangkum hasil analisis dari berbagai aspek, termasuk jumlah cluster, nilai silhouette, kebutuhan parameter, serta asumsi metode. Terlihat bahwa K-Means, K-Medians, dan Fuzzy C-Means menghasilkan jumlah cluster yang sama (2 cluster) dengan nilai silhouette yang relatif lebih baik dibanding metode lainnya.
Dari sisi parameter, metode berbasis centroid memerlukan penentuan jumlah cluster (k), sedangkan DBSCAN dan Mean Shift tidak memerlukan k, tetapi memiliki kelemahan dalam hasil clustering pada dataset ini. Selain itu, Mean Shift menghasilkan jumlah cluster yang sangat besar (286 cluster) dengan data yang lebih sedikit (subsample), yang menunjukkan ketidakstabilan metode pada data ini. Secara keseluruhan, K-Means menjadi metode paling optimal karena memiliki performa terbaik, struktur cluster yang jelas, serta hasil yang lebih konsisten dibanding metode lainnya. ## Visualisasi Perbandingan Shilouette Score
sil_values <- c(
avg_sil_km,
avg_sil_kmed,
ifelse(is.na(avg_sil_db), 0, avg_sil_db),
ifelse(is.na(avg_sil_ms), 0, avg_sil_ms),
avg_sil_fcm
)
methods <- c("K-Means","K-Medians","DBSCAN","Mean Shift","FCM")
best_method <- methods[which.max(sil_values)]
sil_df <- data.frame(Metode=methods, Silhouette=sil_values)
sil_df$Metode <- factor(sil_df$Metode, levels=methods)
sil_df$Terbaik <- sil_df$Silhouette == max(sil_df$Silhouette)
ggplot(sil_df, aes(x=Metode, y=Silhouette, fill=Terbaik)) +
geom_bar(stat="identity", width=0.6) +
geom_text(aes(label=round(Silhouette,4)), vjust=-0.5, fontface="bold") +
scale_fill_manual(values=c("FALSE"="#AED6F1","TRUE"="#2E86C1")) +
labs(title = "Perbandingan Silhouette Score — 5 Metode Clustering",
subtitle = paste("Metode terbaik:", best_method),
x="Metode", y="Avg Silhouette Score") +
theme_minimal() +
theme(plot.title=element_text(hjust=0.5, face="bold"),
plot.subtitle=element_text(hjust=0.5, color="gray50"),
legend.position="none")
### Interpretasi Grafik di atas memperlihatkan perbandingan nilai
rata-rata Silhouette Score dari kelima metode clustering. Berdasarkan
grafik, K-Means memiliki nilai tertinggi (0.1616), diikuti oleh Fuzzy
C-Means (0.1536) dan K-Medians (0.1413). Hal ini menunjukkan bahwa
K-Means memberikan kualitas cluster terbaik dalam hal pemisahan dan
kekompakan data.
Sementara itu, DBSCAN memiliki nilai 0, yang mengindikasikan bahwa metode ini tidak berhasil menemukan struktur cluster yang bermakna. Lebih lanjut, Mean Shift menghasilkan nilai negatif (-0.0084), yang menunjukkan bahwa banyak data kemungkinan salah dikelompokkan (overlapping tinggi). Secara keseluruhan, metode berbasis centroid menunjukkan performa yang lebih baik dibanding metode berbasis densitas pada dataset ini. ## Visualisasi Perbandingan Cluster
par(mfrow=c(2,3), mar=c(4,4,3,1))
plot(df_pca$PC1, df_pca$PC2,
col=rainbow(k_kmeans)[df_pca$cluster_kmeans],
pch=19, cex=0.5, main="K-Means", xlab="PC1", ylab="PC2")
plot(df_pca$PC1, df_pca$PC2,
col=rainbow(k_optimal_kmed)[df_pca$cluster_kmedians],
pch=19, cex=0.5, main="K-Medians", xlab="PC1", ylab="PC2")
db_color <- ifelse(df_pca$cluster_dbscan=="0", "gray80",
rainbow(n_cluster_db)[as.numeric(df_pca$cluster_dbscan)])
plot(df_pca$PC1, df_pca$PC2,
col=db_color, pch=19, cex=0.5,
main="DBSCAN", xlab="PC1", ylab="PC2")
plot(df_pca_ms$PC1, df_pca_ms$PC2,
col=rainbow(n_cluster_ms)[as.numeric(df_pca_ms$cluster_ms)],
pch=19, cex=0.6, main="Mean Shift (subsample)", xlab="PC1", ylab="PC2")
plot(df_pca$PC1, df_pca$PC2,
col=rainbow(k_fcm)[df_pca$cluster_fcm],
pch=19, cex=0.5, main="Fuzzy C-Means", xlab="PC1", ylab="PC2")
plot.new()
legend("center",
legend = paste(methods, ":", round(sil_values,4)),
title = "Silhouette Score",
col = c("#2E86C1","#27AE60","#E74C3C","#F39C12","#8E44AD"),
pch = 19, cex = 1, bty="n")
par(mfrow=c(1,1))
Hasil visualisasi di atas menunjukkan hasil clustering dari lima metode dalam bentuk proyeksi 2D (PCA). Terlihat bahwa metode K-Means, K-Medians, dan Fuzzy C-Means mampu membentuk dua cluster yang relatif jelas meskipun masih terdapat sedikit overlap antar titik. Hal ini menandakan bahwa ketiga metode tersebut cukup mampu menangkap pola dasar dalam data.
Sebaliknya, DBSCAN gagal membentuk cluster yang berarti karena seluruh data cenderung masuk ke satu kelompok saja, sehingga tidak ada pemisahan yang jelas. Sementara itu, Mean Shift menghasilkan jumlah cluster yang sangat banyak (terfragmentasi), sehingga pola menjadi sulit diinterpretasikan dan cenderung overclustering. Secara visual, metode berbasis partisi terlihat lebih stabil dibanding metode berbasis densitas pada dataset ini. # Kesimpulan dan Saran