PENDAHULUAN

Analisis ini dilatarbelakangi oleh kebutuhan untuk memahami keberagaman pola belajar mahasiswa yang memengaruhi hasil akademik mereka di era pendidikan berbasis data. Menggunakan dataset perilaku mahasiswa yang mencakup delapan atribut kunci yaitu durasi belajar (StudyHours), kehadiran (Attendance), penyelesaian tugas (AssignmentCompletion), partisipasi kursus daring (OnlineCourses), keterlibatan diskusi (Discussions), tingkat motivasi (Motivation), tingkat stres (StressLevel), dan nilai ujian (ExamScore)—penelitian ini bertujuan untuk melakukan segmentasi mahasiswa melalui teknik clustering. Dengan membandingkan lima algoritma berbeda (K-Means, K-Median, DBSCAN, Mean Shift, dan Fuzzy C-Means), diharapkan dapat ditemukan model terbaik yang mampu mengidentifikasi kelompok mahasiswa secara akurat guna mendukung pengambilan keputusan pendidikan yang lebih personal dan tepat sasaran.

Load Library

library(dplyr)
library(ggplot2)
library(cluster)
library(factoextra)
library(readr)
library(tidyr)
library(kableExtra)
library(corrplot)
library(ggplot2)
library(flexclust)
library(dbscan)
library(reshape2)
library(LPCM)
library(e1071)
library(cluster)

Import Data

data <- read_csv("merged_dataset.csv",
                 show_col_types = FALSE)
str(data)
## spc_tbl_ [14,003 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ StudyHours          : num [1:14003] 19 19 19 19 19 19 19 19 19 19 ...
##  $ Attendance          : num [1:14003] 64 64 64 64 64 64 64 64 64 64 ...
##  $ Resources           : num [1:14003] 1 1 1 1 1 1 0 0 0 1 ...
##  $ Extracurricular     : num [1:14003] 0 0 0 1 1 1 1 1 1 1 ...
##  $ Motivation          : num [1:14003] 0 0 0 0 0 0 0 0 0 1 ...
##  $ Internet            : num [1:14003] 1 1 1 1 1 1 1 1 1 1 ...
##  $ Gender              : num [1:14003] 0 0 0 0 0 0 0 0 0 0 ...
##  $ Age                 : num [1:14003] 19 23 28 19 23 28 19 23 28 19 ...
##  $ LearningStyle       : num [1:14003] 2 3 1 2 3 1 2 3 1 2 ...
##  $ OnlineCourses       : num [1:14003] 8 16 19 8 16 19 8 16 19 8 ...
##  $ Discussions         : num [1:14003] 1 0 0 1 0 0 1 0 0 1 ...
##  $ AssignmentCompletion: num [1:14003] 59 90 67 59 90 67 59 90 67 59 ...
##  $ ExamScore           : num [1:14003] 40 66 99 40 66 99 40 66 99 40 ...
##  $ EduTech             : num [1:14003] 0 0 1 0 0 1 0 0 1 0 ...
##  $ StressLevel         : num [1:14003] 1 1 1 1 1 1 1 1 1 1 ...
##  $ FinalGrade          : num [1:14003] 3 2 0 3 2 0 3 2 0 3 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   StudyHours = col_double(),
##   ..   Attendance = col_double(),
##   ..   Resources = col_double(),
##   ..   Extracurricular = col_double(),
##   ..   Motivation = col_double(),
##   ..   Internet = col_double(),
##   ..   Gender = col_double(),
##   ..   Age = col_double(),
##   ..   LearningStyle = col_double(),
##   ..   OnlineCourses = col_double(),
##   ..   Discussions = col_double(),
##   ..   AssignmentCompletion = col_double(),
##   ..   ExamScore = col_double(),
##   ..   EduTech = col_double(),
##   ..   StressLevel = col_double(),
##   ..   FinalGrade = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
head(data)
## # A tibble: 6 × 16
##   StudyHours Attendance Resources Extracurricular Motivation Internet Gender
##        <dbl>      <dbl>     <dbl>           <dbl>      <dbl>    <dbl>  <dbl>
## 1         19         64         1               0          0        1      0
## 2         19         64         1               0          0        1      0
## 3         19         64         1               0          0        1      0
## 4         19         64         1               1          0        1      0
## 5         19         64         1               1          0        1      0
## 6         19         64         1               1          0        1      0
## # ℹ 9 more variables: Age <dbl>, LearningStyle <dbl>, OnlineCourses <dbl>,
## #   Discussions <dbl>, AssignmentCompletion <dbl>, ExamScore <dbl>,
## #   EduTech <dbl>, StressLevel <dbl>, FinalGrade <dbl>

Data Cleaning

colSums(is.na(data))
##           StudyHours           Attendance            Resources 
##                    0                    0                    0 
##      Extracurricular           Motivation             Internet 
##                    0                    0                    0 
##               Gender                  Age        LearningStyle 
##                    0                    0                    0 
##        OnlineCourses          Discussions AssignmentCompletion 
##                    0                    0                    0 
##            ExamScore              EduTech          StressLevel 
##                    0                    0                    0 
##           FinalGrade 
##                    0
sum(duplicated(data))
## [1] 1534
cat("Jumlah data sebelum dihapus duplikasi:", nrow(data), "\n")
## Jumlah data sebelum dihapus duplikasi: 14003
data <- distinct(data)
sum(duplicated(data))
## [1] 0
cat("Jumlah data setelah dihapus duplikasi:", nrow(data), "\n")
## Jumlah data setelah dihapus duplikasi: 12469
kable(head(data), caption = "Data setelah penghapusan duplikasi") %>%
  kable_styling(full_width = FALSE, position = "center")
Data setelah penghapusan duplikasi
StudyHours Attendance Resources Extracurricular Motivation Internet Gender Age LearningStyle OnlineCourses Discussions AssignmentCompletion ExamScore EduTech StressLevel FinalGrade
19 64 1 0 0 1 0 19 2 8 1 59 40 0 1 3
19 64 1 0 0 1 0 23 3 16 0 90 66 0 1 2
19 64 1 0 0 1 0 28 1 19 0 67 99 1 1 0
19 64 1 1 0 1 0 19 2 8 1 59 40 0 1 3
19 64 1 1 0 1 0 23 3 16 0 90 66 0 1 2
19 64 1 1 0 1 0 28 1 19 0 67 99 1 1 0

Berdasarkan hasil eksplorasi data, tidak ditemukan missing value pada seluruh variabel. Namun, terdapat 1534 data duplikat yang kemudian dihapus untuk menjaga kualitas dan keakuratan analisis clustering. Setelah dilakukan penghapusan data duplikat, jumlah data menjadi sebanya 12.469 observasi. Tabel berikut menunjukkan sebagian data hasil pembersihan yang akan digunakan dalam analisis selanjutnya.

Preprocessing

Feature Selection

data_selected <- data %>%
  select(
    StudyHours,
    Attendance,
    AssignmentCompletion,
    OnlineCourses,
    Discussions,
    Motivation,
    StressLevel,
    ExamScore
  )

set.seed(123)
data_sample <- data_selected[sample(1:nrow(data_selected), 2500), ]

str(data_selected)
## tibble [12,469 × 8] (S3: tbl_df/tbl/data.frame)
##  $ StudyHours          : num [1:12469] 19 19 19 19 19 19 19 19 19 19 ...
##  $ Attendance          : num [1:12469] 64 64 64 64 64 64 64 64 64 64 ...
##  $ AssignmentCompletion: num [1:12469] 59 90 67 59 90 67 59 90 67 59 ...
##  $ OnlineCourses       : num [1:12469] 8 16 19 8 16 19 8 16 19 8 ...
##  $ Discussions         : num [1:12469] 1 0 0 1 0 0 1 0 0 1 ...
##  $ Motivation          : num [1:12469] 0 0 0 0 0 0 0 0 0 1 ...
##  $ StressLevel         : num [1:12469] 1 1 1 1 1 1 1 1 1 1 ...
##  $ ExamScore           : num [1:12469] 40 66 99 40 66 99 40 66 99 40 ...
cat("Jumlah data setelah sampling:", nrow(data_sample), "\n")
## Jumlah data setelah sampling: 2500

Untuk meningkatkan efisiensi komputasi serta menghindari kendala konvergensi pada algoritma K-Means, dilakukan teknik random sampling sebanyak 2500 observasi dari total data. Jumlah ini dianggap cukup representatif untuk menggambarkan pola umum dalam data.

Scaling

data_scaled <- scale(data_sample)
summary(data_scaled)
##    StudyHours         Attendance        AssignmentCompletion
##  Min.   :-2.51703   Min.   :-1.760694   Min.   :-1.700437   
##  1st Qu.:-0.68002   1st Qu.:-0.884448   1st Qu.:-0.880304   
##  Median :-0.01202   Median :-0.008202   Median : 0.008174   
##  Mean   : 0.00000   Mean   : 0.000000   Mean   : 0.000000   
##  3rd Qu.: 0.65598   3rd Qu.: 0.868045   3rd Qu.: 0.896652   
##  Max.   : 3.16098   Max.   : 1.744291   Max.   : 1.716785   
##  OnlineCourses        Discussions        Motivation       StressLevel     
##  Min.   :-1.638612   Min.   :-1.2389   Min.   :-1.2706   Min.   :-1.6919  
##  1st Qu.:-0.817664   1st Qu.:-1.2389   1st Qu.:-1.2706   1st Qu.:-0.4051  
##  Median : 0.003284   Median : 0.8068   Median : 0.1609   Median : 0.8817  
##  Mean   : 0.000000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.824232   3rd Qu.: 0.8068   3rd Qu.: 0.1609   3rd Qu.: 0.8817  
##  Max.   : 1.645180   Max.   : 0.8068   Max.   : 1.5925   Max.   : 0.8817  
##    ExamScore         
##  Min.   :-1.6964008  
##  1st Qu.:-0.8480081  
##  Median : 0.0003846  
##  Mean   : 0.0000000  
##  3rd Qu.: 0.8487773  
##  Max.   : 1.6971700

Tahap preprocessing dilakukan dengan memilih variabel numerik yang relevan terhadap perilaku belajar dan performa akademik, yaitu StudyHours, Attendance, AssignmentCompletion, OnlineCourses, Discussions, Motivation, StressLevel, dan ExamScore. Selanjutnya dilakukan standarisasi data menggunakan metode z-score untuk menghindari bias akibat perbedaan skala antar variabel.

Cek Korelasi

cor(data_selected)
##                        StudyHours   Attendance AssignmentCompletion
## StudyHours            1.000000000  0.028129398          0.008899517
## Attendance            0.028129398  1.000000000         -0.001891858
## AssignmentCompletion  0.008899517 -0.001891858          1.000000000
## OnlineCourses        -0.002186405  0.006514640          0.011071669
## Discussions           0.027621298 -0.006918192          0.001359650
## Motivation           -0.004675917 -0.004007953          0.007905876
## StressLevel           0.005621005 -0.017937436          0.016280306
## ExamScore             0.004201263 -0.014156151          0.027402241
##                      OnlineCourses  Discussions   Motivation  StressLevel
## StudyHours            -0.002186405  0.027621298 -0.004675917  0.005621005
## Attendance             0.006514640 -0.006918192 -0.004007953 -0.017937436
## AssignmentCompletion   0.011071669  0.001359650  0.007905876  0.016280306
## OnlineCourses          1.000000000  0.002027089  0.002470328  0.003102327
## Discussions            0.002027089  1.000000000 -0.020313527 -0.013770237
## Motivation             0.002470328 -0.020313527  1.000000000 -0.001778368
## StressLevel            0.003102327 -0.013770237 -0.001778368  1.000000000
## ExamScore              0.020684306 -0.031208686 -0.003539395 -0.034324316
##                         ExamScore
## StudyHours            0.004201263
## Attendance           -0.014156151
## AssignmentCompletion  0.027402241
## OnlineCourses         0.020684306
## Discussions          -0.031208686
## Motivation           -0.003539395
## StressLevel          -0.034324316
## ExamScore             1.000000000
cor_matrix <- cor(data_selected)
corrplot(cor_matrix, 
         method = "color", 
         type = "upper", 
         tl.col = "black", 
         tl.srt = 45,
         addCoef.col = "black",
         number.cex = 0.7)

Elbow Method

set.seed(123)
factoextra::fviz_nbclust(
  data_scaled,
  FUNcluster = function(x, k){
    kmeans(x, centers = k, nstart = 25, iter.max = 100)
  },
  method = "wss",
  k.max = 6
) +
  labs(title = "Elbow Method")

Silhouette Method

set.seed(123)
factoextra::fviz_nbclust(
  data_scaled,
  FUNcluster = function(x, k){
    kmeans(x, centers = k, nstart = 25, iter.max = 100)
  },
  method = "silhouette",
  k.max = 6
) +
  labs(title = "Silhouette Method")

Penentuan jumlah cluster optimal dilakukan menggunakan metode Elbow dan Silhouette. Berdasarkan grafik Elbow, terlihat bahwa penurunan nilai Within Sum of Squares mulai melandai setelah k = 2, yang menunjukkan titik siku pada k = 2. Hal ini diperkuat oleh metode Silhouette yang menunjukkan nilai rata-rata silhouette tertinggi pada k = 2. Oleh karena itu, jumlah cluster optimal yang digunakan dalam analisis ini adalah 2 cluster. Nilai silhouette yang relatif rendah menunjukkan bahwa pemisahan antar cluster tidak terlalu kuat, yang mengindikasikan bahwa data memiliki pola yang tidak terlalu terpisah secara jelas.

K-Means Clustering

set.seed(123)

kmeans_result <- kmeans(data_scaled,
                        centers = 2,
                        nstart = 25,
                        iter.max = 100)

kmeans_result
## K-means clustering with 2 clusters of sizes 986, 1514
## 
## Cluster means:
##    StudyHours    Attendance AssignmentCompletion OnlineCourses Discussions
## 1 -0.05199565 -0.0004700804           0.02966161  0.0004529368  -1.2389039
## 2  0.03386243  0.0003061422          -0.01931727 -0.0002949773   0.8068423
##     Motivation StressLevel   ExamScore
## 1  0.011362984  0.03472358  0.04185776
## 2 -0.007400199 -0.02261390 -0.02726007
## 
## Clustering vector:
##    [1] 1 2 2 1 2 2 2 1 1 2 1 1 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 1 1 2 2 1 1 2 1 2 1
##   [38] 2 1 1 2 2 2 2 2 2 2 1 1 2 1 2 2 2 2 1 1 1 2 1 1 1 2 2 2 1 2 1 2 1 2 2 1 2
##   [75] 2 1 2 2 2 1 2 2 2 1 1 1 1 2 2 2 2 1 1 1 1 1 1 1 2 1 2 1 2 2 1 1 2 2 1 2 2
##  [112] 2 1 2 1 1 2 1 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 1 1 2 2 1 2 1 2 1 2 1 2
##  [149] 2 2 2 1 1 1 2 2 1 2 2 1 2 2 2 1 1 1 1 1 2 1 1 2 2 1 1 2 2 1 1 2 2 2 2 1 2
##  [186] 2 2 1 2 2 2 2 2 1 1 1 1 2 1 2 2 1 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 2 1 2 1
##  [223] 1 2 2 2 1 2 2 2 2 1 1 2 2 2 2 2 1 2 1 1 2 1 1 1 2 2 1 2 2 1 2 1 2 2 2 1 2
##  [260] 2 2 2 1 2 1 2 1 1 1 1 1 1 2 2 1 1 2 2 1 1 2 2 2 2 2 2 2 1 1 2 2 1 1 2 2 2
##  [297] 2 1 2 1 2 2 2 2 1 2 1 2 2 2 1 1 2 2 2 2 2 2 1 1 1 2 2 1 2 1 2 1 2 1 2 2 2
##  [334] 2 2 2 2 2 1 2 2 1 1 1 2 2 2 2 1 2 1 2 2 1 1 1 2 1 2 1 2 2 1 2 1 1 1 2 2 2
##  [371] 1 2 1 2 1 1 1 1 1 1 2 1 2 1 1 2 2 2 1 2 2 1 2 1 2 1 2 2 2 2 2 2 1 1 2 1 1
##  [408] 1 1 1 2 2 1 2 2 2 2 1 2 1 2 1 2 1 1 2 1 1 1 2 2 2 2 1 1 1 2 1 1 2 2 2 1 2
##  [445] 1 1 2 2 2 2 1 2 1 1 2 2 2 2 1 1 2 2 2 2 2 2 1 1 2 1 2 2 1 2 2 1 2 1 2 1 1
##  [482] 1 2 1 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 1 1 2 1 2 2 1 2 1 2 2 1 2 1 1 1 2 2 1
##  [519] 1 2 2 2 1 2 1 2 2 1 1 2 2 2 1 1 2 1 2 2 2 1 2 1 2 1 2 2 2 1 1 2 2 1 1 1 2
##  [556] 2 1 1 1 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1
##  [593] 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 2 1 1 2 2 1 1 2 2
##  [630] 1 2 1 2 1 1 1 2 2 2 1 2 1 1 2 2 1 2 2 2 1 2 2 1 1 1 1 2 2 1 2 1 2 2 2 2 2
##  [667] 2 2 1 1 1 2 2 1 2 2 2 2 1 1 1 2 2 1 1 1 1 2 1 2 2 1 1 1 1 1 1 1 2 2 1 2 2
##  [704] 2 1 2 2 2 1 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 1 2
##  [741] 2 2 2 2 2 2 1 2 2 1 2 1 1 1 2 2 1 2 2 2 2 1 2 2 2 1 1 2 2 2 2 1 1 1 2 2 1
##  [778] 2 1 2 1 1 1 1 1 1 2 1 2 2 2 1 2 1 2 2 1 1 2 1 2 1 2 1 1 2 2 1 2 2 1 2 2 2
##  [815] 2 1 1 2 2 2 1 2 2 2 2 1 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 1 2 2 1 2 2 2 2 1 2
##  [852] 2 2 1 2 1 2 2 1 2 1 1 2 2 2 2 2 1 2 2 1 1 2 2 2 1 2 1 2 2 2 2 2 2 1 2 2 2
##  [889] 1 2 1 2 1 2 1 2 2 1 1 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 1 2 2
##  [926] 1 2 2 2 2 2 2 1 2 2 2 2 1 1 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 1 1 2 1 2 1 2
##  [963] 2 2 1 2 1 1 1 2 2 2 1 2 2 2 2 1 1 2 1 2 1 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 1
## [1000] 1 2 2 1 1 1 2 2 2 2 1 2 2 2 2 2 2 1 2 1 2 2 1 2 2 2 2 1 2 1 2 1 2 1 2 2 2
## [1037] 2 2 1 2 1 1 2 1 2 2 1 1 1 2 2 2 1 2 2 2 2 1 2 2 2 2 1 1 2 2 2 2 1 1 2 1 1
## [1074] 1 2 1 2 1 2 2 1 1 1 1 2 1 1 1 2 2 2 1 1 2 2 2 2 2 1 2 2 2 1 1 2 1 1 1 1 2
## [1111] 2 2 1 2 2 1 1 1 2 1 1 2 2 1 2 2 2 1 2 2 1 2 2 2 2 2 2 1 2 1 2 2 1 1 1 1 1
## [1148] 2 2 2 1 2 1 2 1 2 1 1 1 1 2 1 2 1 1 1 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 2 2 2
## [1185] 1 2 1 1 1 2 1 2 1 1 1 2 2 2 1 2 2 1 2 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 2 2 2
## [1222] 2 1 2 1 1 1 2 2 2 2 1 1 2 2 1 1 2 2 1 2 2 1 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1
## [1259] 2 2 2 2 1 1 1 2 1 2 2 2 1 2 2 1 1 2 2 2 1 2 2 2 1 2 1 2 1 2 1 2 2 1 2 2 2
## [1296] 2 2 1 2 1 2 2 2 1 2 2 2 1 1 2 1 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 1 1 2 2 2 1
## [1333] 2 2 1 2 2 1 2 2 1 2 1 1 2 2 2 2 1 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 1 2 2
## [1370] 2 1 1 1 1 2 2 2 2 1 1 1 2 1 1 2 2 1 2 2 1 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2
## [1407] 1 1 1 2 1 1 2 2 2 1 1 2 1 1 1 2 1 1 2 2 1 1 1 2 2 1 1 2 1 2 2 1 2 2 1 2 2
## [1444] 1 2 2 1 1 1 1 1 2 2 1 2 1 2 1 2 1 2 2 2 2 1 2 2 1 2 1 1 2 1 2 2 1 2 2 1 1
## [1481] 2 1 2 1 2 1 2 1 1 2 2 1 1 2 1 1 2 2 2 2 2 1 1 2 2 1 1 2 2 2 1 1 2 2 1 2 2
## [1518] 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 2 1 1 2 2 2 2 1 1 2 1 2 2 2 1 2 1 1 2 1 2
## [1555] 1 2 1 2 1 2 2 2 1 1 1 1 1 2 2 1 2 1 2 1 2 2 1 2 2 2 2 1 2 2 1 2 1 1 1 2 1
## [1592] 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 1 2 1 1 2 2 2 2 2 1 1 1 2 2 1 2 2
## [1629] 1 1 2 2 2 1 1 1 1 1 1 2 2 1 1 2 2 2 1 2 1 2 1 2 2 2 2 1 2 2 1 1 2 2 2 2 2
## [1666] 2 1 2 1 1 2 1 2 2 1 1 2 2 2 1 2 2 1 1 1 2 1 1 2 1 2 2 2 2 1 1 2 1 2 2 1 1
## [1703] 1 2 2 1 1 2 1 2 1 2 1 2 1 2 1 2 2 2 1 2 1 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2
## [1740] 2 2 2 1 2 2 2 1 2 2 2 1 1 2 2 1 1 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 2 2 2
## [1777] 2 2 1 1 2 2 2 1 1 2 2 2 1 2 2 1 1 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 1
## [1814] 2 2 2 2 1 2 2 1 2 2 1 1 1 2 2 1 1 1 1 1 1 2 2 1 2 2 2 1 2 2 2 2 1 1 1 1 2
## [1851] 1 1 1 1 1 2 2 1 2 2 2 2 2 2 2 2 1 1 1 2 2 2 1 1 2 2 1 2 2 1 2 2 1 2 2 2 1
## [1888] 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 2 1 2 2 2 1 1 2 2 2 2 2
## [1925] 2 2 2 1 2 2 2 1 1 2 1 1 2 2 2 2 2 2 1 1 2 1 2 1 2 2 2 2 2 2 1 1 2 2 1 2 1
## [1962] 2 2 1 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 1 1 2 2 2 2 2 2
## [1999] 1 2 2 2 2 1 1 2 1 2 2 2 2 1 1 2 1 2 2 2 2 1 2 2 2 2 1 1 2 2 1 2 2 2 1 1 2
## [2036] 1 1 1 2 1 2 1 2 2 2 1 1 2 2 1 2 2 2 2 1 1 1 1 1 2 2 1 2 2 2 2 2 2 2 1 2 1
## [2073] 2 1 1 1 2 1 2 2 2 2 1 1 2 2 2 1 2 2 1 2 2 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 1
## [2110] 1 2 2 1 2 1 2 1 2 1 2 2 2 2 1 1 2 2 2 1 2 2 1 2 2 1 1 1 1 2 2 1 2 1 1 1 1
## [2147] 1 1 2 2 2 2 1 2 2 2 1 2 1 1 2 2 1 2 2 1 2 2 2 1 1 2 2 2 2 1 2 2 2 1 1 1 2
## [2184] 2 1 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 2 1 2 1 2 2 2 2 1 2 2 2 2 2 2 1 1
## [2221] 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 2 1 2 2 2
## [2258] 2 2 2 2 2 1 2 2 1 1 1 1 2 1 2 1 1 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2
## [2295] 2 1 1 1 2 2 2 1 1 2 1 1 1 1 1 2 2 1 2 1 2 2 1 1 1 2 1 1 1 1 2 2 1 1 1 2 1
## [2332] 1 2 2 2 2 2 1 2 2 1 1 2 2 1 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 1 2 2 2 2 2 2 2
## [2369] 2 2 1 2 1 1 1 2 2 2 1 2 2 2 1 2 2 2 2 1 2 2 1 1 2 1 1 1 1 1 1 2 1 2 1 1 1
## [2406] 2 1 2 2 1 2 2 2 2 1 1 1 2 2 2 2 2 1 1 2 2 2 2 1 2 1 2 1 2 2 2 1 1 2 2 1 1
## [2443] 1 1 2 1 1 1 2 2 1 2 2 1 2 2 1 2 1 2 2 1 1 2 1 1 2 2 2 2 2 2 1 2 1 1 1 1 2
## [2480] 1 1 2 1 1 2 2 2 2 1 1 1 1 2 1 1 1 2 1 1 1
## 
## Within cluster sum of squares by cluster:
## [1]  6890.786 10591.354
##  (between_SS / total_SS =  12.6 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
data_clustered <- as.data.frame(data_sample)
data_clustered$Cluster <- kmeans_result$cluster

head(data_clustered)
##   StudyHours Attendance AssignmentCompletion OnlineCourses Discussions
## 1         24         80                   52             9           0
## 2         18         69                   80             5           1
## 3         16         90                   57             2           1
## 4         31         85                   90             6           0
## 5          8        100                   93             3           1
## 6         16         61                   77             7           1
##   Motivation StressLevel ExamScore Cluster
## 1          1           2        42       1
## 2          1           0        94       2
## 3          1           2        52       2
## 4          1           2        70       1
## 5          1           0        51       2
## 6          0           1        68       2

Setelah jumlah cluster optimal ditentukan sebanyak 2 cluster, dilakukan proses clustering menggunakan algoritma K-Means dengan parameter centers = 2, nstart = 25, dan iter.max = 100 untuk memastikan hasil yang stabil. Hasil clustering kemudian digunakan untuk mengelompokkan data ke dalam dua kelompok utama.

INTERPRETASI

Hasil clustering menunjukkan bahwa data terbagi menjadi dua kelompok utama dengan jumlah anggota masing-masing 986 dan 1514. Berdasarkan nilai centroid, terdapat perbedaan karakteristik yang cukup jelas antara kedua cluster.

Cluster 1 cenderung memiliki nilai Discussions yang sangat rendah, namun memiliki AssignmentCompletion, Motivation, StressLevel, dan ExamScore yang relatif lebih tinggi. Hal ini menunjukkan bahwa kelompok ini merupakan mahasiswa yang lebih fokus secara individu, kurang aktif dalam diskusi, namun tetap mampu mencapai performa akademik yang baik, meskipun dengan tingkat stres yang lebih tinggi.

Sebaliknya, Cluster 2 menunjukkan karakteristik dengan tingkat Discussions yang tinggi dan StudyHours yang lebih besar, namun memiliki nilai AssignmentCompletion, Motivation, dan ExamScore yang lebih rendah. Kelompok ini dapat diinterpretasikan sebagai mahasiswa yang lebih aktif secara sosial dan kolaboratif, namun memiliki performa akademik yang relatif lebih rendah dibandingkan Cluster 1.

Variabel yang paling membedakan kedua cluster adalah Discussions, yang menunjukkan perbedaan signifikan dalam pola interaksi belajar mahasiswa. Namun, nilai between cluster sum of squares yang relatif kecil (sekitar 12.6%) menunjukkan bahwa pemisahan antar cluster tidak terlalu kuat, sehingga struktur cluster dalam data ini masih tergolong lemah.

Hasil ini mengindikasikan bahwa aktivitas diskusi tidak selalu berbanding lurus dengan performa akademik, sehingga diperlukan pendekatan pembelajaran yang lebih seimbang antara kolaborasi dan penyelesaian tugas individu.

Visualisasi Cluster (PCA)

fviz_cluster(kmeans_result, 
             data = data_scaled,
             geom = "point",
             ellipse.type = "norm",
             palette = c("#2E86C1", "#E74C3C"),
             ggtheme = theme_minimal())

Visualisasi cluster menggunakan metode PCA menunjukkan pemisahan antara dua cluster yang terbentuk. Meskipun terdapat pemisahan, masih terlihat adanya overlap antar cluster, yang mengindikasikan bahwa struktur cluster dalam data tidak sepenuhnya terpisah dengan jelas. Hal ini sejalan dengan nilai silhouette yang relatif rendah.

BOX PLOT

data_long <- data_clustered %>%
  pivot_longer(-Cluster, names_to = "Variable", values_to = "Value")

ggplot(data_long, aes(x = factor(Cluster), y = Value, fill = factor(Cluster))) +
  geom_boxplot(alpha = 0.7) +
  facet_wrap(~Variable, scales = "free") +
  theme_minimal() +
  labs(title = "Perbandingan Variabel pada Setiap Cluster",
       x = "Cluster",
       y = "Nilai") +
  scale_fill_manual(values = c("#2E86C1", "#E74C3C"))

Boxplot menunjukkan perbedaan distribusi antar variabel pada masing-masing cluster, terutama pada variabel Discussions yang memiliki perbedaan paling signifikan antara kedua kelompok.

K-MEDIAN CLUSTERING

set.seed(123)

kmedian_result <- kcca(
  data_scaled,
  k = 2,
  family = kccaFamily("kmedians")
)

kmedian_result
## kcca object of family 'kmedians' 
## 
## call:
## kcca(x = data_scaled, k = 2, family = kccaFamily("kmedians"))
## 
## cluster sizes:
## 
##    1    2 
## 1051 1449
centers_kmedian <- kmedian_result@centers
centers_kmedian
##       StudyHours   Attendance AssignmentCompletion OnlineCourses Discussions
## [1,] -0.01202401 -0.008201666           0.07651845     0.3316630  -1.2389039
## [2,] -0.01202401 -0.008201666          -0.06017046    -0.3250954   0.8068423
##      Motivation StressLevel  ExamScore
## [1,]  0.1609065   0.8816974  0.3963012
## [2,]  0.1609065  -0.4050764 -0.2824130

Label Cluster

data_kmedian <- data_sample
data_kmedian$Cluster <- clusters(kmedian_result)
head(data_kmedian)
## # A tibble: 6 × 9
##   StudyHours Attendance AssignmentCompletion OnlineCourses Discussions
##        <dbl>      <dbl>                <dbl>         <dbl>       <dbl>
## 1         24         80                   52             9           0
## 2         18         69                   80             5           1
## 3         16         90                   57             2           1
## 4         31         85                   90             6           0
## 5          8        100                   93             3           1
## 6         16         61                   77             7           1
## # ℹ 4 more variables: Motivation <dbl>, StressLevel <dbl>, ExamScore <dbl>,
## #   Cluster <int>

Visualisasi

centers_df <- as.data.frame(centers_kmedian)
centers_df$Cluster <- factor(1:2)

centers_long <- centers_df %>%
  pivot_longer(-Cluster, names_to="Variable", values_to="Value")

ggplot(centers_long, aes(Variable, Value, group=Cluster, color=Cluster))+
  geom_line(size=1.2)+
  geom_point(size=3)+
  theme_minimal()+
  labs(title="Profil Median Tiap Cluster (K-Median)")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

K-Median digunakan sebagai alternatif K-Means karena menggunakan median sebagai pusat cluster sehingga lebih robust terhadap outlier. Hasil visualisasi menunjukkan pola pemisahan cluster yang relatif mirip dengan K-Means, namun dengan distribusi anggota cluster yang sedikit lebih stabil terhadap nilai ekstrem.

DBSCAN CLUSTERING

kNNdistplot(data_scaled, k = 4)
abline(h = 2, col = "red", lty = 2)

dbscan_result <- dbscan(data_scaled, eps = 2, minPts = 4)

table(dbscan_result$cluster)
## 
##    1    2 
##  986 1514

visualisasi

pca <- prcomp(data_scaled)
pca_df <- as.data.frame(pca$x[,1:2])
pca_df$cluster <- factor(dbscan_result$cluster)

ggplot(pca_df, aes(PC1, PC2, color=cluster))+
  geom_point(size=2)+
  theme_minimal()+
  labs(title="DBSCAN – Deteksi Noise")

DBSCAN adalah mengelompokkan data berdasarkan kepadatan. Hasilnya menunjukkan bahwa adanya cluster utama serta beberapa data yang terdeteksi sebagai noise (outlier). Metode ini mampu mengidentifikasi struktur data tanpa menentukan jumlah cluster di awal. DBSCAN berhasil mengidentifikasi sejumlah data sebagai noise (cluster 0).

MEAN SHIFT Clustering

set.seed(123)

ms_result <- ms(data_scaled, h = 1)

# hasil cluster
cluster_ms <- ms_result$cluster.label
table(cluster_ms)
## cluster_ms
##    1 
## 2500
length(unique(cluster_ms))
## [1] 1

visualisasi

fviz_cluster(
  list(data = data_scaled, cluster = cluster_ms),
  geom = "point",
  ggtheme = theme_minimal(),
  main = "Mean Shift Clustering"
)

Metode Mean Shift merupakan salah satu teknik clustering berbasis kepadatan (density-based clustering). Berbeda dengan metode seperti K-Means atau K-Median, Mean Shift tidak memerlukan penentuan jumlah cluster di awal. Cluster akan terbentuk secara otomatis berdasarkan area yang memiliki kepadatan data paling tinggi, sehingga metode ini mampu menemukan pola alami dalam data tanpa asumsi jumlah kelompok sejak awal.

Berdasarkan hasil analisis, algoritma Mean Shift secara otomatis menghasilkan beberapa cluster. Hal ini menunjukkan bahwa data memiliki beberapa pusat kepadatan alami yang menggambarkan adanya kelompok mahasiswa dengan karakteristik yang mirip. Oleh karena itu, metode Mean Shift sangat cocok digunakan sebagai langkah eksplorasi awal untuk memahami struktur data, karena mampu mengidentifikasi pola pengelompokan tanpa perlu menentukan jumlah cluster terlebih dahulu.

FUZZY C-MEANS

set.seed(123)
fcm_result <- cmeans(data_scaled, centers = 2, m = 2)

head(fcm_result$membership)
##              1         2
## [1,] 0.5000118 0.4999882
## [2,] 0.4999799 0.5000201
## [3,] 0.4999466 0.5000534
## [4,] 0.5000316 0.4999684
## [5,] 0.4999770 0.5000230
## [6,] 0.4999765 0.5000235
cluster_fcm <- apply(fcm_result$membership, 1, which.max)

table(cluster_fcm)
## cluster_fcm
##    1    2 
## 1115 1385

visualisasi

fviz_cluster(
  list(data = data_scaled, cluster = cluster_fcm),
  geom = "point",
  ellipse.type = "norm",
  ggtheme = theme_minimal()
)

Fuzzy C-Means memungkinkan satu data memiliki derajat keanggotaan pada lebih dari satu cluster. Metode ini cocok untuk data dengan batas cluster yang tidak tegas. Hasil menunjukkan pola cluster yang cenderung overlap, menandakan karakteristik mahasiswa yang tidak sepenuhnya terpisah.

Evaluasi Semua Metode

safe_silhouette <- function(data, cluster){
    cluster <- as.numeric(as.factor(cluster))
    if(length(unique(cluster)) < 2){
    return(NA)  
  }
  
  sil <- silhouette(cluster, dist(data))
  mean(sil[,3])
}
sil_kmeans  <- safe_silhouette(data_scaled, kmeans_result$cluster)
sil_kmedian <- safe_silhouette(data_scaled, clusters(kmedian_result))
sil_dbscan  <- safe_silhouette(data_scaled, dbscan_result$cluster)
sil_meanshift <- safe_silhouette(data_scaled, cluster_ms)
sil_fcm <- safe_silhouette(data_scaled, cluster_fcm)

hasil_eval <- data.frame(
  Metode = c("KMeans","KMedian","DBSCAN","MeanShift","Fuzzy CMeans"),
  Silhouette = c(sil_kmeans, sil_kmedian, sil_dbscan, sil_meanshift, sil_fcm)
)

hasil_eval
##         Metode Silhouette
## 1       KMeans 0.13507213
## 2      KMedian 0.09963638
## 3       DBSCAN 0.13507213
## 4    MeanShift         NA
## 5 Fuzzy CMeans 0.11021706

Beberapa metode berbasis kepadatan seperti DBSCAN dan Mean Shift tidak selalu menghasilkan lebih dari satu cluster. Pada kondisi tersebut, nilai Silhouette tidak dapat dihitung sehingga ditandai sebagai NA. Hal ini menunjukkan bahwa struktur pemisahan data pada metode tersebut tidak cukup kuat untuk membentuk lebih dari satu kelompok yang jelas.

Visualisasi Perbadingan Per-Metode

ggplot(hasil_eval, aes(Metode, Silhouette, fill=Metode))+
  geom_col()+
  theme_minimal()+
  labs(title="Perbandingan Kualitas Clustering (Silhouette Score)")
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_col()`).

Berdasarkan hasil visualisasi menunjukkan bahwa perbandingan kualitas hasil clustering menggunakan metrik Silhouette Score pada lima metode yang diuji, yaitu K-Means, K-Median, DBSCAN, Mean Shift, dan Fuzzy C-Means. Semakin tinggi nilai Silhouette, semakin baik kualitas pemisahan antar cluster yang dihasilkan oleh suatu metode.

Berdasarkan grafik, metode K-Means dan DBSCAN memperoleh nilai Silhouette tertinggi, yaitu sekitar 0.135, yang menunjukkan bahwa kedua metode mampu menghasilkan pemisahan cluster yang relatif lebih baik dibandingkan metode lainnya. Metode Fuzzy C-Means berada pada posisi berikutnya dengan nilai sekitar 0.11, diikuti oleh K-Median dengan nilai sekitar 0.10. Sementara itu, metode Mean Shift tidak memiliki nilai Silhouette karena hanya menghasilkan satu cluster, sehingga tidak memungkinkan dilakukan evaluasi menggunakan metrik tersebut.

Meskipun K-Means dan DBSCAN memiliki nilai evaluasi yang sama, metode K-Means dipilih sebagai metode terbaik dalam penelitian ini. Hal ini disebabkan karena K-Means menghasilkan cluster yang lebih stabil, tidak mendeteksi noise seperti DBSCAN, serta lebih mudah diinterpretasikan melalui nilai centroid. Oleh karena itu, analisis karakteristik cluster selanjutnya difokuskan pada hasil clustering menggunakan metode K-Means.

EDA KHUSUS METODE TERBAIK

best_cluster <- kmeans_result$cluster
data_best <- data_sample
data_best$Cluster <- best_cluster

aggregate(. ~ Cluster, data=data_best, mean)
##   Cluster StudyHours Attendance AssignmentCompletion OnlineCourses Discussions
## 1       1   19.76065   80.08824             75.31440      9.982759           0
## 2       2   20.27477   80.09709             74.59775      9.978203           1
##   Motivation StressLevel ExamScore
## 1  0.8955375    1.341785  70.73327
## 2  0.8824306    1.297226  69.51123

Visualisasi

cluster_profile <- aggregate(. ~ Cluster, data=data_best, mean)
cluster_melt <- melt(cluster_profile, id="Cluster")

ggplot(cluster_melt, aes(variable, value, group=Cluster, color=factor(Cluster)))+
  geom_line(size=1.2)+
  geom_point(size=3)+
  theme_minimal()+
  labs(title="Profil Karakteristik Tiap Cluster Terbaik")

Berdasarkan metode clustering terbaik yang terpilih, dilakukan analisis karakteristik setiap cluster untuk memahami profil masing-masing kelompok mahasiswa. Hasil analisis menunjukkan bahwa setiap cluster memiliki pola perilaku belajar yang berbeda pada variabel StudyHours, Attendance, AssignmentCompletion, OnlineCourses, Discussions, Motivation, StressLevel, dan ExamScore. Perbedaan ini menggambarkan adanya segmentasi mahasiswa berdasarkan kebiasaan belajar, tingkat partisipasi, serta performa akademik.

Cluster dengan nilai rata-rata ExamScore yang lebih tinggi dapat diinterpretasikan sebagai kelompok mahasiswa dengan performa akademik lebih baik, sedangkan cluster dengan nilai StudyHours atau Discussions tinggi menunjukkan kecenderungan mahasiswa yang lebih aktif dalam proses pembelajaran. Analisis ini memberikan insight penting bahwa mahasiswa tidak dapat diperlakukan dengan pendekatan yang sama, sehingga strategi pembelajaran dapat disesuaikan dengan karakteristik masing-masing cluster.

KESIMPULAN

Penelitian ini melakukan segmentasi mahasiswa menggunakan lima metode clustering, yaitu K-Means, K-Median, DBSCAN, Mean Shift, dan Fuzzy C-Means setelah melalui tahap preprocessing dan standarisasi data. Evaluasi menggunakan Silhouette Score menunjukkan bahwa metode K-Means memiliki performa terbaik dan dipilih sebagai model final karena menghasilkan cluster yang stabil dan mudah diinterpretasikan.

Hasil clustering membagi mahasiswa menjadi dua kelompok utama dengan karakteristik perilaku belajar yang berbeda, yaitu kelompok dengan performa akademik lebih tinggi namun kurang aktif secara sosial, dan kelompok yang lebih aktif secara kolaboratif tetapi memiliki performa akademik relatif lebih rendah. Temuan ini menunjukkan pentingnya pendekatan pembelajaran yang berbeda untuk setiap kelompok mahasiswa.