Siapkan library dan data
library(sp)
## Warning: package 'sp' was built under R version 4.5.3
library(sf)
## Warning: package 'sf' was built under R version 4.5.3
## Linking to GEOS 3.14.1, GDAL 3.12.1, PROJ 9.7.1; sf_use_s2() is TRUE
library(gstat)
## Warning: package 'gstat' was built under R version 4.5.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.2
##
## 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(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.5.3
library(viridis)
## Warning: package 'viridis' was built under R version 4.5.3
## Loading required package: viridisLite
## Warning: package 'viridisLite' was built under R version 4.5.2
library(dismo)
## Warning: package 'dismo' was built under R version 4.5.3
## Loading required package: raster
## Warning: package 'raster' was built under R version 4.5.3
##
## Attaching package: 'raster'
## The following object is masked from 'package:dplyr':
##
## select
data(meuse)
data(meuse.grid)
df <- meuse
grid <- meuse.grid
head(grid)
str(df)
## 'data.frame': 155 obs. of 14 variables:
## $ x : num 181072 181025 181165 181298 181307 ...
## $ y : num 333611 333558 333537 333484 333330 ...
## $ cadmium: num 11.7 8.6 6.5 2.6 2.8 3 3.2 2.8 2.4 1.6 ...
## $ copper : num 85 81 68 81 48 61 31 29 37 24 ...
## $ lead : num 299 277 199 116 117 137 132 150 133 80 ...
## $ zinc : num 1022 1141 640 257 269 ...
## $ elev : num 7.91 6.98 7.8 7.66 7.48 ...
## $ dist : num 0.00136 0.01222 0.10303 0.19009 0.27709 ...
## $ om : num 13.6 14 13 8 8.7 7.8 9.2 9.5 10.6 6.3 ...
## $ ffreq : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
## $ soil : Factor w/ 3 levels "1","2","3": 1 1 1 2 2 2 2 1 1 2 ...
## $ lime : Factor w/ 2 levels "0","1": 2 2 2 1 1 1 1 1 1 1 ...
## $ landuse: Factor w/ 15 levels "Aa","Ab","Ag",..: 4 4 4 11 4 11 4 2 2 15 ...
## $ dist.m : num 50 30 150 270 380 470 240 120 240 420 ...
Data Prep
df <- sf::st_as_sf(df, coords = c("x", "y"), crs = 28992, remove = FALSE)
grid <- sf::st_as_sf(grid, coords = c("x", "y"), crs = 28992, remove = FALSE)
sf::st_geometry(df)
## Geometry set for 155 features
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 178605 ymin: 329714 xmax: 181390 ymax: 333611
## Projected CRS: Amersfoort / RD New
## First 5 geometries:
## POINT (181072 333611)
## POINT (181025 333558)
## POINT (181165 333537)
## POINT (181298 333484)
## POINT (181307 333330)
sf::st_geometry(grid)
## Geometry set for 3103 features
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 178460 ymin: 329620 xmax: 181540 ymax: 333740
## Projected CRS: Amersfoort / RD New
## First 5 geometries:
## POINT (181180 333740)
## POINT (181140 333700)
## POINT (181180 333700)
## POINT (181220 333700)
## POINT (181100 333660)
AED
ggplot(df) +
geom_sf(aes(color = zinc), size = 2.5) +
scale_color_viridis_c() +
labs(
title = "Persebaran Konsentrasi Zinc",
color = "Zinc"
) +
theme_minimal()

ggplot(grid) +
geom_sf(color = "blue", size = 0.5) +
labs(
title = "Lokasi Grid Prediksi"
) +
theme_minimal()

Metode interpolasi
RMSE <- function(observed, predicted) {sqrt(mean((observed - predicted)^2))}
set.seed(123)
k <- 4
kf <- kfold(nrow(df), k = k)
rmse1 <- rep(NA, k)
rmse2 <- rep(NA, k)
rmse3 <- rep(NA, k)
rmse4 <- rep(NA, k)
for (i in 1:k) {
test <- df[kf == i, ]
train <- df[kf != i, ]
# 1. Closest Observation
nearest <- st_nearest_feature(test, train)
p1 <- train$zinc[nearest]
rmse1[i] <- RMSE(test$zinc, p1)
# 2. INVERSE DISTANCE WEIGHTING (IDW)
idw_model <- gstat(
formula = zinc ~ 1,
locations = train,
nmax = nrow(train),
set = list(idp = 1)
)
p2 <- predict(idw_model, test)$var1.pred
rmse2[i] <- RMSE(test$zinc, p2)
# 3. NEAREST NEIGHBORS (NN)
nn_model <- gstat(
formula = zinc ~ 1,
locations = train,
nmax = 5,
set = list(idp = 0)
)
p3 <- predict(nn_model, test)$var1.pred
rmse3[i] <- RMSE(test$zinc, p3)
# 4. ENSEMBLE
p4 <- (p1 + p2 + p3) / 3
rmse4[i] <- RMSE(test$zinc, p4)
}
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
## [inverse distance weighted interpolation]
Evaluasi RMSE
hasil_cv <- data.frame(
Fold = 1:k,
Closest_Observation = rmse1,
IDW = rmse2,
Nearest_Neighbors = rmse3,
Ensemble = rmse4
)
print(hasil_cv)
## Fold Closest_Observation IDW Nearest_Neighbors Ensemble
## 1 1 393.7434 282.7544 232.2025 248.7509
## 2 2 364.5879 316.9761 290.8121 274.1471
## 3 3 271.5254 417.0272 333.2966 317.7759
## 4 4 287.9924 304.7345 280.6150 266.7027
hasil_akhir <- data.frame(
Metode = c(
"Closest Observation",
"IDW",
"Nearest Neighbors",
"Ensemble"
),
Mean_RMSE = c(
mean(rmse1),
mean(rmse2),
mean(rmse3),
mean(rmse4)
)
)
hasil_akhir <- hasil_akhir %>%
arrange(Mean_RMSE)
print(hasil_akhir)
## Metode Mean_RMSE
## 1 Ensemble 276.8441
## 2 Nearest Neighbors 284.2316
## 3 Closest Observation 329.4623
## 4 IDW 330.3730
Interpolasi
# A. CLOSEST OBSERVATION
nearest_full <- st_nearest_feature(grid, df)
grid$pred_closest <- df$zinc[nearest_full]
# B. IDW
idw_full <- gstat(formula = zinc ~ 1, locations = df, nmax = nrow(df), set = list(idp = 1))
grid$pred_idw <- predict(idw_full, grid)$var1.pred
## [inverse distance weighted interpolation]
# C. NEAREST NEIGHBORS
nn_full <- gstat(formula = zinc ~ 1, locations = df,nmax = 5, set = list(idp = 0))
grid$pred_nn <- predict(nn_full, grid)$var1.pred
## [inverse distance weighted interpolation]
# D. ENSEMBLE
grid$pred_ensemble <- (grid$pred_closest +grid$pred_idw +grid$pred_nn) / 3
Visualisasi
plot_interpolasi <- function(data, variabel, judul) {
ggplot() +
geom_sf(
data = data,
aes(color = .data[[variabel]]),
size = 1
) +
geom_sf(
data = df,
color = "black",
size = 0.5
) +
scale_color_viridis_c() +
labs(
title = judul,
color = "Prediksi Zinc"
) +
theme_minimal()
}
p1 <- plot_interpolasi(
grid,
"pred_closest",
"Closest Observation"
)
p2 <- plot_interpolasi(
grid,
"pred_idw",
"Inverse Distance Weighting"
)
p3 <- plot_interpolasi(
grid,
"pred_nn",
"Nearest Neighbors"
)
p4 <- plot_interpolasi(
grid,
"pred_ensemble",
"Ensemble"
)
print(p1)

print(p2)

print(p3)

print(p4)
