1 Install Packages

#install.packages("meanShiftR")

2 Load library

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.

3 Karakteristik Data

3.1 Statistik Deskriptif

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.

3.2 Skewness & Kurtosis

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.

3.3 Distribusi variabel

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.

3.4 Deteksi Outlier

# 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.

3.5 Heatmap korelasi

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.

3.6 Scatter plot variabel kunci

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.

4 preprocessing

# 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.

5 Uji asumsi

5.1 Hopkins Statistic (Uji Kecenderungan Cluster)

# 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.

5.2 Uji Normalitas (Shapiro-Wilk)

# 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.

5.3 Uji Multikolinearitas

# 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

6 Clustering K-Means

6.1 Menentukan K optimal

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.

6.2 Jalankan K-Means

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.

6.3 Silhouette Score K-Means

# 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.

6.4 Visualisasi 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.

6.5 Karakteristik & Interpretasi Cluster K-Means

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)

6.6 Interpretasi

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.

7 Clustering K-Medians

7.1 Jalankan K-Medians

# 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.

7.2 Silhouette Score K-Medians

# 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.

7.3 Visualisasi K-Medians

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.

7.4 Karakteristik & Interpretasi Cluster K-Medians

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.

7.5 Interpretasi

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.

8 Clustering DBSCAN

8.1 Menentukan eps Optimal (KNN Plot)

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.

8.2 Jalankan DBSCAN

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.

8.3 Silhouette Score DBSCAN

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.

8.4 Visualisasi DBSCAN

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.

8.5 Karakteristik & Interpretasi Cluster DBSCAN

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

8.6 Interpretasi

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:

  • Kepadatan data cukup tinggi
  • Tidak terdapat pemisahan struktur cluster yang jelas
  • Semua data dianggap berada dalam satu kelompok yang homogen

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.

9 Clustering Mean Shift

9.1 Jalankan Mean Shift

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.

9.2 Visualisasi Mean Shift

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.

9.3 Karakteristik dan Interpretasi Mean Shift

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.

9.4 Interpretasi

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:

  • Cluster 1 menunjukkan developer dengan kondisi sedang, dengan jam coding 7 jam/hari, stres cukup tinggi (69), dan tingkat keberhasilan tugas 63%.
  • Cluster 2 merepresentasikan developer produktif, dengan jam coding tinggi (9 jam/hari), stres rendah (39), serta tingkat keberhasilan tugas tinggi (78%).
  • Cluster 3 dan 4 termasuk kategori sedang, dengan performa dan tingkat stres yang moderat.
  • Cluster 5 menunjukkan developer burnout, dengan tingkat stres sangat tinggi (91), jam tidur rendah (4 jam), dan keberhasilan tugas rendah (34%).

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.

10 Clustering Fuzzy C - Means

10.1 Jalankan Fuzzy C - Means

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.

10.2 Shilouette FCM

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.

10.3 Visualisasi Fuzzy C - Means

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.

10.4 Interpretasi

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:

  • Jam coding (sekitar 5.7–6.0 jam/hari)
  • Tingkat stres (sekitar 66)
  • Tingkat keberhasilan tugas (sekitar 56–57%)
  • Jam tidur (sekitar 6.4–6.5 jam)

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.

11 Perbandingan Semua Metode

11.1 Tabel Perbandingan

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")
## ======================================================================

11.1.1 Interpretasi

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))

11.1.2 Interpretasi

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