Latihan Praktikum 10 RegSpas

Library

library(spData)
## Warning: package 'spData' was built under R version 4.5.3
## To access larger datasets in this package, install the spDataLarge
## package with: `install.packages('spDataLarge',
## repos='https://nowosad.github.io/drat/', type='source')`
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.4, PROJ 9.7.0; sf_use_s2() is TRUE
library(terra)
## terra 1.8.93
library(tmap)
## Warning: package 'tmap' 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
library(dismo)
## Warning: package 'dismo' was built under R version 4.5.3
## Loading required package: raster
## Loading required package: sp
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:raster':
## 
##     intersect, select, union
## The following objects are masked from 'package:terra':
## 
##     intersect, union
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(spatstat.data)
## Warning: package 'spatstat.data' was built under R version 4.5.3
library(sp)
library(maptiles)
## Warning: package 'maptiles' was built under R version 4.5.3
library(gstat)
## Warning: package 'gstat' was built under R version 4.5.3
library(dismo)
library(mapview)
## Warning: package 'mapview' was built under R version 4.5.3
library(automap)
## Warning: package 'automap' was built under R version 4.5.3
library(ggplot2)
library(rlang)

Data Diameter Pohon di Georgia, Amerika Serikat

data(longleaf)
longleaf_df <- data.frame(
  x    = longleaf$x,
  y    = longleaf$y,
  vble = longleaf$marks      
)
longleaf_sf <- st_as_sf(longleaf_df, coords = c("x", "y"), crs = 32617)
longleaf_sf
## Simple feature collection with 584 features and 1 field
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 0 ymin: 0 xmax: 200 ymax: 200
## Projected CRS: WGS 84 / UTM zone 17N
## First 10 features:
##    vble           geometry
## 1  32.9    POINT (200 8.8)
## 2  53.5   POINT (199.3 10)
## 3  68.0 POINT (193.6 22.4)
## 4  17.7 POINT (167.7 35.6)
## 5  36.9 POINT (183.9 45.4)
## 6  51.6 POINT (182.5 47.2)
## 7  66.4 POINT (166.1 48.8)
## 8  17.7 POINT (160.7 42.1)
## 9  21.9   POINT (162.9 29)
## 10 25.7 POINT (166.4 33.6)

Peta Batas Administratif

map_local <- st_as_sf(st_as_sfc(st_bbox(c(xmin=0, ymin=0, xmax=200, ymax=200))))
st_crs(map_local) <- 32617

tmap_mode("plot")
## ℹ tmap modes "plot" - "view"
## ℹ toggle with `tmap::ttm()`
tm_shape(map_local) + tm_polygons(alpha = 0.3) +
  tm_shape(longleaf_sf) +
  tm_dots("vble", palette = "viridis")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_polygons()`: use `fill_alpha` instead of `alpha`.

grid <- rast(map_local, nrows = 100, ncols = 100)
xy   <- xyFromCell(grid, 1:ncell(grid))
coop <- st_as_sf(as.data.frame(xy), coords = c("x","y"), crs = 32617)
qtm(coop)

Metode Deterministik

Closest Observation

v <- voronoi(x = vect(longleaf_sf), bnd = map_local)
plot(v)
points(vect(longleaf_sf), cex = 0.5)

v <- st_as_sf(v)
tm_shape(v) + tm_fill(col = "vble", palette = "viridis", alpha = 0.6)
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the map variable `fill` namely 'palette' (rename to 'values') to fill.scale =
## tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: use 'fill' for the fill color of polygons/symbols
## (instead of 'col'), and 'col' for the outlines (instead of 'border.col').
## [v3->v4] `tm_polygons()`: use `fill_alpha` instead of `alpha`.

resp <- st_intersection(v, coop)
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
resp$pred <- resp$vble
pred <- rasterize(resp, grid, field = "pred", fun = "mean")
c1<-tm_shape(pred) + tm_raster(alpha = 0.6, palette = "viridis") + tm_title("Closest Observation")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_raster()`: migrate the argument(s) related to the scale of the
## map variable `col` namely 'palette' (rename to 'values') to col.scale =
## tm_scale(<HERE>).
## [v3->v4] `tm_raster()`: use `col_alpha` instead of `alpha`.
c1

Inverse Distant Weight

res <- gstat(formula = vble ~ 1, locations = longleaf_sf, nmax = nrow(longleaf_sf), set = list(idp = 1))
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")
c2<-tm_shape(pred) + tm_raster(alpha = 0.6, palette = "viridis") + tm_title("IDW")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_raster()`: migrate the argument(s) related to the scale of the
## map variable `col` namely 'palette' (rename to 'values') to col.scale =
## tm_scale(<HERE>).
## [v3->v4] `tm_raster()`: use `col_alpha` instead of `alpha`.
c2

Nearest Neighbors

res <- gstat(formula = vble ~ 1, locations = longleaf_sf, nmax = 6, 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") + tm_title("KNN")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_raster()`: migrate the argument(s) related to the scale of the
## map variable `col` namely 'palette' (rename to 'values') to col.scale =
## tm_scale(<HERE>).
## [v3->v4] `tm_raster()`: use `col_alpha` instead of `alpha`.
c3

Pendekatan Ensemble

Closest Observation

v <- voronoi(x = vect(longleaf_sf), bnd = vect(map_local))
v <- st_as_sf(v)

idx <- st_intersects(coop, v)
p1  <- vapply(idx,
              function(i) if (length(i) == 0) NA_real_ else v$vble[i[1]],
              numeric(1))

IDW

gs<-gstat(formula=vble~1,locations= longleaf_sf,nmax= nrow(longleaf_sf),
set= list(idp=1))
p2<-predict(gs,coop)$var1.pred
## [inverse distance weighted interpolation]

K-Nearest Neighbors

nn<-gstat(formula=vble~1,locations= longleaf_sf,nmax= 6,
set= list(idp=0))
p3<-predict(nn,coop)$var1.pred
## [inverse distance weighted interpolation]

Ensemble

weights<-c(1/3,1/3,1/3)
p4<-p1*weights[1]+p2*weights[2]+p3*weights[3]
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 = 32617)

pred4 <- rasterize(vect(resp), grid, field = "pred", fun = "mean")

c4 <- tm_shape(pred4) + tm_raster(alpha = 0.6, palette = "viridis") +
  tm_title("Ensemble")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_raster()`: migrate the argument(s) related to the scale of the
## map variable `col` namely 'palette' (rename to 'values') to col.scale =
## tm_scale(<HERE>).
## [v3->v4] `tm_raster()`: use `col_alpha` instead of `alpha`.
c4

tmap_arrange(c1, c2, c3, c4, ncol = 2)

Metode Stokastik (Kriging)

mapview(longleaf_sf, zcol = "vble", map.types = "CartoDB.Voyager")
mapview(coop, map.types = "CartoDB.Voyager")
## Warning in cbind(`Feature ID` = fid, mat): number of rows of result is not a
## multiple of vector length (arg 1)
vc <- variogram(log(vble) ~ 1, longleaf_sf, cloud = TRUE)
plot(vc)

v <- variogram(log(vble) ~ 1, data = longleaf_sf)
plot(v)

vgm()
##    short                                      long
## 1    Nug                              Nug (nugget)
## 2    Exp                         Exp (exponential)
## 3    Sph                           Sph (spherical)
## 4    Gau                            Gau (gaussian)
## 5    Exc        Exclass (Exponential class/stable)
## 6    Mat                              Mat (Matern)
## 7    Ste Mat (Matern, M. Stein's parameterization)
## 8    Cir                            Cir (circular)
## 9    Lin                              Lin (linear)
## 10   Bes                              Bes (bessel)
## 11   Pen                      Pen (pentaspherical)
## 12   Per                            Per (periodic)
## 13   Wav                                Wav (wave)
## 14   Hol                                Hol (hole)
## 15   Log                         Log (logarithmic)
## 16   Pow                               Pow (power)
## 17   Spl                              Spl (spline)
## 18   Leg                            Leg (Legendre)
## 19   Err                   Err (Measurement error)
## 20   Int                           Int (Intercept)
show.vgms(par.strip.text = list(cex = 0.75))

vinitial <- vgm(psill = 0.76, model = "Sph", range = 30, nugget = 0.2)
plot(v, vinitial, cutoff = 100, cex = 1.5)

fv<-fit.variogram(object=v,model= vgm(psill= 0.76,model= "Sph",range= 30,nugget= 0.2))
fv
##   model      psill    range
## 1   Nug 0.03703298  0.00000
## 2   Sph 0.90397406 28.24346
plot(v,fv, cex= 1.5)

afvg <- autofitVariogram(log(vble) ~ 1, longleaf_sf)
plot(afvg)

k <- gstat(formula = log(vble) ~ 1, data = longleaf_sf, model = fv)
kpred <- predict(k, coop)
## [using ordinary kriging]
ggplot() + geom_sf(data = kpred, aes(color = var1.pred)) +
  geom_sf(data = longleaf_sf) +
  scale_color_viridis(name = "log(vble)") + theme_bw()

ggplot() + geom_sf(data = kpred, aes(color = var1.var)) +
  geom_sf(data = longleaf_sf) +
  scale_color_viridis(name = "variance") + theme_bw()

Evaluasi Model

Cross Validation

set.seed(048)
RMSE <- function(observed, predicted) {
  sqrt(mean((observed - predicted)^2))
}
kf <- kfold(nrow(longleaf_sf), k = 5)
rmse1 <- rep(NA, 5) 
rmse2 <- rep(NA, 5) 
rmse3 <- rep(NA, 5) 
rmse4 <- rep(NA, 5) 
rmse5 <- rep(NA, 5) 
for(k in 1:5){

test<-longleaf_sf[kf== k,]
train<-longleaf_sf[kf !=k,]

v   <- voronoi(x = vect(train), bnd = vect(map_local))
v   <- st_as_sf(v)
idx <- st_intersects(test, v)
p1  <- vapply(idx,
              function(i) if (length(i) == 0) NA_real_ else v$vble[i[1]],
              numeric(1))
rmse1[k] <- RMSE(test$vble, p1)

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)

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)

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)

afvg_k <- tryCatch(
    autofitVariogram(log(vble) ~ 1, train, cutoff = 100),
    error = function(e) NULL
  )
  
  if (!is.null(afvg_k)) {
    k_k    <- gstat(formula = log(vble) ~ 1, data = train,
                    model = afvg_k$var_model)
    p5_log <- predict(k_k, test)$var1.pred
    p5     <- exp(p5_log)                    
    rmse5[k] <- RMSE(test$vble, p5)
  } else {
    p5 <- rep(NA_real_, nrow(test))
    rmse5[k] <- NA
  }
}
## [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]

Tabel RMSE

data.frame(closest.obs= rmse1,IDW= rmse2,
nearest.neighbors= rmse3,ensemble= rmse4, kriging= rmse5)
##   closest.obs      IDW nearest.neighbors ensemble  kriging
## 1    14.05815 16.94283          12.61120 12.78885 12.64418
## 2    12.20609 14.88017          11.22873 10.82253 12.15022
## 3    14.42222 14.17224          10.19146 11.00566 12.14936
## 4    16.89717 17.28433          15.10307 14.78798 14.87530
## 5    12.14880 15.32086          11.04565 10.94442 11.60855

Tabel Rata-Rata RMSE

data.frame(
  closest.obs       = mean(rmse1, na.rm = TRUE),
  IDW               = mean(rmse2, na.rm = TRUE),
  nearest.neigh     = mean(rmse3, na.rm = TRUE),
  ensemble          = mean(rmse4, na.rm = TRUE),
  kriging           = mean(rmse5, na.rm = TRUE)
)
##   closest.obs      IDW nearest.neigh ensemble  kriging
## 1    13.94648 15.72009      12.03602 12.06989 12.68552