Tugas Praktikum Regspas 9
Persiapan Data
Library
library(sp) # data 'meuse'
library(sf) # objek spasial (sf)
library(terra) # raster & voronoi
library(gstat) # IDW, NN, variogram, kriging
library(dismo) # kfold
library(automap) # autofit variogram
library(dplyr)
library(tidyr)
library(ggplot2)
library(viridis)
library(tmap)
library(patchwork) # menyusun beberapa peta# Memuat data meuse
data(meuse)
data(meuse.riv)
# Konversi ke sf (koordinat x,y; CRS RD New = 28992)
d <- st_as_sf(meuse, coords = c("x", "y"), crs = 28992)
# Peubah yang diinterpolasi
d$vble <- d$zinc
# Convex hull dari titik pengamatan
map <- st_sf(geometry = st_convex_hull(st_union(d)))
# Konversi data sungai Meuse
riv_sf <- st_sf(geometry = st_sfc(st_linestring(meuse.riv), crs = 28992))
summary(d$zinc)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 113.0 198.0 326.0 469.7 674.5 1839.0
library(sf)
data(meuse.grid) # reset ke data.frame asli
meuse.grid <- st_as_sf(meuse.grid, coords = c("x", "y"), crs = 28992)# Fungsi bantu: titik prediksi -> raster -> peta ggplot
to_rast <- function(sf_obj, col) {
rasterize(vect(sf_obj), grid, field = col, fun = "mean")
}
peta_rast <- function(r, judul, nama = "Zinc", lim = NULL) {
df <- as.data.frame(r, xy = TRUE); names(df)[3] <- "val"
ggplot(df, aes(x, y, fill = val)) + geom_raster() + coord_equal() +
scale_fill_viridis(name = nama, limits = lim) +
theme_bw() + ggtitle(judul) +
theme(axis.title = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank())
}
lim_zinc <- range(d$zinc) # skala warna sama untuk semua petaPeta Data Zinc
bb <- st_bbox(d) # kotak pembatas titik data
ggplot() +
geom_sf(data = map, fill = "grey95", alpha = 0.5) +
geom_sf(data = riv_sf, colour = "#9fc5e8", linewidth = 1) +
geom_sf(data = d, aes(colour = vble), size = 2) +
coord_sf(xlim = c(bb["xmin"], bb["xmax"]),
ylim = c(bb["ymin"], bb["ymax"]),
expand = TRUE) +
scale_colour_viridis(name = "Zinc (ppm)") +
theme_bw() + ggtitle("Sebaran Kadar Zinc di Data meuse")Metode Deterministik
Closest Observation (voronoi)
# Membuat diagram Voronoi dari lokasi properti
v <- voronoi(x = vect(d), bnd = map)
plot(v)
# Menampilkan diagram Voronoi dengan harga properti
points(vect(d), cex = 0.5)resp <- st_intersection(v, coop)
resp$pred <- resp$vble
pred <- rasterize(resp, grid, field = "pred", fun = "mean")
c1<-tm_shape(pred) + tm_raster(alpha = 0.6, palette = "viridis")
# Tampilkan peta
c1Nearest Neighbors
res <- gstat(formula = vble ~ 1, locations = d, nmax = 5, set = list(idp = 0))
resp <- predict(res, coop)## [inverse distance weighted interpolation]
resp$x <- st_coordinates(resp)[,1]
resp$y <- st_coordinates(resp)[,2]
resp$pred <- resp$var1.pred
pred <- rasterize(resp, grid, field = "pred", fun = "mean")
c3<-tm_shape(pred) + tm_raster(alpha = 0.6, palette = "viridis")
c3Invers Distance Weight
library(gstat)
# Menerapkan IDW menggunakan semua lokasi properti
res <- gstat(formula = vble ~ 1, locations = d, nmax = nrow(d), set = list(idp = 1))
# Mendapatkan prediksi harga untuk lokasi yang belum teramati
resp <- predict(res, coop)## [inverse distance weighted interpolation]
resp$x <- st_coordinates(resp)[,1]
resp$y <- st_coordinates(resp)[,2]
resp$pred <- resp$var1.pred
# Membuat peta prediksi harga dengan metode IDW
pred <- rasterize(resp, grid, field = "pred", fun = "mean")
c2<-tm_shape(pred) + tm_raster(alpha = 0.6, palette = "viridis")
# Tampilkan peta
c2Pendekatan ensambel
#Closestobservation(Voronoi)
v<-voronoi(x=vect(d),bnd= map)
v<-st_as_sf(v)
p1<-st_intersection(v,coop)$vble
#IDW
gs<-gstat(formula=vble~1,locations= d,nmax= nrow(d),
set= list(idp=1))
p2<-predict(gs,coop)$var1.pred## [inverse distance weighted interpolation]
#Nearestneighbors
nn<-gstat(formula=vble~1,locations= d,nmax= 5,
set= list(idp=0))
p3<-predict(nn,coop)$var1.pred## [inverse distance weighted interpolation]
resp<-data.frame(x=st_coordinates(coop)[,1], y=st_coordinates(coop)[,2], pred=p4)
resp<-st_as_sf(resp,coords= c("x","y"),crs= st_crs(map))
pred<-rasterize(resp,grid, field= "pred",fun= "mean")
c4<-tm_shape(pred)+tm_raster(alpha= 0.6,palette="viridis")
c4Metode Stikastik
kringing
Eksplorasi Variogram
# Variogram Cloud
# Variogram dengan cloud plot
vc <- variogram(log(zinc) ~ 1, d, cloud = TRUE)
plot(vc)Pemodelan Variogram
# Menentukan model variogram awal dengan parameter psill, model, range, dan nugget
vinitial <- vgm(psill = 0.5, model = "Sph", range = 900, nugget = 0.1)
# Memvisualisasikan variogram dengan model awal (vinitial) dan batas cutoff 1000
plot(v, vinitial, cutoff = 1000, cex = 1.5)# Menyesuaikan variogram dengan model "Sph" menggunakan data v dan parameter
fv<-fit.variogram(object=v,model= vgm(psill= 0.5,model= "Sph",range= 900,nugget= 0.1))
fv## model psill range
## 1 Nug 0.05066017 0.0000
## 2 Sph 0.59060556 897.0044
Autofit Variogram
library(automap)
# Autofit variogram untuk data log-zinc
afvg <- autofitVariogram(log(zinc) ~ 1, d)
# Plot hasil
plot(afvg)Interpolasi Kringing
library(ggplot2)
library(viridis)
# Membuat objek gstat dengan model variogram hasil fitting (fv) untuk data zinc
k <- gstat(formula = log(zinc) ~ 1, data = d, model = fv)
# Melakukan prediksi variabel pada grid menggunakan model gstat yang sudah dibuat
kpred <- predict(k, meuse.grid)## [using ordinary kriging]
Visualisasi
k <- gstat(formula = log(zinc) ~ 1, data = d, model = fv)
kpred <- predict(k, coop, debug.level = 0)
# Transformasi balik ke skala zinc agar sebanding dengan metode lain
kpred$pred <- exp(kpred$var1.pred + kpred$var1.var / 2)
ggplot() +
geom_sf(data = kpred, aes(colour = var1.pred)) +
geom_sf(data = d, shape = 4) +
scale_colour_viridis(name = "Prediksi\nlog(zinc)") +
theme_bw() + ggtitle("Peta Prediksi Kriging (skala log)")# Peta Varians
ggplot() +
geom_sf(data = kpred, aes(colour = var1.var)) +
geom_sf(data = d, shape = 4) +
scale_colour_viridis(name = "Varians") +
theme_bw() + ggtitle("Peta Varians Kriging")pred_kriging <- to_rast(kpred, "pred")
c5 <- peta_rast(pred_kriging, "Kriging (back-transform)", lim = lim_zinc)
c5Interpretasi Peta
Pola umum sebaran zinc serupa pada semua metode: konsentrasi tinggi berada di dekat sungai Meuse dan menurun menjauhi sungai. Perbedaan utama ada pada tingkat kehalusan. Closest Observation menghasilkan peta paling kasar dengan batas tegas antar poligon Voronoi. IDW dan NN lebih halus karena memakai beberapa tetangga. NN dengan k = 5 memberi pola yang lebih “berbintik” dibanding IDW. Ensemble tampil sebagai kompromi dari ketiga metode.
Kriging memberi gradasi yang paling halus dan kontinu karena bobot tetangga ditentukan oleh struktur variogram.
Evaluasi
set.seed(123)
# Fungsi untuk menghitung RMSE
RMSE <- function(observed, predicted) {
sqrt(mean((observed - predicted)^2))
}
# Pembagian data untuk K-fold
kf <- kfold(nrow(d), k = 5)
# Vectors to store the RMSE values obtained with each method
rmse1 <- rep(NA, 5) # Closest observation
rmse2 <- rep(NA, 5) # IDW
rmse3 <- rep(NA, 5) # Nearest neighbors
rmse4 <- rep(NA, 5) # Ensemble
rmse5 <- rep(NA, 5)
for(k in 1:5){
#Splitdataintest andtrain
test<-d[kf== k,]
train<-d[kf !=k,]
#Closestobservation
v<-voronoi(x=vect(train), bnd= map)
v<-st_as_sf(v)
p1<-st_intersection(v,test)$vble
rmse1[k] <-RMSE(test$vble,p1)
#IDW
gs<-gstat(formula=vble ~1,locations= train,
nmax=nrow(train), set= list(idp=1))
p2 <-predict(gs,test)$var1.pred
rmse2[k] <-RMSE(test$vble,p2)
#Nearestneighbors
nn<-gstat(formula=vble~1,locations= train,
nmax=5,set= list(idp=0))
p3 <-predict(nn,test)$var1.pred
rmse3[k] <-RMSE(test$vble,p3)
#Ensemble(weightsareinverseRMSEsolowerRMSEhigherweight)
w<-1/c(rmse1[k],rmse2[k],rmse3[k])
weights<-w/sum(w)
p4<-p1*weights[1]+p2*weights[2]+p3*weights[3]
rmse4[k] <-RMSE(test$vble,p4)
#Kringing
train_sp <- as(train, "Spatial")
afvg_train <- autofitVariogram(log(zinc) ~ 1, train_sp)
k_train <- gstat(formula = log(zinc) ~ 1, data = train,
model = afvg_train$var_model)
p5_log <- predict(k_train, test)$var1.pred
p5_back <- exp(p5_log)
rmse5[k] <- RMSE(test$vble, p5_back)
}## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [using ordinary kriging]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [using ordinary kriging]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [using ordinary kriging]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [using ordinary kriging]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [using ordinary kriging]
# Hasil RMSE
data.frame(closest.obs= rmse1,IDW= rmse2,
nearest.neigh= rmse3,ensemble= rmse4, Kringing=rmse5)## closest.obs IDW nearest.neigh ensemble Kringing
## 1 309.9009 282.3744 265.3339 250.9364 190.2728
## 2 385.8027 277.6231 275.7933 260.7226 221.7091
## 3 323.5046 438.7651 364.2145 337.4435 325.1786
## 4 237.6379 323.2493 255.5252 242.7105 207.8869
## 5 299.4034 329.9387 294.7488 281.7473 249.2541
# Rata rata RMSE
data.frame(
closest.obs = mean(rmse1),
IDW = mean(rmse2),
nearest.neigh = mean(rmse3),
kringing = mean(rmse5),
ensemble = mean(rmse4))## closest.obs IDW nearest.neigh kringing ensemble
## 1 311.2499 330.3901 291.1231 238.8603 274.7121
Kesimpulan
Berdasarkan RMSE rata-rata 5-fold cross-validation, metode terbaik adalah Kringing (RMSE = 238.86), diikuti Ensemble (RMSE = 274.71) dan Nearest Neighbors (k-NN) (RMSE = 291.12) serta Closest Observation (RMSE = 311.25). Metode dengan error terbesar adalah IDW (RMSE = 330.39).