# Data manipulation & preprocessing
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.2.3
##
## 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(stringr)
## Warning: package 'stringr' was built under R version 4.2.3
library(forcats)
## Warning: package 'forcats' was built under R version 4.2.3
library(readr)
## Warning: package 'readr' was built under R version 4.2.3
library(readxl)
## Warning: package 'readxl' was built under R version 4.2.3
# Modeling & Evaluation
library(caret) # Framework modeling
## Warning: package 'caret' was built under R version 4.2.3
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 4.2.3
## Loading required package: lattice
library(randomForest) # Random Forest
## Warning: package 'randomForest' was built under R version 4.2.3
## randomForest 4.7-1.1
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
##
## margin
## The following object is masked from 'package:dplyr':
##
## combine
library(xgboost) # XGBoost
## Warning: package 'xgboost' was built under R version 4.2.3
##
## Attaching package: 'xgboost'
## The following object is masked from 'package:dplyr':
##
## slice
library(pROC) # ROC Curve & AUC
## Warning: package 'pROC' was built under R version 4.2.3
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
library(smotefamily) # SMOTE
## Warning: package 'smotefamily' was built under R version 4.2.3
# Visualization
library(ggplot2)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.2.3
## corrplot 0.92 loaded
# Preprocessing / Outlier Handling
library(DescTools) # Winsorize
## Warning: package 'DescTools' was built under R version 4.2.3
##
## Attaching package: 'DescTools'
## The following objects are masked from 'package:caret':
##
## MAE, RMSE
library(robustHD) # Outlier detection
## Warning: package 'robustHD' was built under R version 4.2.3
## Loading required package: perry
## Warning: package 'perry' was built under R version 4.2.3
## Loading required package: parallel
## Loading required package: robustbase
## Warning: package 'robustbase' was built under R version 4.2.3
rumah_tangga <- read.csv("rumah_tangga.csv")
rumah_tangga
summary(rumah_tangga[, c("jumlah_art", "konsumsi_listrik_kwh", "jumlah_mobil", "jumlah_motor")])
## jumlah_art konsumsi_listrik_kwh jumlah_mobil jumlah_motor
## Min. : 1.000 Min. : 0.0 Min. :0.0000 Min. :0.000
## 1st Qu.: 3.000 1st Qu.: 117.0 1st Qu.:0.0000 1st Qu.:1.000
## Median : 4.000 Median : 211.0 Median :0.0000 Median :1.000
## Mean : 4.319 Mean : 296.9 Mean :0.2504 Mean :1.525
## 3rd Qu.: 5.000 3rd Qu.: 360.0 3rd Qu.:0.0000 3rd Qu.:2.000
## Max. :28.000 Max. :6256.0 Max. :2.0000 Max. :7.000
## NA's :69 NA's :68
data_kat <- rumah_tangga %>% select(where(~is.character(.) | is.factor(.)))
data_kat <- data.frame(lapply(data_kat, as.factor))
tabel<- function(var) {
var_data <- data_kat[[var]]
freq_table <- table(var_data, useNA = "no") # hanya hitung non-NA
top_value <- names(which.max(freq_table))
top_freq <- max(freq_table)
data.frame(
variable = var,
count = sum(!is.na(var_data)), # jumlah data non-NA
na = sum(is.na(var_data)), # jumlah NA
unique = length(unique(na.omit(var_data))),
top = top_value,
freq = top_freq
)
}
tabel_des <- lapply(names(data_kat), tabel) %>% bind_rows()
tabel_des
#Status Kemiskinan
miskin <- rumah_tangga %>%
count(status_miskin) %>%
mutate(
prop = n / sum(n),
label = paste0(round(prop * 100, 1), "%")
)
# Pie chart
ggplot(miskin, aes(x = "", y = prop, fill = status_miskin)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
labs(title = "Proporsi Status Kemiskinan") +
scale_fill_manual(values = c("Miskin" = "red", "Tidak Miskin" = "lightgreen")) +
theme_void() +
geom_text(aes(label = label),
position = position_stack(vjust = 0.5),
color = "black", size = 5) +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold")
)
Menunjukkan proporsi rumah tangga miskin vs tidak miskin untuk melihat
apakah kelas target imbalanced (tidak seimbang).Distribusi menunjukkan
bahwa sebagian besar rumah tangga tergolong tidak miskin. Rumah tangga
miskin hanya sekitar ¼ dari total populasi, menandakan bahwa data
bersifat imbalanced.
# Histogram Jumlah ART
ggplot(rumah_tangga, aes(x = jumlah_art)) +
geom_histogram(bins = 15, fill = "skyblue", color = "white") +
labs(title = "Distribusi Jumlah Anggota Rumah Tangga", x = "Jumlah ART", y = "Frequency") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold")
)
# Histogram Konsumsi Listrik
ggplot(rumah_tangga, aes(x = konsumsi_listrik_kwh)) +
geom_histogram(bins = 25, fill = "skyblue", color = "white") +
labs(title = "Distribusi Konsumsi Listrik (kWh)", x = "Konsumsi Listrik (kWh)", y = "Frequency") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold")
)
## Warning: Removed 69 rows containing non-finite outside the scale range
## (`stat_bin()`).
# Histogram Jumlah Mobil
ggplot(rumah_tangga, aes(x = jumlah_mobil)) +
geom_histogram(bins = 3, fill = "skyblue", color = "white") +
labs(title = "Distribusi Jumlah Mobil", x = "Jumlah Mobil", y = "Frequency") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold")
)
# Histogram Jumlah Motor
ggplot(rumah_tangga, aes(x = jumlah_motor)) +
geom_histogram(bins = 8, fill = "skyblue", color = "white") +
labs(title = "Distribusi Jumlah Motor", x = "Jumlah Motor", y = "Frequency") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold")
)
## Warning: Removed 68 rows containing non-finite outside the scale range
## (`stat_bin()`).
### Hubungan Variabel Numerik dengan Status Miskin
# Jumlah ART vs Status Miskin
ggplot(rumah_tangga, aes(x = as.factor(status_miskin), y = jumlah_art)) +
geom_boxplot(fill = c("lightgreen", "tomato")) +
labs(title = "Jumlah ART berdasarkan Status Kemiskinan",
x = "Status Miskin", y = "Jumlah Anggota RT") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
# Konsumsi Listrik vs Status Miskin
ggplot(rumah_tangga, aes(x = as.factor(status_miskin), y = konsumsi_listrik_kwh)) +
geom_boxplot(fill = c("lightgreen", "tomato")) +
labs(title = "Konsumsi Listrik berdasarkan Status Kemiskinan",
x = "Status Miskin", y = "Konsumsi Listrik (kWh)") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
## Warning: Removed 69 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
# Jumlah Mobil vs Status Miskin
ggplot(rumah_tangga, aes(x = as.factor(status_miskin), y = jumlah_mobil)) +
geom_boxplot(fill = c("lightgreen", "tomato")) +
labs(title = "Jumlah Mobil berdasarkan Status Kemiskinan",
x = "Status Miskin", y = "Jumlah Mobil") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
# Jumlah Motor vs Status Miskin
ggplot(rumah_tangga, aes(x = as.factor(status_miskin), y = jumlah_motor)) +
geom_boxplot(fill = c("lightgreen", "tomato")) +
labs(title = "Jumlah Motor berdasarkan Status Kemiskinan",
x = "Status Miskin", y = "Jumlah Motor") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
## Warning: Removed 68 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
Sebagian besar rumah tangga memiliki 3 hingga 5 anggota. Rumah tangga
miskin cenderung memiliki jumlah anggota lebih banyak, yang tercermin
dari sebaran nilai jumlah_art yang lebih tinggi. Hal ini menunjukkan
beban tanggungan yang lebih besar, yang dapat memengaruhi kondisi
ekonomi rumah tangga secara keseluruhan.
Distribusi konsumsi listrik menceng ke kanan (right-skewed), menunjukkan bahwa sebagian besar rumah tangga menggunakan listrik dalam jumlah kecil. Kelompok miskin memiliki konsumsi listrik yang jauh lebih rendah dibanding tidak miskin, bahkan banyak yang nol, mengindikasikan keterbatasan akses terhadap energi dasar.
Mayoritas rumah tangga tidak memiliki mobil, sedangkan motor lebih umum tetapi tidak merata. Rumah tangga miskin hampir tidak memiliki kendaraan sama sekali, menunjukkan keterbatasan mobilitas dan aset fisik. Perbedaan ini mencerminkan kesenjangan ekonomi yang cukup jelas antar kelompok.
# Korelasi
cor_data <- rumah_tangga[, c("jumlah_art", "jumlah_mobil", "jumlah_motor", "konsumsi_listrik_kwh")]
cor_matrix <- cor(cor_data, use = "complete.obs")
# Buat corrplot
corrplot(cor_matrix,
method = "color", # Kotak berwarna
type = "upper", # Tampilkan hanya bagian atas
order = "hclust", # Urutkan berdasarkan clustering
addCoef.col = "black", # Tambah nilai korelasi
tl.col = "black", # Warna label
tl.srt = 45, # Rotasi label
col = colorRampPalette(c("red", "white", "blue"))(200), # Skala warna
number.cex = 0.9, # Ukuran angka korelasi
tl.cex = 0.9, # Ukuran teks label
mar = c(0,0,1,0)) # Margin judul
Terdapat korelasi positif moderat antara jumlah_motor, jumlah_mobil, dan
konsumsi_listrik_kwh, menunjukkan keterkaitan antar indikator kemampuan
ekonomi rumah tangga. Sementara korelasi dengan jumlah_art relatif lebih
lemah.
kategorik <- c(
"pendidikan_krt", "pendidikan_art_tertinggi", "pekerjaan_krt",
"jenis_dinding", "jenis_atap", "jenis_lantai", "kepemilikan_toilet",
"sumber_air_minum", "daya_terpasang_pln", "kepemilikan_kulkas",
"kepemilikan_mesin_cuci", "kepemilikan_ac", "kepemilikan_komputer",
"internet_kabel"
)
# Loop untuk buat plot per variabel
for (var in kategorik) {
p <- ggplot(rumah_tangga, aes_string(x = var, fill = "as.factor(status_miskin)")) +
geom_bar(position = "fill") +
scale_fill_manual(values = c("tomato","lightgreen")) +
labs(
title = paste("Proporsi Status Kemiskinan menurut", gsub("_", " ", var)),
x = gsub("_", " ", var),
y = "Proporsi",
fill = "Status Miskin"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
axis.text.x = element_text(angle = 20, hjust = 1)
)
print(p)
}
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
for (var in kategorik) {
p <- ggplot(rumah_tangga, aes_string(x = var, fill = "as.factor(status_miskin)")) +
geom_bar(position = "stack") + # jumlah, bukan proporsi
scale_fill_manual(values = c("tomato", "lightgreen")) +
labs(
title = paste("Jumlah Rumah Tangga menurut", gsub("_", " ", var)),
x = gsub("_", " ", var),
y = "Jumlah",
fill = "Status Miskin"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
axis.text.x = element_text(angle = 20, hjust = 1)
)
print(p)
}
Rumah tangga miskin lebih banyak memiliki dinding dari bahan tidak permanen seperti bambu atau kayu. Sementara rumah tangga tidak miskin didominasi oleh dinding tembok atau plester. Hal ini menunjukkan bahwa kualitas tempat tinggal menjadi indikator penting kesejahteraan.
Atap dari rumbia atau seng lebih sering ditemukan pada rumah tangga miskin, sedangkan rumah tangga tidak miskin lebih banyak menggunakan genteng atau bahan atap permanen lainnya.
Rumah tangga miskin lebih banyak memiliki lantai dari tanah atau papan, sedangkan rumah tangga tidak miskin cenderung menggunakan keramik atau semen.
Rumah tangga yang tidak memiliki toilet pribadi yang layak (bersama/tidak layak) lebih sering ditemukan pada kelompok miskin. Sebaliknya, rumah tangga dengan toilet pribadi yang layak mayoritas tidak miskin. Akses terhadap fasilitas sanitasi pribadi yang layak merupakan penentu penting kesejahteraan. Ketiadaan toilet pribadi layak mencerminkan kondisi ekonomi dan kualitas hidup yang lebih rendah.
Rumah tangga yang menggunakan air tidak layak (seperti sungai, sumur terbuka) mayoritas berada dalam kelompok miskin. Keterbatasan akses terhadap air minum yang aman berkaitan erat dengan kemiskinan, baik karena faktor geografis maupun finansial.
Tingkat pendidikan kepala rumah tangga sangat berasosiasi dengan kemiskinan. Pendidikan rendah (tidak sekolah/SD) dominan pada kelompok miskin, sedangkan pendidikan menengah ke atas lebih banyak dimiliki oleh rumah tangga tidak miskin.
Jenis pekerjaan informal seperti buruh, tani, atau tidak bekerja lebih sering ditemukan pada kelompok miskin. Sebaliknya, pegawai, pedagang tetap, dan profesi lainnya lebih umum pada kelompok tidak miskin. Jenis pekerjaan mencerminkan kestabilan pendapatan.
# Data awal
nrow(rumah_tangga)
## [1] 1366
# Cek jumlah duplikat
sum(duplicated(rumah_tangga))
## [1] 10
# Cek kolom yang duplikat
rumah_tangga[duplicated(rumah_tangga), ] %>%
arrange(id_rt)
# Hapus duplikat
rumah_tangga <- rumah_tangga %>%
distinct(id_rt, .keep_all = TRUE)
# Data setelah penanganan duplikat
nrow(rumah_tangga)
## [1] 1356
rumah_tangga <- rumah_tangga %>%
select(-daya_terpasang_watt)
dat_clear1 <- rumah_tangga
dat_clear1$konsumsi_listrik_kwh[is.na(dat_clear1$konsumsi_listrik_kwh)] <-
median(dat_clear1$konsumsi_listrik_kwh, na.rm = TRUE)
dat_clear1$jumlah_motor[is.na(dat_clear1$jumlah_motor)] <-
median(dat_clear1$jumlah_motor, na.rm = TRUE)
# Pendidikan ART Tertinggi
# Cek Modus
modus_art <- names(sort(table(dat_clear1$pendidikan_art_tertinggi), decreasing = TRUE))[1]
# Imputasi
dat_clear1$pendidikan_art_tertinggi[is.na(dat_clear1$pendidikan_art_tertinggi)] <- modus_art
# Cek modus
modus_pekerjaan_krt <- names(sort(table(dat_clear1$pekerjaan_krt), decreasing = TRUE))[1]
# Imputasi
dat_clear1$pekerjaan_krt[is.na(dat_clear1$pekerjaan_krt)] <- modus_pekerjaan_krt
sum(is.na(dat_clear1))
## [1] 0
p99 <- quantile(dat_clear1$konsumsi_listrik_kwh, 0.99)
dat_clear1$konsumsi_listrik_no_outlier <- pmin(dat_clear1$konsumsi_listrik_kwh, p99)
par(mfrow = c(1, 2)) # Bagi area plot menjadi 1 baris 2 kolom
boxplot(dat_clear1$konsumsi_listrik_kwh,
main = "Sebelum Winsorizing",
ylab = "kWh per Bulan",
col = "skyblue")
boxplot(dat_clear1$konsumsi_listrik_no_outlier,
main = "Sesudah Winsorizing",
ylab = "kWh per Bulan",
col = "tomato")
par(mfrow = c(1, 1)) # Kembalikan layout ke normal
data_encoded <- dat_clear1 %>%
mutate(
# Ordinal encoding
pendidikan_krt = as.numeric(factor(pendidikan_krt,
levels = c("Tidak Sekolah", "SD", "SMP", "SMA", "Diploma/S1+"),
ordered = TRUE)),
pendidikan_art_tertinggi = as.numeric(factor(pendidikan_art_tertinggi,
levels = c("Tidak Sekolah", "SD", "SMP", "SMA", "Diploma/S1+"),
ordered = TRUE)),
daya_terpasang_pln = as.numeric(factor(daya_terpasang_pln,
levels = c("450", "900", "1300", "2200", ">2200"),
ordered = TRUE)),
# Label encoding
pekerjaan_krt = as.numeric(factor(pekerjaan_krt)),
jenis_dinding = as.numeric(factor(jenis_dinding)),
jenis_atap = as.numeric(factor(jenis_atap)),
jenis_lantai = as.numeric(factor(jenis_lantai)),
kepemilikan_toilet = as.numeric(factor(kepemilikan_toilet)),
sumber_air_minum = as.numeric(factor(sumber_air_minum)),
kepemilikan_kulkas = as.numeric(factor(kepemilikan_kulkas)),
kepemilikan_mesin_cuci = as.numeric(factor(kepemilikan_mesin_cuci)),
kepemilikan_ac = as.numeric(factor(kepemilikan_ac)),
kepemilikan_komputer = as.numeric(factor(kepemilikan_komputer)),
internet_kabel = as.numeric(factor(internet_kabel)),
status_miskin = ifelse(status_miskin == "Miskin", 1, 0),
status_miskin = factor(status_miskin,
levels = c(1, 0),
labels = c("Miskin", "Tidak_Miskin"))
)
data_fix_clear1 <- data_encoded %>%
mutate(
# Kategori jumlah ART
kategori_art = as.numeric(factor(ifelse(jumlah_art <= 4, 0, 1))),
# Total kendaraan & keberadaan kendaraan
total_kendaraan = jumlah_motor + jumlah_mobil,
keberadaan_kendaraan = ifelse(total_kendaraan > 0, 1, 0),
# Bangunan tidak permanen
bangunan_tidak_permanen =
as.integer(jenis_dinding == 1) + # "Bambu/Lainnya"
as.integer(jenis_lantai == 3) + # "Tanah"
as.integer(jenis_atap == 2), # "Ijuk/Lainnya"
kualitas_bangunan = as.numeric(factor(
ifelse(bangunan_tidak_permanen == 0, 0, 1)
)),
# Akses layanan dasar
akses_layanan_dasar = as.numeric(factor(
ifelse(kepemilikan_toilet == 2 & sumber_air_minum == 1, # "Milik Sendiri/Layak" & "Layak"
0, 1)
)),
# Kategori pendidikan KRT (sudah ordinal 1-5)
kategori_pendidikan = as.numeric(factor(case_when(
pendidikan_krt <= 3 ~ 1, # Tidak Sekolah, SD, SMP
pendidikan_krt >= 4 ~ 0),
ordered = TRUE
)),
# Kategori pekerjaan KRT berdasarkan angka hasil encoding
kategori_pekerjaan = as.numeric(factor(case_when(
pekerjaan_krt == 4 ~ "Tidak Bekerja", # "Tidak Bekerja"
pekerjaan_krt %in% c(2, 3) ~ "Informal",# "Informal" dan "Pertanian"
pekerjaan_krt == 1 ~ "Formal", # "Formal"
))
)
)
set.seed(123)
split <- createDataPartition(data_fix_clear1$status_miskin, p = 0.8, list = FALSE)
train_data <- data_fix_clear1[split, ]
test_data <- data_fix_clear1[-split, ]
X <- train_data[, !names(train_data) %in% c("status_miskin")]
y <- train_data$status_miskin
smote_result <- SMOTE(X = X, target = y, K = 5, dup_size = 3) # dup_size = perc.over / 100
train_data_smote <- smote_result$data
colnames(train_data_smote)[ncol(train_data_smote)] <- "status_miskin"
train_data_smote$status_miskin <- as.factor(train_data_smote$status_miskin)
# Train Control
ctrl <- trainControl(
method = "cv", number = 5,
classProbs = TRUE,
summaryFunction = twoClassSummary
)
# Pastikan target jadi faktor dengan 2 level
train_data_smote$status_miskin <- as.factor(train_data_smote$status_miskin)
test_data$status_miskin <- as.factor(test_data$status_miskin)
summary(train_data_smote$status_miskin)
## Miskin Tidak_Miskin
## 480 965
# Model Random Forest
model_rf <- train(
status_miskin ~ keberadaan_kendaraan + konsumsi_listrik_no_outlier + daya_terpasang_pln +
pendidikan_krt + pendidikan_art_tertinggi + pekerjaan_krt +
kualitas_bangunan + akses_layanan_dasar,
data = train_data_smote,
method = "rf",
trControl = ctrl,
tuneLength = 5,
metric = "ROC"
)
# Prediksi
pred_class_rf <- predict(model_rf, newdata = test_data)
conf_rf <- confusionMatrix(pred_class_rf, test_data$status_miskin, positive = "Miskin")
# Metrik evaluasi
accuracy <- conf_rf$overall["Accuracy"]
precision <- conf_rf$byClass["Pos Pred Value"]
recall <- conf_rf$byClass["Sensitivity"]
specificity <- conf_rf$byClass["Specificity"]
f1 <- conf_rf$byClass["F1"]
# Output
cat("Akurasi :", round(accuracy, 3), "\n")
## Akurasi : 1
cat("Presisi :", round(precision, 3), "\n")
## Presisi : 1
cat("Recall :", round(recall, 3), "\n")
## Recall : 1
cat("F1 Score :", round(f1, 3), "\n")
## F1 Score : 1
cat("Spesifisitas:", round(specificity, 3), "\n\n")
## Spesifisitas: 1
var_imp <- varImp(model_rf)
var_imp
## rf variable importance
##
## Overall
## kualitas_bangunan 100.00
## pendidikan_krt 85.66
## akses_layanan_dasar 77.51
## daya_terpasang_pln 50.02
## konsumsi_listrik_no_outlier 38.95
## keberadaan_kendaraan 25.72
## pekerjaan_krt 9.64
## pendidikan_art_tertinggi 0.00
# Pastikan target pada SMOTE juga faktor
train_data_smote$status_miskin <- as.factor(train_data_smote$status_miskin)
# Model XGBoost
model_xgb <- train(
status_miskin ~ keberadaan_kendaraan + konsumsi_listrik_no_outlier + daya_terpasang_pln +
pendidikan_krt + pendidikan_art_tertinggi + pekerjaan_krt +
kualitas_bangunan + akses_layanan_dasar,
data = train_data_smote,
method = "xgbTree",
trControl = ctrl,
metric = "ROC",
tuneGrid = expand.grid(
nrounds = 100,
max_depth = 3,
eta = 0.1,
gamma = 0,
colsample_bytree = 0.8,
min_child_weight = 1,
subsample = 0.8
)
)
# Prediksi probabilitas & kelas
pred_prob_xgb <- predict(model_xgb, newdata = test_data, type = "prob")[, "Miskin"]
pred_class_xgb <- predict(model_xgb, newdata = test_data)
# Confusion matrix
conf_xgb <- confusionMatrix(pred_class_xgb, test_data$status_miskin, positive = "Miskin")
conf_xgb$table
## Reference
## Prediction Miskin Tidak_Miskin
## Miskin 30 0
## Tidak_Miskin 0 241
# Hitung metrik
TP <- conf_xgb$table["Miskin", "Miskin"]
FP <- conf_xgb$table["Miskin", "Tidak_Miskin"]
FN <- conf_xgb$table["Tidak_Miskin", "Miskin"]
TN <- conf_xgb$table["Tidak_Miskin", "Tidak_Miskin"]
accuracy <- (TP + TN) / (TP + TN + FP + FN)
precision <- TP / (TP + FP)
recall <- TP / (TP + FN)
f1_score <- 2 * precision * recall / (precision + recall)
specificity <- TN / (TN + FP)
# Output
cat("Akurasi :", round(accuracy, 4), "\n")
## Akurasi : 1
cat("Presisi :", round(precision, 4), "\n")
## Presisi : 1
cat("Recall :", round(recall, 4), "\n")
## Recall : 1
cat("F1 Score :", round(f1_score, 4), "\n")
## F1 Score : 1
var_imp1 <- varImp(model_xgb)
var_imp1
## xgbTree variable importance
##
## Overall
## kualitas_bangunan 100.00000
## pendidikan_krt 28.75217
## akses_layanan_dasar 27.12496
## daya_terpasang_pln 4.39849
## konsumsi_listrik_no_outlier 0.81043
## keberadaan_kendaraan 0.08468
## pekerjaan_krt 0.02736
## pendidikan_art_tertinggi 0.00000