Regresi Spasial Praktikum 9
Membuat interpolasi menggunakan data meuse, dengan menggunakan seluruh metode interpolasi, yaitu Closest Observation, NN, IDW, Ensembel, dan Kriging. Setelah itu bandingkan RMSE dengan menggunakan Cross Validation
1. Data
## x y cadmium copper lead zinc elev dist om ffreq soil lime
## 1 181072 333611 11.7 85 299 1022 7.909 0.00135803 13.6 1 1 1
## 2 181025 333558 8.6 81 277 1141 6.983 0.01222430 14.0 1 1 1
## 3 181165 333537 6.5 68 199 640 7.800 0.10302900 13.0 1 1 1
## 4 181298 333484 2.6 81 116 257 7.655 0.19009400 8.0 1 2 0
## 5 181307 333330 2.8 48 117 269 7.480 0.27709000 8.7 1 2 0
## 6 181390 333260 3.0 61 137 281 7.791 0.36406700 7.8 1 2 0
## landuse dist.m
## 1 Ah 50
## 2 Ah 30
## 3 Ah 150
## 4 Ga 270
## 5 Ah 380
## 6 Ga 470
library(spData)
library(sf)
library(terra)
library(tmap)
library(viridis)
library(dismo)
library(dplyr)
library(ggplot2)CRS Rijksdriehoek (Amersfoort / RD New) = EPSG:28992
meuse_sf <- st_as_sf(meuse, coords = c("x", "y"), crs = 28992, remove = FALSE)
grid_sf <- st_as_sf(meuse.grid, coords = c("x", "y"), crs = 28992, remove = FALSE)
summary(meuse_sf$zinc)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 113.0 198.0 326.0 469.7 674.5 1839.0
Visualisasi sebaran titik
ggplot(meuse_sf) +
geom_sf(aes(color = zinc), size = 2) +
scale_color_viridis_c(option = "C") +
labs(title = "Sebaran Konsentrasi Zinc (meuse)", color = "Zinc (ppm)") +
theme_minimal()
Konsentrasi Zinc pada wilayah pengamatan menunjukkan pola persebaran
yang heterogen, dengan sebagian besar lokasi memiliki konsentrasi
relatif rendah dan beberapa lokasi menunjukkan konsentrasi tinggi.
Konsentrasi tinggi cenderung muncul pada titik-titik tertentu, sehingga
terdapat indikasi pola pengelompokan spasial.
3. Fungsi tiap metode interpolasi
Closest Observation (proximity / Voronoi)
Nearest Neighbour (rata-rata k tetangga terdekat, k = 5)
IDW (power = 2)
Ordinary Kriging
fit_variogram <- function(train) {
v <- variogram(zinc ~ 1, train)
buat_awal <- function(tipe) {
vgm(psill = var(train$zinc) * 0.8,
model = tipe,
range = max(v$dist) / 3,
nugget = var(train$zinc) * 0.2)
}
hasil <- lapply(c(Sph = "Sph", Exp = "Exp", Gau = "Gau"), function(tipe) {
fit.variogram(v, model = buat_awal(tipe))
})
sse <- sapply(hasil, function(m) attr(m, "SSErr"))
list(emp = v, model = hasil[[which.min(sse)]], sse = sse)
}
pred_krige <- function(train, test) {
vm <- fit_variogram(train)$model
k <- krige(zinc ~ 1, locations = train, newdata = test, model = vm,
debug.level = 0)
k$var1.pred
}4. Variogram
## model psill range
## 1 Nug 9486.627 0.0000
## 2 Exp 163285.480 381.7101
## Sph Exp Gau
## 2223258 1791466 3729204
Variogram Zinc menunjukkan adanya struktur ketergantungan spasial, yang ditandai dengan meningkatnya semivarian seiring bertambahnya jarak hingga mencapai kondisi relatif stabil. Hal ini mengindikasikan bahwa lokasi yang berdekatan cenderung memiliki konsentrasi Zinc yang lebih mirip dibandingkan lokasi yang berjauhan. Berdasarkan nilai SSErr terkecil, model variogram yang terpilih adalah Exp.
5. K-Fold Cross Validation
set.seed(123)
K <- 5
n <- nrow(meuse_sf)
fold <- sample(rep(1:K, length.out = n))
cv_pred <- data.frame(
obs = meuse_sf$zinc,
fold = fold,
closest = NA_real_,
nn = NA_real_,
idw = NA_real_,
kriging = NA_real_
)
for (f in 1:K) {
train <- meuse_sf[fold != f, ]
test <- meuse_sf[fold == f, ]
i <- which(fold == f)
cv_pred$closest[i] <- pred_closest(train, test)
cv_pred$nn[i] <- pred_nn(train, test)
cv_pred$idw[i] <- pred_idw(train, test)
cv_pred$kriging[i] <- pred_krige(train, test)
}6. Ensemble
cv_pred$ens_mean <- rowMeans(cv_pred[, c("idw", "nn", "kriging")])
rm_comp <- sapply(c("idw", "nn", "kriging"), function(m) rmse(cv_pred$obs, cv_pred[[m]]))
w <- (1 / rm_comp) / sum(1 / rm_comp)
print(round(w, 3))## idw nn kriging
## 0.311 0.323 0.367
Ensemble dibangun dari tiga metode, yaitu IDW, Nearest Neighbour, dan Ordinary Kriging. Dua versi dibandingkan:
rata-rata sederhana
rata-rata terbobot dengan bobot proporsional terhadap 1/RMSE tiap metode
metode dengan kesalahan lebih kecil mendapat bobot lebih besar. Bobot hasil perhitungan ditampilkan pada keluaran di atas.
7. Perbandingan RMSE
null_pred <- sapply(1:n, function(i) mean(meuse_sf$zinc[fold != fold[i]])) # model nol (rata-rata)
hasil_rmse <- data.frame(
Metode = c("Model Nol (rata-rata)", "Closest Observation", "Nearest Neighbour (k=5)",
"IDW (p=2)", "Kriging (Ordinary)",
"Ensemble (rata-rata)", "Ensemble (terbobot 1/RMSE)"),
RMSE = c(rmse(cv_pred$obs, null_pred),
rmse(cv_pred$obs, cv_pred$closest),
rmse(cv_pred$obs, cv_pred$nn),
rmse(cv_pred$obs, cv_pred$idw),
rmse(cv_pred$obs, cv_pred$kriging),
rmse(cv_pred$obs, cv_pred$ens_mean),
rmse(cv_pred$obs, cv_pred$ens_weighted))
) %>%
mutate(RMSE = round(RMSE, 2),
Peningkatan_vs_Nol = round((1 - RMSE / RMSE[1]) * 100, 1)) %>%
arrange(RMSE)
print(hasil_rmse)## Metode RMSE Peningkatan_vs_Nol
## 1 Kriging (Ordinary) 235.75 35.9
## 2 Ensemble (terbobot 1/RMSE) 250.58 31.9
## 3 Ensemble (rata-rata) 251.93 31.5
## 4 Nearest Neighbour (k=5) 267.83 27.2
## 5 IDW (p=2) 278.16 24.4
## 6 Closest Observation 351.95 4.4
## 7 Model Nol (rata-rata) 368.01 0.0
ggplot(hasil_rmse, aes(x = reorder(Metode, -RMSE), y = RMSE, fill = RMSE)) +
geom_col(show.legend = FALSE) +
geom_text(aes(label = RMSE), hjust = -0.1) +
coord_flip() +
scale_fill_viridis_c(direction = -1) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
labs(title = "Perbandingan RMSE (5-Fold Cross Validation)",
x = NULL, y = "RMSE (zinc, ppm)") +
theme_minimal()##
## Metode terbaik: Kriging (Ordinary) dengan RMSE = 235.75
r_ <- setNames(hasil_rmse$RMSE, hasil_rmse$Metode)
peningkatan <- setNames(hasil_rmse$Peningkatan_vs_Nol, hasil_rmse$Metode)Berdasarkan hasil 5-Fold Cross Validation, Kriging (Ordinary) merupakan metode interpolasi terbaik dengan RMSE sebesar 235.75 ppm, atau menurunkan kesalahan sekitar 35.9% dibandingkan model nol (RMSE 368.01 ppm). Pemodelan variogram yang memanfaatkan struktur ketergantungan spasial antar lokasi menghasilkan estimasi Zinc yang lebih akurat dibandingkan metode yang hanya bergantung pada jarak.
Closest Observation hanya memberikan sedikit perbaikan dari model nol (RMSE 351.95 ppm) karena hanya meminjam satu titik terdekat sehingga sangat sensitif terhadap variasi lokal. Nearest Neighbour (267.83 ppm) dan IDW (278.16 ppm) lebih baik karena merata-ratakan beberapa titik. Ensemble (terbobot 250.58 ppm; rata-rata 251.93 ppm) lebih baik dari NN dan IDW, namun belum melampaui Kriging karena ikut memuat metode yang lebih lemah. Selisih antara ensemble terbobot dan rata-rata sederhana sangat kecil, sehingga pembobotan tidak banyak menambah manfaat.
8. Peta hasil interpolasi
peta <- data.frame(st_drop_geometry(grid_sf)[, c("x", "y")])
peta$Closest <- pred_closest(meuse_sf, grid_sf)
peta$NN <- pred_nn(meuse_sf, grid_sf)
peta$IDW <- pred_idw(meuse_sf, grid_sf)
peta$Kriging <- pred_krige(meuse_sf, grid_sf)
peta$Ensemble <- w["idw"] * peta$IDW + w["nn"] * peta$NN + w["kriging"] * peta$Kriging
metode <- c("Closest", "NN", "IDW", "Ensemble", "Kriging")
peta_long <- do.call(rbind, lapply(metode, function(m) {
data.frame(x = peta$x, y = peta$y, Metode = m, Zinc = peta[[m]])
}))
peta_long$Metode <- factor(peta_long$Metode, levels = metode)
ggplot(peta_long, aes(x = x, y = y, fill = Zinc)) +
geom_tile() +
facet_wrap(~ Metode, ncol = 3) +
scale_fill_viridis_c(option = "C") +
coord_equal() +
labs(title = "Hasil Interpolasi Zinc (data meuse)", fill = "Zinc (ppm)") +
theme_minimal() +
theme(axis.text = element_blank(), axis.title = element_blank())Secara keseluruhan, kelima metode mampu menggambarkan pola persebaran konsentrasi Zinc pada wilayah pengamatan. Namun, terdapat perbedaan karakteristik hasil interpolasi berdasarkan pendekatan masing-masing metode. Jika dikaitkan dengan hasil 5-Fold Cross Validation sebelumnya, Kriging (Ordinary) merupakan metode terbaik dengan RMSE sebesar 235.75 ppm. Dengan demikian, meskipun secara visual beberapa metode menghasilkan pola yang relatif serupa, Ordinary Kriging memberikan tingkat kesalahan prediksi paling rendah sehingga lebih direkomendasikan untuk interpolasi konsentrasi Zinc pada data Meuse.