Analisis ini menggunakan pendekatan CRISP-DM untuk menyelesaikan studi kasus prediksi status akademik mahasiswa.
Dataset yang digunakan adalah Prediksi Status Akademik
Mahasiswa dari Kaggle.
Dataset ini dipilih karena konteksnya mudah dipahami, yaitu berkaitan
dengan aktivitas dan performa akademik mahasiswa.
Metode yang digunakan adalah Decision Tree Classification karena target yang diprediksi berupa kategori, yaitu status akademik mahasiswa.
Permasalahan yang dianalisis adalah bagaimana membangun model yang dapat memprediksi status akademik mahasiswa berdasarkan data aktivitas dan performa akademiknya.
Atribut dalam dataset berkaitan dengan kegiatan akademik mahasiswa, seperti kehadiran, partisipasi diskusi, nilai tugas, aktivitas e-learning, dan IPK.
Karena target yang diprediksi berupa kelas atau
kategori, maka metode yang digunakan adalah
klasifikasi.
Algoritma yang dipilih adalah Decision Tree karena
hasilnya mudah dipahami dan dapat divisualisasikan dalam bentuk pohon
keputusan.
Tujuan analisis ini adalah:
Dataset diperoleh dari Kaggle dengan judul Prediksi Status Akademik Mahasiswa.
Link dataset:
https://www.kaggle.com/datasets/einherjar3451234123/prediksi-status-akademik-mahasiswa
File dataset diunduh terlebih dahulu dari Kaggle.
Setelah itu, file Excel disimpan dalam folder yang sama dengan file R
Markdown ini.
file_dataset <- file.choose()
file_dataset
## [1] "C:\\Users\\A S U S.LAPTOP-Q1GO7RFS\\Downloads\\Dataset_Mahasiswa_Kehadiran_Aktivitas_IPK.xlsx"
ext_file <- tools::file_ext(file_dataset)
if (ext_file %in% c("xlsx", "xls")) {
data_mahasiswa <- readxl::read_excel(file_dataset)
} else if (ext_file == "csv") {
data_mahasiswa <- read.csv(file_dataset)
} else {
stop("Format file belum didukung. Gunakan file .xlsx, .xls, atau .csv")
}
head(data_mahasiswa)
## # A tibble: 6 × 10
## Nama `Jenis Kelamin` Umur `Status Menikah` `Kehadiran (%)`
## <chr> <chr> <dbl> <chr> <dbl>
## 1 Kiki Ananda Laki-laki 20 Belum Menikah 73
## 2 Putri Fauzi Laki-laki 21 Belum Menikah 42
## 3 Mira Hidayat Laki-laki 25 Belum Menikah 71
## 4 Mira Ananda Laki-laki 23 Belum Menikah 44
## 5 Mira Septiani Laki-laki 21 Menikah 54
## 6 Eka Hidayat Perempuan 20 Menikah 53
## # ℹ 5 more variables: `Partisipasi Diskusi (skor)` <dbl>,
## # `Nilai Tugas (rata-rata)` <dbl>, `Aktivitas E-Learning (skor)` <dbl>,
## # IPK <dbl>, `Status Akademik` <chr>
Kode di atas digunakan untuk membaca file dataset secara langsung
dari lokasi penyimpanan di laptop.
Saat proses Knit dijalankan, R akan membuka pilihan file. Pilih file
dataset yang sudah diunduh dari Kaggle.
clean_names <- function(x) {
x <- tolower(x)
x <- gsub("[^a-z0-9]+", "_", x)
x <- gsub("^_|_$", "", x)
return(x)
}
names(data_mahasiswa) <- clean_names(names(data_mahasiswa))
names(data_mahasiswa)
## [1] "nama" "jenis_kelamin"
## [3] "umur" "status_menikah"
## [5] "kehadiran" "partisipasi_diskusi_skor"
## [7] "nilai_tugas_rata_rata" "aktivitas_e_learning_skor"
## [9] "ipk" "status_akademik"
Nama kolom dirapikan agar lebih mudah dipanggil dalam proses
analisis.
Huruf dibuat kecil dan spasi diganti menjadi garis bawah.
str(data_mahasiswa)
## tibble [500 × 10] (S3: tbl_df/tbl/data.frame)
## $ nama : chr [1:500] "Kiki Ananda" "Putri Fauzi" "Mira Hidayat" "Mira Ananda" ...
## $ jenis_kelamin : chr [1:500] "Laki-laki" "Laki-laki" "Laki-laki" "Laki-laki" ...
## $ umur : num [1:500] 20 21 25 23 21 20 24 19 20 18 ...
## $ status_menikah : chr [1:500] "Belum Menikah" "Belum Menikah" "Belum Menikah" "Belum Menikah" ...
## $ kehadiran : num [1:500] 73 42 71 44 54 53 64 57 77 73 ...
## $ partisipasi_diskusi_skor : num [1:500] 99 83 61 88 92 71 59 60 100 62 ...
## $ nilai_tugas_rata_rata : num [1:500] 91 53 87 62 67 92 86 84 99 84 ...
## $ aktivitas_e_learning_skor: num [1:500] 88 64 54 81 64 49 71 65 69 52 ...
## $ ipk : num [1:500] 3.77 3.55 2.73 3.59 3.02 1.52 2.93 1.66 3.87 2.37 ...
## $ status_akademik : chr [1:500] "Lulus" "Lulus" "Lulus" "Tidak" ...
dim(data_mahasiswa)
## [1] 500 10
summary(data_mahasiswa)
## nama jenis_kelamin umur status_menikah
## Length:500 Length:500 Min. :18.00 Length:500
## Class :character Class :character 1st Qu.:20.00 Class :character
## Mode :character Mode :character Median :22.00 Mode :character
## Mean :21.54
## 3rd Qu.:23.00
## Max. :25.00
## kehadiran partisipasi_diskusi_skor nilai_tugas_rata_rata
## Min. : 40.00 Min. : 40.00 Min. : 40.00
## 1st Qu.: 54.00 1st Qu.: 55.00 1st Qu.: 55.00
## Median : 69.00 Median : 69.50 Median : 69.00
## Mean : 69.43 Mean : 69.62 Mean : 70.18
## 3rd Qu.: 85.00 3rd Qu.: 84.00 3rd Qu.: 85.00
## Max. :100.00 Max. :100.00 Max. :100.00
## aktivitas_e_learning_skor ipk status_akademik
## Min. : 40.00 Min. :1.500 Length:500
## 1st Qu.: 54.00 1st Qu.:2.185 Class :character
## Median : 69.50 Median :2.815 Mode :character
## Mean : 69.48 Mean :2.806
## 3rd Qu.: 85.00 3rd Qu.:3.422
## Max. :100.00 Max. :3.990
colSums(is.na(data_mahasiswa))
## nama jenis_kelamin umur
## 0 0 0
## status_menikah kehadiran partisipasi_diskusi_skor
## 0 0 0
## nilai_tugas_rata_rata aktivitas_e_learning_skor ipk
## 0 0 0
## status_akademik
## 0
Missing value perlu diperiksa karena data kosong dapat mengganggu
proses pembangunan model.
Jika terdapat missing value, data tersebut akan dihapus agar model
dibangun menggunakan data yang lengkap.
data_clean <- na.omit(data_mahasiswa)
dim(data_clean)
## [1] 500 10
info_kolom <- data.frame(
Nama_Kolom = names(data_clean),
Tipe_Data = sapply(data_clean, function(x) class(x)[1]),
Jumlah_Nilai_Unik = sapply(data_clean, function(x) length(unique(x)))
)
info_kolom
## Nama_Kolom Tipe_Data Jumlah_Nilai_Unik
## nama nama character 278
## jenis_kelamin jenis_kelamin character 2
## umur umur numeric 8
## status_menikah status_menikah character 2
## kehadiran kehadiran numeric 61
## partisipasi_diskusi_skor partisipasi_diskusi_skor numeric 61
## nilai_tugas_rata_rata nilai_tugas_rata_rata numeric 61
## aktivitas_e_learning_skor aktivitas_e_learning_skor numeric 61
## ipk ipk numeric 213
## status_akademik status_akademik character 2
Tabel di atas digunakan untuk melihat nama kolom, tipe data, dan
jumlah nilai unik pada setiap kolom.
Kolom target klasifikasi biasanya memiliki jumlah nilai unik yang
sedikit, misalnya Lulus dan Tidak.
cek_target <- function(x) {
nilai <- unique(na.omit(tolower(trimws(as.character(x)))))
kondisi_jumlah <- length(nilai) >= 2 && length(nilai) <= 10
kondisi_isi <- any(grepl("lulus|tidak|gagal|berhasil|aktif|nonaktif|risiko|aman", nilai))
return(kondisi_jumlah && kondisi_isi)
}
target_candidates <- names(data_clean)[sapply(data_clean, cek_target)]
target_candidates
## [1] "status_akademik"
if (length(target_candidates) == 0) {
stop(
paste(
"Kolom target tidak ditemukan secara otomatis. Cek nama kolom berikut:",
paste(names(data_clean), collapse = ", ")
)
)
}
target_col <- target_candidates[1]
target_col
## [1] "status_akademik"
Kolom target ditentukan berdasarkan isi kolom yang memiliki kategori
seperti Lulus dan Tidak.
Kolom ini akan digunakan sebagai kelas yang diprediksi oleh model
Decision Tree.
kolom_identitas <- names(data_clean)[
grepl("nama|nim|id|no|nomor|mahasiswa_id|student_id", names(data_clean))
]
kolom_identitas <- setdiff(kolom_identitas, target_col)
kolom_identitas
## [1] "nama"
data_model <- data_clean %>%
select(-any_of(kolom_identitas))
head(data_model)
## # A tibble: 6 × 9
## jenis_kelamin umur status_menikah kehadiran partisipasi_diskusi_skor
## <chr> <dbl> <chr> <dbl> <dbl>
## 1 Laki-laki 20 Belum Menikah 73 99
## 2 Laki-laki 21 Belum Menikah 42 83
## 3 Laki-laki 25 Belum Menikah 71 61
## 4 Laki-laki 23 Belum Menikah 44 88
## 5 Laki-laki 21 Menikah 54 92
## 6 Perempuan 20 Menikah 53 71
## # ℹ 4 more variables: nilai_tugas_rata_rata <dbl>,
## # aktivitas_e_learning_skor <dbl>, ipk <dbl>, status_akademik <chr>
Kolom identitas seperti nama, NIM, ID, nomor, atau kode mahasiswa
tidak digunakan dalam model.
Kolom tersebut hanya berfungsi sebagai identitas data dan tidak
diperlukan dalam proses klasifikasi.
kolom_terlalu_unik <- names(data_model)[
sapply(data_model, function(x) length(unique(x)) > 0.9 * nrow(data_model))
]
kolom_terlalu_unik <- setdiff(kolom_terlalu_unik, target_col)
kolom_terlalu_unik
## character(0)
data_model <- data_model %>%
select(-any_of(kolom_terlalu_unik))
names(data_model)
## [1] "jenis_kelamin" "umur"
## [3] "status_menikah" "kehadiran"
## [5] "partisipasi_diskusi_skor" "nilai_tugas_rata_rata"
## [7] "aktivitas_e_learning_skor" "ipk"
## [9] "status_akademik"
Kolom yang hampir semua nilainya berbeda tidak digunakan dalam model
karena biasanya tidak membantu membentuk pola klasifikasi.
Contohnya adalah kolom ID atau nomor unik.
data_model[[target_col]] <- as.factor(data_model[[target_col]])
levels(data_model[[target_col]])
## [1] "Lulus" "Tidak"
jumlah_kelas_target <- nlevels(data_model[[target_col]])
jumlah_kelas_target
## [1] 2
Target diubah menjadi faktor karena Decision Tree digunakan untuk
klasifikasi.
Jika jumlah kelas target sedikit, maka target tersebut sesuai untuk
model klasifikasi.
data_model <- data_model %>%
mutate(across(where(is.character), as.factor))
str(data_model)
## tibble [500 × 9] (S3: tbl_df/tbl/data.frame)
## $ jenis_kelamin : Factor w/ 2 levels "Laki-laki","Perempuan": 1 1 1 1 1 2 1 2 2 2 ...
## $ umur : num [1:500] 20 21 25 23 21 20 24 19 20 18 ...
## $ status_menikah : Factor w/ 2 levels "Belum Menikah",..: 1 1 1 1 2 2 1 1 1 1 ...
## $ kehadiran : num [1:500] 73 42 71 44 54 53 64 57 77 73 ...
## $ partisipasi_diskusi_skor : num [1:500] 99 83 61 88 92 71 59 60 100 62 ...
## $ nilai_tugas_rata_rata : num [1:500] 91 53 87 62 67 92 86 84 99 84 ...
## $ aktivitas_e_learning_skor: num [1:500] 88 64 54 81 64 49 71 65 69 52 ...
## $ ipk : num [1:500] 3.77 3.55 2.73 3.59 3.02 1.52 2.93 1.66 3.87 2.37 ...
## $ status_akademik : Factor w/ 2 levels "Lulus","Tidak": 1 1 1 2 1 2 1 2 1 2 ...
if (!target_col %in% names(data_model)) {
stop("Kolom target tidak ditemukan dalam data_model.")
}
if (!is.factor(data_model[[target_col]])) {
stop("Kolom target belum berbentuk faktor.")
}
if (nlevels(data_model[[target_col]]) > 10) {
stop("Kolom target memiliki terlalu banyak kelas. Kemungkinan kolom target yang dipilih masih salah.")
}
Validasi ini memastikan bahwa kolom target benar-benar sesuai untuk
klasifikasi.
Target klasifikasi seharusnya berupa kategori, bukan angka identitas
atau angka bebas.
table(data_model[[target_col]])
##
## Lulus Tidak
## 270 230
jumlah_kelas <- length(levels(data_model[[target_col]]))
ggplot(data_model, aes(x = .data[[target_col]], fill = .data[[target_col]])) +
geom_bar(width = 0.6) +
scale_fill_manual(values = pal_pink[1:jumlah_kelas]) +
labs(
title = "Distribusi Status Akademik Mahasiswa",
x = "Status Akademik",
y = "Jumlah Data",
fill = "Status"
) +
theme_minimal() +
theme(
plot.title = element_text(color = "#c94f93", face = "bold", size = 16),
axis.title = element_text(color = "#8a5a73"),
legend.position = "bottom"
)
Grafik di atas menunjukkan jumlah data pada setiap status akademik
mahasiswa.
Distribusi target penting untuk diperhatikan karena dapat memengaruhi
performa model klasifikasi.
Data dibagi menjadi:
set.seed(123)
index_train <- sample(
1:nrow(data_model),
size = 0.8 * nrow(data_model)
)
data_train <- data_model[index_train, ]
data_test <- data_model[-index_train, ]
data_train[[target_col]] <- droplevels(data_train[[target_col]])
data_test[[target_col]] <- factor(
data_test[[target_col]],
levels = levels(data_train[[target_col]])
)
dim(data_train)
## [1] 400 9
dim(data_test)
## [1] 100 9
Data latih digunakan untuk membangun model Decision Tree.
Data uji digunakan untuk mengevaluasi kemampuan model dalam memprediksi
data baru.
fitur_model <- setdiff(names(data_train), target_col)
formula_model <- reformulate(
termlabels = fitur_model,
response = target_col
)
formula_model
## status_akademik ~ jenis_kelamin + umur + status_menikah + kehadiran +
## partisipasi_diskusi_skor + nilai_tugas_rata_rata + aktivitas_e_learning_skor +
## ipk
model_tree <- rpart(
formula_model,
data = data_train,
method = "class",
parms = list(split = "information"),
control = rpart.control(
cp = 0.005,
minsplit = 10,
maxdepth = 4
)
)
model_tree
## n= 400
##
## node), split, n, loss, yval, (yprob)
## * denotes terminal node
##
## 1) root 400 187 Lulus (0.53250000 0.46750000)
## 2) ipk>=2.495 251 83 Lulus (0.66932271 0.33067729)
## 4) nilai_tugas_rata_rata>=66.5 139 23 Lulus (0.83453237 0.16546763)
## 8) aktivitas_e_learning_skor>=53.5 115 11 Lulus (0.90434783 0.09565217) *
## 9) aktivitas_e_learning_skor< 53.5 24 12 Lulus (0.50000000 0.50000000)
## 18) ipk< 3.225 10 2 Lulus (0.80000000 0.20000000) *
## 19) ipk>=3.225 14 4 Tidak (0.28571429 0.71428571) *
## 5) nilai_tugas_rata_rata< 66.5 112 52 Tidak (0.46428571 0.53571429)
## 10) kehadiran>=78.5 35 10 Lulus (0.71428571 0.28571429)
## 20) aktivitas_e_learning_skor>=69.5 17 0 Lulus (1.00000000 0.00000000) *
## 21) aktivitas_e_learning_skor< 69.5 18 8 Tidak (0.44444444 0.55555556) *
## 11) kehadiran< 78.5 77 27 Tidak (0.35064935 0.64935065)
## 22) aktivitas_e_learning_skor>=97.5 3 0 Lulus (1.00000000 0.00000000) *
## 23) aktivitas_e_learning_skor< 97.5 74 24 Tidak (0.32432432 0.67567568) *
## 3) ipk< 2.495 149 45 Tidak (0.30201342 0.69798658)
## 6) nilai_tugas_rata_rata>=84.5 33 15 Lulus (0.54545455 0.45454545)
## 12) partisipasi_diskusi_skor>=71.5 15 3 Lulus (0.80000000 0.20000000)
## 24) umur>=19.5 12 1 Lulus (0.91666667 0.08333333) *
## 25) umur< 19.5 3 1 Tidak (0.33333333 0.66666667) *
## 13) partisipasi_diskusi_skor< 71.5 18 6 Tidak (0.33333333 0.66666667)
## 26) partisipasi_diskusi_skor< 41.5 3 0 Lulus (1.00000000 0.00000000) *
## 27) partisipasi_diskusi_skor>=41.5 15 3 Tidak (0.20000000 0.80000000) *
## 7) nilai_tugas_rata_rata< 84.5 116 27 Tidak (0.23275862 0.76724138)
## 14) partisipasi_diskusi_skor< 43.5 7 2 Lulus (0.71428571 0.28571429) *
## 15) partisipasi_diskusi_skor>=43.5 109 22 Tidak (0.20183486 0.79816514) *
Model Decision Tree dibangun menggunakan seluruh variabel selain
target sebagai prediktor.
Kriteria split yang digunakan adalah information,
sehingga pembentukan pohon berkaitan dengan konsep entropy dan
information gain.
Parameter maxdepth = 4 digunakan agar pohon keputusan tidak terlalu panjang dan tetap mudah dibaca.
jumlah_kelas_model <- length(levels(data_train[[target_col]]))
rpart.plot(
model_tree,
type = 4,
extra = 104,
fallen.leaves = TRUE,
under = TRUE,
faclen = 0,
varlen = 0,
branch = 0.8,
branch.col = "#d85c9f",
box.palette = as.list(pal_pink[1:jumlah_kelas_model]),
shadow.col = "#f8bbd0",
roundint = FALSE,
cex = 0.8,
main = "Decision Tree Prediksi Status Akademik Mahasiswa"
)
Visualisasi di atas menunjukkan pohon keputusan yang dibentuk oleh
software R.
Pohon ini memperlihatkan aturan yang digunakan model untuk menentukan
status akademik mahasiswa.
buat_label_aman <- function(x) {
x <- gsub('"', "'", x)
x <- gsub("<=", "≤", x)
x <- gsub(">=", "≥", x)
x <- gsub("<", "kurang dari", x)
x <- gsub(">", "lebih dari", x)
x <- gsub(",", ", ", x)
return(x)
}
hitung_entropy <- function(count_vector) {
total <- sum(count_vector)
if (total == 0) {
return(0)
}
p <- count_vector / total
p <- p[p > 0]
entropy <- -sum(p * log2(p))
return(round(entropy, 3))
}
frame_tree <- model_tree$frame
node_id <- as.numeric(row.names(frame_tree))
kelas <- levels(data_train[[target_col]])
jumlah_kelas <- length(kelas)
yval2 <- frame_tree$yval2
counts <- yval2[, 2:(jumlah_kelas + 1), drop = FALSE]
prediksi_node <- kelas[frame_tree$yval]
node_text <- c()
for (i in seq_along(node_id)) {
jumlah_data <- frame_tree$n[i]
entropy_value <- hitung_entropy(as.numeric(counts[i, ]))
jenis_node <- ifelse(
frame_tree$var[i] == "<leaf>",
"LEAF NODE",
paste0("SPLIT: ", frame_tree$var[i])
)
jumlah_per_kelas <- paste(
paste0(kelas, " = ", as.numeric(counts[i, ])),
collapse = "\\n"
)
hasil_prediksi <- prediksi_node[i]
label_node <- paste(
paste0("Node ", node_id[i]),
jenis_node,
paste0("Data = ", jumlah_data),
jumlah_per_kelas,
paste0("Entropy = ", entropy_value),
paste0("Prediksi = ", hasil_prediksi),
sep = "\\n"
)
warna_node <- ifelse(
frame_tree$var[i] == "<leaf>",
"#ffeaf4",
"#f8bbd0"
)
node_text[i] <- paste0(
node_id[i],
' [label = "',
buat_label_aman(label_node),
'", fillcolor = "',
warna_node,
'"];'
)
}
edge_text <- c()
for (parent in node_id[frame_tree$var != "<leaf>"]) {
children <- c(parent * 2, parent * 2 + 1)
for (child in children) {
if (child %in% node_id) {
path_child <- path.rpart(model_tree, nodes = child, print.it = FALSE)[[1]]
label_edge <- tail(path_child, 1)
label_edge <- buat_label_aman(label_edge)
edge_text <- c(
edge_text,
paste0(parent, " -> ", child, ' [label = "', label_edge, '"];')
)
}
}
}
dot_code <- paste0(
"
digraph decision_tree {
graph [
layout = dot,
rankdir = TB,
bgcolor = '#fff7fb',
labelloc = 't',
label = 'Visualisasi Decision Tree Status Akademik Mahasiswa dengan Entropy',
fontsize = 20,
fontname = 'Segoe UI',
fontcolor = '#c94f93',
ranksep = 0.60,
nodesep = 0.40
]
node [
shape = box,
style = 'filled, rounded',
fontname = 'Segoe UI',
fontsize = 12,
color = '#d85c9f',
penwidth = 2,
margin = 0.18
]
edge [
fontname = 'Segoe UI',
fontsize = 10,
color = '#c94f93',
fontcolor = '#8a3d68',
penwidth = 2
]
",
paste(node_text, collapse = "\n"),
"\n",
paste(edge_text, collapse = "\n"),
"
}
"
)
grViz(dot_code, width = "100%", height = "900px")
Visualisasi Decision Tree di atas dibuat untuk menampilkan informasi
yang lebih lengkap.
Setiap node menampilkan jumlah data, jumlah data pada masing-masing
kelas, nilai entropy, dan hasil prediksi.
Nilai entropy menunjukkan tingkat ketidakmurnian data pada
node.
Jika entropy semakin kecil, maka data pada node tersebut semakin
murni.
Jika entropy bernilai 0, berarti seluruh data pada node tersebut berada
pada satu kelas yang sama.
prediksi <- predict(model_tree, data_test, type = "class")
head(prediksi)
## 1 2 3 4 5 6
## Lulus Tidak Tidak Tidak Tidak Lulus
## Levels: Lulus Tidak
prediksi <- factor(prediksi, levels = levels(data_test[[target_col]]))
conf_matrix <- table(
Aktual = data_test[[target_col]],
Prediksi = prediksi
)
conf_matrix
## Prediksi
## Aktual Lulus Tidak
## Lulus 29 28
## Tidak 12 31
Confusion matrix digunakan untuk melihat jumlah prediksi benar dan
salah.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil
prediksi model.
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
accuracy
## [1] 0.6
kelas_eval <- levels(data_test[[target_col]])
metric_per_class <- data.frame(
Kelas = kelas_eval,
Precision = NA,
Recall = NA,
F1_Score = NA
)
for (i in seq_along(kelas_eval)) {
kelas_i <- kelas_eval[i]
TP <- conf_matrix[kelas_i, kelas_i]
FP <- sum(conf_matrix[, kelas_i]) - TP
FN <- sum(conf_matrix[kelas_i, ]) - TP
precision <- ifelse((TP + FP) == 0, 0, TP / (TP + FP))
recall <- ifelse((TP + FN) == 0, 0, TP / (TP + FN))
f1 <- ifelse((precision + recall) == 0, 0, 2 * precision * recall / (precision + recall))
metric_per_class$Precision[i] <- precision
metric_per_class$Recall[i] <- recall
metric_per_class$F1_Score[i] <- f1
}
metric_per_class
## Kelas Precision Recall F1_Score
## 1 Lulus 0.7073171 0.5087719 0.5918367
## 2 Tidak 0.5254237 0.7209302 0.6078431
hasil_evaluasi <- data.frame(
Metrik = c("Accuracy", "Macro Precision", "Macro Recall", "Macro F1-Score"),
Nilai = c(
accuracy,
mean(metric_per_class$Precision),
mean(metric_per_class$Recall),
mean(metric_per_class$F1_Score)
)
)
hasil_evaluasi
## Metrik Nilai
## 1 Accuracy 0.6000000
## 2 Macro Precision 0.6163704
## 3 Macro Recall 0.6148511
## 4 Macro F1-Score 0.5998399
Metrik evaluasi digunakan untuk menilai performa model.
ggplot(hasil_evaluasi, aes(x = Metrik, y = Nilai, fill = Metrik)) +
geom_col(width = 0.6) +
scale_fill_manual(values = pal_pink[1:nrow(hasil_evaluasi)]) +
ylim(0, 1) +
labs(
title = "Hasil Evaluasi Model Decision Tree",
x = "Metrik Evaluasi",
y = "Nilai"
) +
theme_minimal() +
theme(
plot.title = element_text(color = "#c94f93", face = "bold", size = 16),
axis.title = element_text(color = "#8a5a73"),
legend.position = "none"
)
## Interpretasi Evaluasi Model
Berdasarkan hasil evaluasi, model Decision Tree memperoleh nilai accuracy sebesar 60%. Nilai ini menunjukkan bahwa dari seluruh data uji, sekitar 60% data berhasil diklasifikasikan dengan benar oleh model.
Nilai macro precision sebesar 61.64% menunjukkan rata-rata ketepatan model ketika memberikan prediksi pada setiap kelas. Nilai macro recall sebesar 61.49% menunjukkan kemampuan model dalam menemukan data yang benar dari masing-masing kelas. Sementara itu, nilai macro F1-score sebesar 59.98% menunjukkan keseimbangan antara precision dan recall.
Secara umum, performa model dapat dikategorikan sedang. Artinya, model sudah mampu mengenali sebagian pola pada data, tetapi hasilnya belum sepenuhnya optimal. Kondisi ini masih wajar karena Decision Tree yang digunakan dibatasi kedalamannya agar visualisasi tetap sederhana dan mudah dibaca.
Nilai evaluasi menunjukkan bahwa model Decision Tree sudah dapat digunakan untuk melakukan klasifikasi status akademik mahasiswa. Namun, apabila nilai accuracy berada di sekitar 60%, maka performa model belum dapat dikatakan sangat baik. Model masih tergolong sedang, sehingga hasilnya perlu diinterpretasikan secara hati-hati.
Keputusan untuk tetap menggunakan Decision Tree pada analisis ini didasarkan pada keunggulan interpretasi. Decision Tree memungkinkan proses pengambilan keputusan ditampilkan dalam bentuk pohon, sehingga lebih mudah dipahami dibandingkan model yang lebih kompleks.
importance <- model_tree$variable.importance
if (is.null(importance)) {
importance_df <- data.frame(
Variabel = "Tidak ada variabel penting",
Nilai_Importance = 0
)
} else {
importance_df <- data.frame(
Variabel = names(importance),
Nilai_Importance = as.numeric(importance)
)
}
importance_df
## Variabel Nilai_Importance
## 1 ipk 35.063812
## 2 nilai_tugas_rata_rata 27.530325
## 3 aktivitas_e_learning_skor 24.511179
## 4 partisipasi_diskusi_skor 14.280827
## 5 kehadiran 12.179518
## 6 umur 4.318690
## 7 status_menikah 1.764682
## 8 jenis_kelamin 1.513081
ggplot(importance_df, aes(x = reorder(Variabel, Nilai_Importance), y = Nilai_Importance, fill = Variabel)) +
geom_col(width = 0.6) +
coord_flip() +
scale_fill_manual(values = pal_pink[1:nrow(importance_df)]) +
labs(
title = "Tingkat Kepentingan Variabel pada Decision Tree",
x = "Variabel",
y = "Nilai Importance"
) +
theme_minimal() +
theme(
plot.title = element_text(color = "#c94f93", face = "bold", size = 16),
axis.title = element_text(color = "#8a5a73"),
legend.position = "none"
)
Variable importance menunjukkan variabel mana yang paling berpengaruh
dalam proses klasifikasi.
Semakin tinggi nilai importance, semakin besar peran variabel tersebut
dalam membentuk model Decision Tree.
Berdasarkan model Decision Tree, status akademik mahasiswa diprediksi menggunakan beberapa atribut akademik dan aktivitas pembelajaran yang tersedia pada dataset. Model membaca pola dari data latih, kemudian membentuk aturan keputusan berdasarkan atribut yang paling mampu memisahkan kelas target.
Atribut yang muncul di bagian atas pohon keputusan merupakan atribut yang memiliki pengaruh besar pada proses pemisahan data. Berdasarkan grafik variable importance, variabel yang paling berpengaruh dalam model ini adalah ipk. Artinya, variabel tersebut memiliki peran paling besar dalam membantu model membedakan status akademik mahasiswa.
Proses kerja model dapat dipahami dari arah cabang pada pohon keputusan. Data mahasiswa akan masuk dari node paling atas, kemudian mengikuti aturan tertentu hingga sampai pada leaf node. Leaf node tersebut berisi kelas akhir yang menjadi hasil prediksi model.
Nilai entropy pada node menunjukkan tingkat ketidakmurnian data. Jika entropy masih besar, berarti data pada node tersebut masih bercampur antara beberapa kelas. Sebaliknya, jika entropy semakin kecil atau mendekati nol, berarti data pada node tersebut semakin murni dan lebih mudah diklasifikasikan.
Interpretasi utama dari model ini adalah bahwa Decision Tree mampu memberikan aturan klasifikasi yang mudah dipahami. Model tidak hanya memberikan hasil prediksi, tetapi juga menunjukkan jalur keputusan yang digunakan untuk menghasilkan prediksi tersebut.
Walaupun performa model belum sempurna, model tetap bermanfaat untuk memahami pola umum dalam data. Misalnya, atribut akademik tertentu dapat menjadi indikator penting dalam memprediksi status akademik mahasiswa.
Berdasarkan analisis menggunakan tahapan CRISP-DM, dataset Prediksi Status Akademik Mahasiswa dapat dianalisis menggunakan metode klasifikasi. Tahapan analisis dimulai dari pemahaman masalah, pemahaman data, preprocessing data, pembangunan model, evaluasi, interpretasi hasil, hingga penarikan kesimpulan.
Metode yang digunakan adalah Decision Tree Classification karena target data berupa kategori. Decision Tree sesuai digunakan pada studi kasus ini karena model dapat membentuk aturan keputusan yang mudah dipahami dan dapat divisualisasikan dalam bentuk pohon keputusan.
Hasil evaluasi menunjukkan bahwa model memperoleh accuracy sebesar 60%. Nilai ini menunjukkan bahwa model sudah mampu melakukan klasifikasi, tetapi performanya masih tergolong sedang dan belum optimal. Oleh karena itu, hasil prediksi model perlu digunakan secara hati-hati dan tidak dapat langsung dianggap sebagai keputusan akhir tanpa pertimbangan lain.
Performa model yang belum terlalu tinggi dapat disebabkan oleh beberapa faktor, seperti pola data yang belum sepenuhnya dapat dipisahkan dengan satu pohon keputusan, fitur yang belum cukup kuat, atau pembatasan kedalaman pohon agar visualisasi tetap mudah dibaca. Meskipun demikian, Decision Tree tetap dipertahankan karena tujuan analisis ini tidak hanya mengejar akurasi, tetapi juga menekankan kemudahan interpretasi model.
Secara keseluruhan, model Decision Tree dapat digunakan untuk memahami pola awal dalam prediksi status akademik mahasiswa. Untuk pengembangan selanjutnya, performa model dapat ditingkatkan dengan pengaturan parameter yang lebih optimal, penambahan fitur yang lebih relevan, atau perbandingan dengan metode lain seperti Random Forest.
Link dataset:
https://www.kaggle.com/datasets/einherjar3451234123/prediksi-status-akademik-mahasiswa
Link pengerjaan RPubs: