Variabel - Y: Harga rumah (juta rupiah). - X1: Luas rumah (m²). - X2: Jarak ke pusat kota (km).
Rumah baru yang akan diprediksi memiliki luas 85 m² dan berjarak 7,5 km dari pusat kota.
Jika package belum terpasang, jalankan
install.packages() satu kali di Console.
# install.packages(c("rpart", "rpart.plot", "randomForest", "ggplot2", "tidyr"))
library(rpart)
library(rpart.plot)
library(randomForest)
library(ggplot2)
library(tidyr)
data_rumah <- data.frame(
x1 = c(40, 55, 60, 70, 80, 90, 100),
x2 = c(14, 12, 10, 9, 8, 7, 6),
y = c(320, 360, 400, 420, 460, 510, 540)
)
data_rumah
## x1 x2 y
## 1 40 14 320
## 2 55 12 360
## 3 60 10 400
## 4 70 9 420
## 5 80 8 460
## 6 90 7 510
## 7 100 6 540
# Rumah yang akan diprediksi
rumah_baru <- data.frame(
x1 = 85,
x2 = 7.5
)
rumah_baru
## x1 x2
## 1 85 7.5
model_tree <- rpart(
y ~ x1 + x2,
data = data_rumah,
method = "anova",
control = rpart.control(
cp = 0,
minsplit = 2,
minbucket = 1,
maxdepth = 5,
xval = 0
)
)
model_tree
## n= 7
##
## node), split, n, deviance, yval
## * denotes terminal node
##
## 1) root 7 37400.000 430.0000
## 2) x1< 75 4 5900.000 375.0000
## 4) x1< 57.5 2 800.000 340.0000
## 8) x1< 47.5 1 0.000 320.0000 *
## 9) x1>=47.5 1 0.000 360.0000 *
## 5) x1>=57.5 2 200.000 410.0000
## 10) x1< 65 1 0.000 400.0000 *
## 11) x1>=65 1 0.000 420.0000 *
## 3) x1>=75 3 3266.667 503.3333
## 6) x2>=7.5 1 0.000 460.0000 *
## 7) x2< 7.5 2 450.000 525.0000
## 14) x1< 95 1 0.000 510.0000 *
## 15) x1>=95 1 0.000 540.0000 *
# Prediksi rumah baru
pred_tree <- predict(model_tree, newdata = rumah_baru)
cat(
"\nPrediksi Decision Tree:",
round(pred_tree, 2), "juta rupiah\n"
)
##
## Prediksi Decision Tree: 460 juta rupiah
rpart.plot(
model_tree,
type = 2,
extra = 101,
fallen.leaves = TRUE,
box.palette = "Blues",
shadow.col = "gray",
nn = TRUE,
main = "Decision Tree Regression Harga Rumah"
)
prediksi_semua_tree <- predict(model_tree, newdata = data_rumah)
data_grafik_tree <- data.frame(
index = seq_len(nrow(data_rumah)),
Aktual = data_rumah$y,
Prediksi = as.numeric(prediksi_semua_tree)
)
data_grafik_tree_long <- tidyr::pivot_longer(
data_grafik_tree,
cols = c(Aktual, Prediksi),
names_to = "Keterangan",
values_to = "Harga"
)
ggplot(
data_grafik_tree_long,
aes(
x = index,
y = Harga,
color = Keterangan,
group = Keterangan
)
) +
geom_line(linewidth = 1.1) +
geom_point(size = 2.5, color = "black") +
scale_color_manual(
values = c(
"Aktual" = "#FF6666",
"Prediksi" = "#00BFC4"
)
) +
scale_x_continuous(breaks = seq_len(nrow(data_rumah))) +
labs(
title = "Decision Tree Regression",
x = "Index",
y = "Harga Rumah (juta rupiah)",
color = "Keterangan"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(hjust = 0, face = "bold"),
legend.position = "right"
)
set.seed(123)
model_rf <- randomForest(
y ~ x1 + x2,
data = data_rumah,
ntree = 2,
mtry = 2,
nodesize = 1,
keep.forest = TRUE,
importance = TRUE
)
model_rf
##
## Call:
## randomForest(formula = y ~ x1 + x2, data = data_rumah, ntree = 2, mtry = 2, nodesize = 1, keep.forest = TRUE, importance = TRUE)
## Type of random forest: regression
## Number of trees: 2
## No. of variables tried at each split: 2
##
## Mean of squared residuals: 841.6667
## % Var explained: 84.25
# Prediksi rumah baru
pred_rf <- predict(model_rf, newdata = rumah_baru)
cat(
"Prediksi Random Forest:",
round(pred_rf, 2), "juta rupiah\n"
)
## Prediksi Random Forest: 465 juta rupiah
# Struktur kedua pohon
pohon_1 <- getTree(model_rf, k = 1, labelVar = TRUE)
pohon_2 <- getTree(model_rf, k = 2, labelVar = TRUE)
cat("\nStruktur Pohon 1:\n")
##
## Struktur Pohon 1:
print(pohon_1)
## left daughter right daughter split var split point status prediction
## 1 2 3 x2 8.0 -3 447.1429
## 2 4 5 x1 95.0 -3 530.0000
## 3 6 7 x1 50.0 -3 385.0000
## 4 0 0 <NA> 0.0 -1 510.0000
## 5 0 0 <NA> 0.0 -1 540.0000
## 6 0 0 <NA> 0.0 -1 320.0000
## 7 8 9 x2 9.5 -3 406.6667
## 8 0 0 <NA> 0.0 -1 420.0000
## 9 0 0 <NA> 0.0 -1 400.0000
cat("\nStruktur Pohon 2:\n")
##
## Struktur Pohon 2:
print(pohon_2)
## left daughter right daughter split var split point status prediction
## 1 2 3 x1 85.0 -3 394.2857
## 2 4 5 x1 57.5 -3 370.0000
## 3 0 0 <NA> 0.0 -1 540.0000
## 4 6 7 x2 13.0 -3 350.0000
## 5 8 9 x1 65.0 -3 410.0000
## 6 0 0 <NA> 0.0 -1 360.0000
## 7 0 0 <NA> 0.0 -1 320.0000
## 8 0 0 <NA> 0.0 -1 400.0000
## 9 0 0 <NA> 0.0 -1 420.0000
Fungsi ini menggunakan hubungan node anak kiri dan kanan dari
getTree(). Node pemisah menampilkan variabel dan titik
pemisahan; node daun menampilkan nilai prediksi. Diagram ini adalah
visualisasi struktur pohon hasil randomForest.
gambar_pohon_rf <- function(pohon, nomor_pohon) {
jumlah_node <- nrow(pohon)
cari_anak <- function(node, arah) {
kolom <- if (arah == "kiri") "left daughter" else "right daughter"
anak <- as.integer(pohon[node, kolom])
if (is.na(anak) || anak == 0) {
return(NA_integer_)
}
anak
}
hitung_daun <- function(node) {
kiri <- cari_anak(node, "kiri")
kanan <- cari_anak(node, "kanan")
if (is.na(kiri) && is.na(kanan)) return(1)
hasil <- 0
if (!is.na(kiri)) hasil <- hasil + hitung_daun(kiri)
if (!is.na(kanan)) hasil <- hasil + hitung_daun(kanan)
hasil
}
posisi <- data.frame(
node = seq_len(jumlah_node),
x = rep(NA_real_, jumlah_node),
y = rep(NA_real_, jumlah_node)
)
tempatkan <- function(node, batas_kiri, batas_kanan, level = 1) {
posisi$x[node] <<- (batas_kiri + batas_kanan) / 2
posisi$y[node] <<- -level
anak_kiri <- cari_anak(node, "kiri")
anak_kanan <- cari_anak(node, "kanan")
if (!is.na(anak_kiri) && !is.na(anak_kanan)) {
daun_kiri <- hitung_daun(anak_kiri)
daun_kanan <- hitung_daun(anak_kanan)
batas_tengah <- batas_kiri +
(batas_kanan - batas_kiri) *
daun_kiri / (daun_kiri + daun_kanan)
tempatkan(anak_kiri, batas_kiri, batas_tengah, level + 1)
tempatkan(anak_kanan, batas_tengah, batas_kanan, level + 1)
} else if (!is.na(anak_kiri)) {
tempatkan(anak_kiri, batas_kiri, batas_kanan, level + 1)
} else if (!is.na(anak_kanan)) {
tempatkan(anak_kanan, batas_kiri, batas_kanan, level + 1)
}
}
tempatkan(1, 0, hitung_daun(1))
jumlah_daun <- hitung_daun(1)
kedalaman <- max(abs(posisi$y), na.rm = TRUE)
plot(
NA,
xlim = c(-0.5, jumlah_daun + 0.5),
ylim = c(-kedalaman - 0.7, 0.7),
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = "",
main = paste("Random Forest - Pohon", nomor_pohon),
bty = "n"
)
# Garis cabang
for (i in seq_len(jumlah_node)) {
anak_kiri <- cari_anak(i, "kiri")
anak_kanan <- cari_anak(i, "kanan")
if (!is.na(anak_kiri)) {
segments(
posisi$x[i], posisi$y[i] - 0.12,
posisi$x[anak_kiri], posisi$y[anak_kiri] + 0.12
)
text(
(posisi$x[i] + posisi$x[anak_kiri]) / 2,
(posisi$y[i] + posisi$y[anak_kiri]) / 2,
labels = "<=",
cex = 0.65,
pos = 2
)
}
if (!is.na(anak_kanan)) {
segments(
posisi$x[i], posisi$y[i] - 0.12,
posisi$x[anak_kanan], posisi$y[anak_kanan] + 0.12
)
text(
(posisi$x[i] + posisi$x[anak_kanan]) / 2,
(posisi$y[i] + posisi$y[anak_kanan]) / 2,
labels = ">",
cex = 0.65,
pos = 4
)
}
}
# Kotak dan label node
for (i in seq_len(jumlah_node)) {
variabel <- as.character(pohon[i, "split var"])
is_daun <- is.na(variabel) ||
variabel == "<NA>" ||
variabel == "<leaf>"
if (is_daun) {
label <- paste0(
"Node ", i, "\nPrediksi = ",
round(pohon[i, "prediction"], 2)
)
warna <- "lightblue"
} else {
label <- paste0(
"Node ", i, "\n",
variabel, " <= ",
round(pohon[i, "split point"], 2)
)
warna <- "lightyellow"
}
rect(
posisi$x[i] - 0.38,
posisi$y[i] - 0.2,
posisi$x[i] + 0.38,
posisi$y[i] + 0.2,
col = warna,
border = "gray40"
)
text(
posisi$x[i],
posisi$y[i],
labels = label,
cex = 0.65
)
}
}
par(mfrow = c(1, 2), mar = c(1, 1, 3, 1))
gambar_pohon_rf(pohon_1, 1)
gambar_pohon_rf(pohon_2, 2)
par(mfrow = c(1, 1))
prediksi_semua_rf <- predict(model_rf, newdata = data_rumah)
data_grafik_rf <- data.frame(
index = seq_len(nrow(data_rumah)),
Aktual = data_rumah$y,
Prediksi = as.numeric(prediksi_semua_rf)
)
data_grafik_rf_long <- tidyr::pivot_longer(
data_grafik_rf,
cols = c(Aktual, Prediksi),
names_to = "Keterangan",
values_to = "Harga"
)
ggplot(
data_grafik_rf_long,
aes(
x = index,
y = Harga,
color = Keterangan,
group = Keterangan
)
) +
geom_line(linewidth = 1.1) +
geom_point(size = 2.5, color = "black") +
scale_color_manual(
values = c(
"Aktual" = "#FF6666",
"Prediksi" = "#00BFC4"
)
) +
scale_x_continuous(breaks = seq_len(nrow(data_rumah))) +
labs(
title = "Random Forest Regresi",
x = "Index",
y = "Harga Rumah (juta rupiah)",
color = "Keterangan"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(hjust = 0, face = "bold"),
legend.position = "right"
)
hasil_prediksi <- data.frame(
Metode = c("Decision Tree", "Random Forest (2 Pohon)"),
Prediksi_juta = c(
as.numeric(pred_tree),
as.numeric(pred_rf)
)
)
cat("\nTabel prediksi rumah baru:\n")
##
## Tabel prediksi rumah baru:
print(hasil_prediksi)
## Metode Prediksi_juta
## 1 Decision Tree 460
## 2 Random Forest (2 Pohon) 465
data_grafik <- data.frame(
Index = seq_len(nrow(data_rumah)),
Aktual = data_rumah$y,
Decision_Tree = as.numeric(prediksi_semua_tree),
Random_Forest = as.numeric(prediksi_semua_rf)
)
data_grafik_long <- tidyr::pivot_longer(
data_grafik,
cols = c(Aktual, Decision_Tree, Random_Forest),
names_to = "Metode",
values_to = "Harga"
)
data_grafik_long$Metode <- factor(
data_grafik_long$Metode,
levels = c("Aktual", "Decision_Tree", "Random_Forest"),
labels = c("Aktual", "Decision Tree", "Random Forest")
)
ggplot(
data_grafik_long,
aes(
x = Index,
y = Harga,
color = Metode,
group = Metode
)
) +
# Garis prediksi digambar terlebih dahulu
geom_line(
data = subset(data_grafik_long, Metode == "Decision Tree"),
linewidth = 1.1
) +
geom_line(
data = subset(data_grafik_long, Metode == "Random Forest"),
linewidth = 1.1
) +
# Garis aktual digambar terakhir agar terlihat
geom_line(
data = subset(data_grafik_long, Metode == "Aktual"),
linewidth = 1.3
) +
geom_point(size = 2.5) +
scale_color_manual(
values = c(
"Aktual" = "#FF6666",
"Decision Tree" = "#00A6B2",
"Random Forest" = "#3366CC"
)
) +
scale_x_continuous(breaks = seq_len(nrow(data_rumah))) +
labs(
title = "Perbandingan Harga Rumah Aktual dan Prediksi",
x = "Indeks Observasi",
y = "Harga Rumah (juta rupiah)",
color = "Keterangan"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "right"
)
data_prediksi_baru <- data.frame(
Metode = c("Decision Tree", "Random Forest"),
Harga = c(
as.numeric(pred_tree),
as.numeric(pred_rf)
)
)
ggplot(
data_prediksi_baru,
aes(x = Metode, y = Harga, fill = Metode)
) +
geom_col(width = 0.55) +
geom_text(
aes(label = round(Harga, 2)),
vjust = -0.5,
size = 4
) +
labs(
title = "Prediksi Harga Rumah Baru",
subtitle = "Luas = 85 m² dan Jarak ke Pusat Kota = 7,5 km",
x = "Metode",
y = "Prediksi Harga (juta rupiah)"
) +
scale_fill_manual(
values = c(
"Decision Tree" = "#00A6B2",
"Random Forest" = "#3366CC"
)
) +
expand_limits(y = max(data_prediksi_baru$Harga) * 1.1) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)
Hasil prediksi rumah baru dari Decision Tree dan Random Forest ditampilkan pada tabel di Bagian 5 dan diagram batang di Bagian 7. Grafik pada Bagian 3.2 dan 4.3 membandingkan harga aktual dengan prediksi masing-masing model, sedangkan grafik Bagian 6 membandingkan ketiganya secara bersamaan.