This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
# === LIBRARY ===
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.2 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
##
## The following object is masked from 'package:purrr':
##
## lift
library(e1071)
library(MASS)
##
## Attaching package: 'MASS'
##
## The following object is masked from 'package:dplyr':
##
## select
library(caTools)
library(psych)
##
## Attaching package: 'psych'
##
## The following objects are masked from 'package:ggplot2':
##
## %+%, alpha
library(lmtest)
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(corrplot)
## corrplot 0.95 loaded
# === LOAD DATA ===
data <- read.csv("students_dropout_academic_success.csv", header = TRUE)
colnames(data) <- make.names(colnames(data)) # bersihkan nama kolom
# === PREPROCESSING DATA ===
# Cek nilai yang hilang (missing values)
sum(is.na(data))
## [1] 0
# Mengganti nilai yang hilang dengan median untuk kolom numerik
data[] <- lapply(data, function(x) ifelse(is.numeric(x),
ifelse(is.na(x), median(x, na.rm = TRUE), x), x))
# Pastikan target adalah variabel faktor
data$target <- as.factor(data$target)
# === STATISTIK DESKRIPTIF ===
str(data)
## 'data.frame': 4424 obs. of 37 variables:
## $ Marital.Status : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Application.mode : int 17 17 17 17 17 17 17 17 17 17 ...
## $ Application.order : int 5 5 5 5 5 5 5 5 5 5 ...
## $ Course : int 171 171 171 171 171 171 171 171 171 171 ...
## $ Daytime.evening.attendance : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Previous.qualification : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Previous.qualification..grade. : num 122 122 122 122 122 122 122 122 122 122 ...
## $ Nacionality : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Mother.s.qualification : int 19 19 19 19 19 19 19 19 19 19 ...
## $ Father.s.qualification : int 12 12 12 12 12 12 12 12 12 12 ...
## $ Mother.s.occupation : int 5 5 5 5 5 5 5 5 5 5 ...
## $ Father.s.occupation : int 9 9 9 9 9 9 9 9 9 9 ...
## $ Admission.grade : num 127 127 127 127 127 ...
## $ Displaced : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Educational.special.needs : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Debtor : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Tuition.fees.up.to.date : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Gender : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Scholarship.holder : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Age.at.enrollment : int 20 20 20 20 20 20 20 20 20 20 ...
## $ International : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..credited. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..enrolled. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..evaluations. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..approved. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..grade. : num 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.1st.sem..without.evaluations.: int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..credited. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..enrolled. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..evaluations. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..approved. : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..grade. : num 0 0 0 0 0 0 0 0 0 0 ...
## $ Curricular.units.2nd.sem..without.evaluations.: int 0 0 0 0 0 0 0 0 0 0 ...
## $ Unemployment.rate : num 10.8 10.8 10.8 10.8 10.8 10.8 10.8 10.8 10.8 10.8 ...
## $ Inflation.rate : num 1.4 1.4 1.4 1.4 1.4 1.4 1.4 1.4 1.4 1.4 ...
## $ GDP : num 1.74 1.74 1.74 1.74 1.74 1.74 1.74 1.74 1.74 1.74 ...
## $ target : Factor w/ 1 level "Dropout": 1 1 1 1 1 1 1 1 1 1 ...
summary(data)
## Marital.Status Application.mode Application.order Course
## Min. :1 Min. :17 Min. :5 Min. :171
## 1st Qu.:1 1st Qu.:17 1st Qu.:5 1st Qu.:171
## Median :1 Median :17 Median :5 Median :171
## Mean :1 Mean :17 Mean :5 Mean :171
## 3rd Qu.:1 3rd Qu.:17 3rd Qu.:5 3rd Qu.:171
## Max. :1 Max. :17 Max. :5 Max. :171
## Daytime.evening.attendance Previous.qualification
## Min. :1 Min. :1
## 1st Qu.:1 1st Qu.:1
## Median :1 Median :1
## Mean :1 Mean :1
## 3rd Qu.:1 3rd Qu.:1
## Max. :1 Max. :1
## Previous.qualification..grade. Nacionality Mother.s.qualification
## Min. :122 Min. :1 Min. :19
## 1st Qu.:122 1st Qu.:1 1st Qu.:19
## Median :122 Median :1 Median :19
## Mean :122 Mean :1 Mean :19
## 3rd Qu.:122 3rd Qu.:1 3rd Qu.:19
## Max. :122 Max. :1 Max. :19
## Father.s.qualification Mother.s.occupation Father.s.occupation Admission.grade
## Min. :12 Min. :5 Min. :9 Min. :127.3
## 1st Qu.:12 1st Qu.:5 1st Qu.:9 1st Qu.:127.3
## Median :12 Median :5 Median :9 Median :127.3
## Mean :12 Mean :5 Mean :9 Mean :127.3
## 3rd Qu.:12 3rd Qu.:5 3rd Qu.:9 3rd Qu.:127.3
## Max. :12 Max. :5 Max. :9 Max. :127.3
## Displaced Educational.special.needs Debtor Tuition.fees.up.to.date
## Min. :1 Min. :0 Min. :0 Min. :1
## 1st Qu.:1 1st Qu.:0 1st Qu.:0 1st Qu.:1
## Median :1 Median :0 Median :0 Median :1
## Mean :1 Mean :0 Mean :0 Mean :1
## 3rd Qu.:1 3rd Qu.:0 3rd Qu.:0 3rd Qu.:1
## Max. :1 Max. :0 Max. :0 Max. :1
## Gender Scholarship.holder Age.at.enrollment International
## Min. :1 Min. :0 Min. :20 Min. :0
## 1st Qu.:1 1st Qu.:0 1st Qu.:20 1st Qu.:0
## Median :1 Median :0 Median :20 Median :0
## Mean :1 Mean :0 Mean :20 Mean :0
## 3rd Qu.:1 3rd Qu.:0 3rd Qu.:20 3rd Qu.:0
## Max. :1 Max. :0 Max. :20 Max. :0
## Curricular.units.1st.sem..credited. Curricular.units.1st.sem..enrolled.
## Min. :0 Min. :0
## 1st Qu.:0 1st Qu.:0
## Median :0 Median :0
## Mean :0 Mean :0
## 3rd Qu.:0 3rd Qu.:0
## Max. :0 Max. :0
## Curricular.units.1st.sem..evaluations. Curricular.units.1st.sem..approved.
## Min. :0 Min. :0
## 1st Qu.:0 1st Qu.:0
## Median :0 Median :0
## Mean :0 Mean :0
## 3rd Qu.:0 3rd Qu.:0
## Max. :0 Max. :0
## Curricular.units.1st.sem..grade.
## Min. :0
## 1st Qu.:0
## Median :0
## Mean :0
## 3rd Qu.:0
## Max. :0
## Curricular.units.1st.sem..without.evaluations.
## Min. :0
## 1st Qu.:0
## Median :0
## Mean :0
## 3rd Qu.:0
## Max. :0
## Curricular.units.2nd.sem..credited. Curricular.units.2nd.sem..enrolled.
## Min. :0 Min. :0
## 1st Qu.:0 1st Qu.:0
## Median :0 Median :0
## Mean :0 Mean :0
## 3rd Qu.:0 3rd Qu.:0
## Max. :0 Max. :0
## Curricular.units.2nd.sem..evaluations. Curricular.units.2nd.sem..approved.
## Min. :0 Min. :0
## 1st Qu.:0 1st Qu.:0
## Median :0 Median :0
## Mean :0 Mean :0
## 3rd Qu.:0 3rd Qu.:0
## Max. :0 Max. :0
## Curricular.units.2nd.sem..grade.
## Min. :0
## 1st Qu.:0
## Median :0
## Mean :0
## 3rd Qu.:0
## Max. :0
## Curricular.units.2nd.sem..without.evaluations. Unemployment.rate
## Min. :0 Min. :10.8
## 1st Qu.:0 1st Qu.:10.8
## Median :0 Median :10.8
## Mean :0 Mean :10.8
## 3rd Qu.:0 3rd Qu.:10.8
## Max. :0 Max. :10.8
## Inflation.rate GDP target
## Min. :1.4 Min. :1.74 Dropout:4424
## 1st Qu.:1.4 1st Qu.:1.74
## Median :1.4 Median :1.74
## Mean :1.4 Mean :1.74
## 3rd Qu.:1.4 3rd Qu.:1.74
## Max. :1.4 Max. :1.74
describe(data[, sapply(data, is.numeric)])
## vars n mean sd median
## Marital.Status 1 4424 1.00 0 1.00
## Application.mode 2 4424 17.00 0 17.00
## Application.order 3 4424 5.00 0 5.00
## Course 4 4424 171.00 0 171.00
## Daytime.evening.attendance 5 4424 1.00 0 1.00
## Previous.qualification 6 4424 1.00 0 1.00
## Previous.qualification..grade. 7 4424 122.00 0 122.00
## Nacionality 8 4424 1.00 0 1.00
## Mother.s.qualification 9 4424 19.00 0 19.00
## Father.s.qualification 10 4424 12.00 0 12.00
## Mother.s.occupation 11 4424 5.00 0 5.00
## Father.s.occupation 12 4424 9.00 0 9.00
## Admission.grade 13 4424 127.30 0 127.30
## Displaced 14 4424 1.00 0 1.00
## Educational.special.needs 15 4424 0.00 0 0.00
## Debtor 16 4424 0.00 0 0.00
## Tuition.fees.up.to.date 17 4424 1.00 0 1.00
## Gender 18 4424 1.00 0 1.00
## Scholarship.holder 19 4424 0.00 0 0.00
## Age.at.enrollment 20 4424 20.00 0 20.00
## International 21 4424 0.00 0 0.00
## Curricular.units.1st.sem..credited. 22 4424 0.00 0 0.00
## Curricular.units.1st.sem..enrolled. 23 4424 0.00 0 0.00
## Curricular.units.1st.sem..evaluations. 24 4424 0.00 0 0.00
## Curricular.units.1st.sem..approved. 25 4424 0.00 0 0.00
## Curricular.units.1st.sem..grade. 26 4424 0.00 0 0.00
## Curricular.units.1st.sem..without.evaluations. 27 4424 0.00 0 0.00
## Curricular.units.2nd.sem..credited. 28 4424 0.00 0 0.00
## Curricular.units.2nd.sem..enrolled. 29 4424 0.00 0 0.00
## Curricular.units.2nd.sem..evaluations. 30 4424 0.00 0 0.00
## Curricular.units.2nd.sem..approved. 31 4424 0.00 0 0.00
## Curricular.units.2nd.sem..grade. 32 4424 0.00 0 0.00
## Curricular.units.2nd.sem..without.evaluations. 33 4424 0.00 0 0.00
## Unemployment.rate 34 4424 10.80 0 10.80
## Inflation.rate 35 4424 1.40 0 1.40
## GDP 36 4424 1.74 0 1.74
## trimmed mad min max range
## Marital.Status 1.00 0 1.00 1.00 0
## Application.mode 17.00 0 17.00 17.00 0
## Application.order 5.00 0 5.00 5.00 0
## Course 171.00 0 171.00 171.00 0
## Daytime.evening.attendance 1.00 0 1.00 1.00 0
## Previous.qualification 1.00 0 1.00 1.00 0
## Previous.qualification..grade. 122.00 0 122.00 122.00 0
## Nacionality 1.00 0 1.00 1.00 0
## Mother.s.qualification 19.00 0 19.00 19.00 0
## Father.s.qualification 12.00 0 12.00 12.00 0
## Mother.s.occupation 5.00 0 5.00 5.00 0
## Father.s.occupation 9.00 0 9.00 9.00 0
## Admission.grade 127.30 0 127.30 127.30 0
## Displaced 1.00 0 1.00 1.00 0
## Educational.special.needs 0.00 0 0.00 0.00 0
## Debtor 0.00 0 0.00 0.00 0
## Tuition.fees.up.to.date 1.00 0 1.00 1.00 0
## Gender 1.00 0 1.00 1.00 0
## Scholarship.holder 0.00 0 0.00 0.00 0
## Age.at.enrollment 20.00 0 20.00 20.00 0
## International 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..credited. 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..enrolled. 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..evaluations. 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..approved. 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..grade. 0.00 0 0.00 0.00 0
## Curricular.units.1st.sem..without.evaluations. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..credited. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..enrolled. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..evaluations. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..approved. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..grade. 0.00 0 0.00 0.00 0
## Curricular.units.2nd.sem..without.evaluations. 0.00 0 0.00 0.00 0
## Unemployment.rate 10.80 0 10.80 10.80 0
## Inflation.rate 1.40 0 1.40 1.40 0
## GDP 1.74 0 1.74 1.74 0
## skew kurtosis se
## Marital.Status NaN NaN 0
## Application.mode NaN NaN 0
## Application.order NaN NaN 0
## Course NaN NaN 0
## Daytime.evening.attendance NaN NaN 0
## Previous.qualification NaN NaN 0
## Previous.qualification..grade. NaN NaN 0
## Nacionality NaN NaN 0
## Mother.s.qualification NaN NaN 0
## Father.s.qualification NaN NaN 0
## Mother.s.occupation NaN NaN 0
## Father.s.occupation NaN NaN 0
## Admission.grade -Inf NaN 0
## Displaced NaN NaN 0
## Educational.special.needs NaN NaN 0
## Debtor NaN NaN 0
## Tuition.fees.up.to.date NaN NaN 0
## Gender NaN NaN 0
## Scholarship.holder NaN NaN 0
## Age.at.enrollment NaN NaN 0
## International NaN NaN 0
## Curricular.units.1st.sem..credited. NaN NaN 0
## Curricular.units.1st.sem..enrolled. NaN NaN 0
## Curricular.units.1st.sem..evaluations. NaN NaN 0
## Curricular.units.1st.sem..approved. NaN NaN 0
## Curricular.units.1st.sem..grade. NaN NaN 0
## Curricular.units.1st.sem..without.evaluations. NaN NaN 0
## Curricular.units.2nd.sem..credited. NaN NaN 0
## Curricular.units.2nd.sem..enrolled. NaN NaN 0
## Curricular.units.2nd.sem..evaluations. NaN NaN 0
## Curricular.units.2nd.sem..approved. NaN NaN 0
## Curricular.units.2nd.sem..grade. NaN NaN 0
## Curricular.units.2nd.sem..without.evaluations. NaN NaN 0
## Unemployment.rate NaN NaN 0
## Inflation.rate NaN NaN 0
## GDP NaN NaN 0
# === MEMERIKSA KORELASI ANTAR VARIABEL ===
num_cols <- sapply(data, is.numeric)
corr_matrix <- cor(data[, num_cols], use = "complete.obs")
## Warning in cor(data[, num_cols], use = "complete.obs"): the standard deviation
## is zero
corrplot(corr_matrix, method = "color", type = "upper", tl.cex = 0.7)
# === REGRESI LOGISTIK ===
data_log <- data %>% filter(target %in% c("Graduate", "Dropout"))
set.seed(123)
split <- sample.split(data_log$target, SplitRatio = 0.7)
train <- subset(data_log, split == TRUE)
test <- subset(data_log, split == FALSE)
# Model regresi logistik
log_model <- glm(target ~ Admission.grade +
Curricular.units.1st.sem..approved. +
Unemployment.rate + Inflation.rate + GDP,
data = train, family = "binomial")
## Warning: glm.fit: algorithm did not converge
# Periksa koefisien model
summary(log_model)
##
## Call:
## glm(formula = target ~ Admission.grade + Curricular.units.1st.sem..approved. +
## Unemployment.rate + Inflation.rate + GDP, family = "binomial",
## data = train)
##
## Coefficients: (5 not defined because of singularities)
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -26.57 6400.31 -0.004 0.997
## Admission.grade NA NA NA NA
## Curricular.units.1st.sem..approved. NA NA NA NA
## Unemployment.rate NA NA NA NA
## Inflation.rate NA NA NA NA
## GDP NA NA NA NA
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 0.0000e+00 on 3095 degrees of freedom
## Residual deviance: 1.7962e-08 on 3095 degrees of freedom
## AIC: 2
##
## Number of Fisher Scoring iterations: 25
# Prediksi
log_prob <- predict(log_model, newdata = test, type = "response")
log_class <- ifelse(log_prob > 0.5, "Graduate", "Dropout") %>% as.factor()
# Memeriksa distribusi kelas pada hasil prediksi
table(log_class)
## log_class
## Dropout
## 1328
# Memastikan kedua kelas ada di data uji dan prediksi
if (length(unique(test$target)) == 2 && length(unique(log_class)) == 2) {
confusionMatrix(log_class, test$target)
} else {
message("Data uji atau prediksi tidak mengandung dua kelas yang berbeda.")
}
## Data uji atau prediksi tidak mengandung dua kelas yang berbeda.
# === LDA ===
# Cek distribusi setiap variabel dalam setiap kelas target sebelum LDA
vars <- c("Admission.grade", "Curricular.units.1st.sem..approved.",
"Unemployment.rate", "Inflation.rate", "GDP")
# Tampilkan ringkasan per kelas
for (v in vars) {
print(paste("Distribusi untuk", v))
print(by(train[[v]], train$target, summary))
}
## [1] "Distribusi untuk Admission.grade"
## train$target: Dropout
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 127.3 127.3 127.3 127.3 127.3 127.3
## [1] "Distribusi untuk Curricular.units.1st.sem..approved."
## train$target: Dropout
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 0 0 0 0
## [1] "Distribusi untuk Unemployment.rate"
## train$target: Dropout
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 10.8 10.8 10.8 10.8 10.8 10.8
## [1] "Distribusi untuk Inflation.rate"
## train$target: Dropout
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.4 1.4 1.4 1.4 1.4 1.4
## [1] "Distribusi untuk GDP"
## train$target: Dropout
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.74 1.74 1.74 1.74 1.74 1.74
# Periksa variasi dalam setiap kelas untuk setiap variabel
valid_vars <- vars[sapply(vars, function(v) {
all(tapply(train[[v]], train$target, function(x) length(unique(x))) > 1)
})]
# Periksa apakah masih ada variabel valid untuk LDA
if (length(valid_vars) >= 1) {
# Buat formula LDA dinamis
lda_formula <- as.formula(paste("target ~", paste(valid_vars, collapse = " + ")))
# Fit LDA model
lda_model <- lda(lda_formula, data = train)
# Prediksi dan evaluasi
lda_pred <- predict(lda_model, test)
confusionMatrix(lda_pred$class, test$target)
# Simpan hasil komponen LDA ke data test
test$LDA1 <- lda_pred$x[, 1]
if (ncol(lda_pred$x) > 1) {
test$LDA2 <- lda_pred$x[, 2]
ggplot(test, aes(x = LDA1, y = LDA2, color = target)) +
geom_point(alpha = 0.7) +
labs(title = "LDA Scatter Plot (2D)", x = "LDA 1", y = "LDA 2") +
theme_minimal()
} else {
ggplot(test, aes(x = LDA1, fill = target)) +
geom_density(alpha = 0.7) +
labs(title = "LDA Projection (1D)", x = "LDA 1", y = "Density") +
theme_minimal()
}
} else {
message("Tidak ada variabel yang memiliki variasi cukup dalam setiap kelas untuk LDA.")
}
## Tidak ada variabel yang memiliki variasi cukup dalam setiap kelas untuk LDA.
# === UJI ASUMSI LDA ===
# Uji Normalitas untuk setiap kelas (contoh untuk variabel Admission.grade)
# Uji normalitas hanya jika nilai tidak identik
unique_test <- by(data$Admission.grade, data$target, function(x) {
if (length(unique(x)) > 1) {
return(shapiro.test(x))
} else {
return("Semua nilai identik, tidak bisa dilakukan uji normalitas.")
}
})
print(unique_test)
## data$target: Dropout
## [1] "Semua nilai identik, tidak bisa dilakukan uji normalitas."
# Uji Homogenitas Varians (Box's M Test)
# === UJI ASUMSI LDA ===
# Pastikan fungsi boxM tersedia
if (!require("biotools")) install.packages("biotools")
## Loading required package: biotools
## ---
## biotools version 4.3
library(biotools)
# Filter hanya data dengan dua kelas
lda_data <- data %>% filter(target %in% c("Graduate", "Dropout"))
# Pilih variabel yang tidak konstan antar kelas
vars <- c("Admission.grade", "Unemployment.rate", "Inflation.rate", "GDP")
valid_vars <- vars[sapply(vars, function(v) {
all(tapply(lda_data[[v]], lda_data$target, function(x) length(unique(x)) > 1))
})]
if (length(valid_vars) >= 2) {
boxM_result <- boxM(lda_data[, valid_vars], lda_data$target)
print(boxM_result)
} else {
message("Tidak cukup variabel dengan variasi untuk menjalankan Box's M Test.")
}
## Tidak cukup variabel dengan variasi untuk menjalankan Box's M Test.
You can also embed plots, for example:
## Warning in cor(data[, num_cols], use = "complete.obs"): the standard deviation
## is zero
## LDA model tidak tersedia, visualisasi tidak dilakukan.
Note that the echo = FALSE parameter was added to the
code chunk to prevent printing of the R code that generated the
plot.