system.file("shape/nc.shp", package="sf")sf::st_read (or sf::read_sf)library(sf)
## Linking to GEOS 3.7.0, GDAL 2.4.0, PROJ 5.2.0
nc = read_sf(system.file("shape/nc.shp", package="sf"))
plot(nc)
## Warning: plotting the first 10 out of 14 attributes; use max.plot = 14 to
## plot all
plot(nc[,2])
# or, e.g.
# library(tidyverse)
# nc %>% select(2) %>% plot
plot(nc[,2], pal = viridis::viridis) # note that this is a function, not a set of colors
plot(nc[,2], nbreaks = 5, pal = viridis::viridis) # note that we don't get exactly 5, because of "pretty" style
plot(nc[1:20,2])
plot(nc[1:20,2], axes = TRUE)
st_crs(nc)
## Coordinate Reference System:
## EPSG: 4267
## proj4string: "+proj=longlat +datum=NAD27 +no_defs"
nc dataset, compute the area of the polygons with st_areaAREA field in the dataset; is there a discrepancy?a = st_area(nc)
plot(a, nc$AREA)
POINT (-81.49826 36.4314)pt = st_as_sfc("POINT (-81.49826 36.4314)", crs = st_crs(nc))
nc[pt,]
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
## Simple feature collection with 1 feature and 14 fields
## geometry type: MULTIPOLYGON
## dimension: XY
## bbox: xmin: -81.74107 ymin: 36.23436 xmax: -81.23989 ymax: 36.58965
## epsg (SRID): 4267
## proj4string: +proj=longlat +datum=NAD27 +no_defs
## # A tibble: 1 x 15
## AREA PERIMETER CNTY_ CNTY_ID NAME FIPS FIPSNO CRESS_ID BIR74 SID74
## <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl> <int> <dbl> <dbl>
## 1 0.114 1.44 1825 1825 Ashe 37009 37009 5 1091 1
## # … with 5 more variables: NWBIR74 <dbl>, BIR79 <dbl>, SID79 <dbl>,
## # NWBIR79 <dbl>, geometry <MULTIPOLYGON [°]>
system.file("tif/L7_ETMs.tif", package = "stars") with stars::read_starslibrary(stars)
## Loading required package: abind
r = read_stars(system.file("tif/L7_ETMs.tif", package = "stars"))
r
## stars object with 3 dimensions and 1 attribute
## attribute(s):
## L7_ETMs.tif
## Min. : 1.00
## 1st Qu.: 54.00
## Median : 69.00
## Mean : 68.91
## 3rd Qu.: 86.00
## Max. :255.00
## dimension(s):
## from to offset delta refsys point values
## x 1 349 288776 28.5 +proj=utm +zone=25 +south... FALSE NULL [x]
## y 1 352 9120761 -28.5 +proj=utm +zone=25 +south... FALSE NULL [y]
## band 1 6 NA NA NA NA NULL
plot(r)
The color breaks are chosen by the default method for breaks, which is “quantile”; this means that (regularly chosen) quantiles of the pixel values are chosen; this means that the map shows equal amounts of each color.
st_apply)st_apply(r, 3, max)
## stars object with 1 dimensions and 1 attribute
## attribute(s):
## max
## Min. :255
## 1st Qu.:255
## Median :255
## Mean :255
## 3rd Qu.:255
## Max. :255
## dimension(s):
## from to offset delta refsys point values
## band 1 6 NA NA NA NA NULL
plot(st_apply(r, 1:2, max))
* find and plot the mean reflectance over all bands for all pixels
plot(st_apply(r, 1:2, mean))
* plot the subset of these data with the first 10 rows, the second 10 colums, and the last 3 bands
r[,1:10, 11:20, 4:6]
## stars object with 3 dimensions and 1 attribute
## attribute(s):
## L7_ETMs.tif
## Min. : 19.00
## 1st Qu.: 55.00
## Median : 72.00
## Mean : 70.13
## 3rd Qu.: 83.00
## Max. :130.00
## dimension(s):
## from to offset delta refsys point values
## x 1 10 288776 28.5 +proj=utm +zone=25 +south... FALSE NULL [x]
## y 11 20 9120761 -28.5 +proj=utm +zone=25 +south... FALSE NULL [y]
## band 4 6 NA NA NA NA NULL
st_crop to crop the dataset to the area 300 m around POINT (293749.5 9115745)pt = st_as_sfc("POINT (293749.5 9115745)", crs = st_crs(r))
cr = st_crop(r, st_buffer(pt, units::set_units(300, m)))
plot(cr)
* is this cropped dataset still a (rectangular) raster?
yes: the values outside the circle are simply set to NA, and are not plotted.
data(DE_RB_2005, package = "gstat")
library(spacetime)
library(stars)
s = st_as_stars(as(DE_RB_2005, "STFDF"))
# select a single day, omit NA values:
s1 = na.omit(st_as_sf(s[,,100]))
names(s1)[1] = "PM10"
library(gstat)
variogram(PM10~1, s1)
## np dist gamma dir.hor dir.ver id
## 1 4 18898.55 7.020488 0 0 var1
## 2 23 34364.92 6.440393 0 0 var1
## 3 32 56345.09 11.255562 0 0 var1
## 4 39 77732.46 7.906209 0 0 var1
## 5 55 99506.37 8.341365 0 0 var1
## 6 71 122440.26 9.902675 0 0 var1
## 7 85 143636.56 15.158993 0 0 var1
## 8 80 164572.07 13.839935 0 0 var1
## 9 91 187694.48 12.821504 0 0 var1
## 10 88 209843.86 14.708895 0 0 var1
## 11 98 231000.08 17.078920 0 0 var1
## 12 110 254882.02 22.609394 0 0 var1
## 13 104 276259.20 22.452120 0 0 var1
## 14 101 297576.88 18.176579 0 0 var1
## 15 91 320326.70 28.031442 0 0 var1
plot(variogram(PM10~1, s1))
Building on the above dataset, create out plot where:
cutoff to a much larger, and a much smaller valueplot(variogram(PM10~1, s1, cutoff = 1e5))
width argument to a larger and smaller valueplot(variogram(PM10~1, s1, width = 10000, cutoff = 5e5))
plot(variogram(PM10~1, s1, width = 100000, cutoff = 5e5))
plot(variogram(PM10~1, s1, width = 100000, cutoff = 5e5, plot.numbers = TRUE))
## Warning in variogram.default(y, locations, X, trend.beta = beta, grid =
## grid, : the following arguments are ignored: TRUE
cloud=TRUE - what do the points in this plot represent? (hint: plot the number of point pairs)plot(variogram(PM10~1, s1, cutoff = 5e5, cloud = TRUE)) # width ignored
fit.variogram; use vgm() to list the possible models and show.vgms() to get an idea how they look.v = variogram(PM10~1, s1)
init = vgm(20, "Sph", 300000, 5)
f = fit.variogram(v, init)
## Warning in fit.variogram(v, init): No convergence after 200 iterations: try
## different initial values?
plot(v, f)
plot(v, fit), and examine how it looksCompare the ranges of the kriging and idw map, and the range of the PM10 data. Explain differences and correspondences.
# load German boundaries
data(air, package = "spacetime")
de <- st_transform(st_as_sf(DE_NUTS1), 32632)
bb = st_bbox(de)
dx = seq(bb[1], bb[3], 10000)
dy = seq(bb[4], bb[2], -10000) # decreases!
st_as_stars(matrix(0., length(dx), length(dy))) %>%
st_set_dimensions(1, dx) %>%
st_set_dimensions(2, dy) %>%
st_set_crs(32632) -> grd
i = idw(PM10~1, s1, grd)
## [inverse distance weighted interpolation]
v = variogram(PM10~1, s1)
f = fit.variogram(v, vgm(20, "Lin", 0, 4))
kr = krige(PM10~1, s1, grd, f)
## [using ordinary kriging]
range(i[["var1.pred"]])
## [1] 4.03311 29.36141
range(kr[["var1.pred"]])
## [1] 7.254416 24.375381
range(s1$PM10)
## [1] 3.625 29.667
Kriging smoothes much more, mostly because the variogram model used (here) has a considerable relative nugget (nugget component as fraction of the total variance)
Examine the kriging variance error map.
plot(kr[2])
Compute a standard error map by taking the square root of the kriging variance
kr$stderr = sqrt(kr$var1.var)
Plot this map with the data points overlayed: can you explain the pattern in the errors?
plot(kr["stderr"], reset = FALSE)
plot(st_geometry(de), add = TRUE, col = NA, border = 'red')
plot(s1, add = TRUE, col = 'green', pch = 3)
Repeat the exercise with the same linear model but with a zero nugget effect, and compare the ranges again.
# brute-force: setting the nugget to zero:
f$psill[1] = 0
# somewhat "nicer": fitting the same model, but without a nugget:
f = fit.variogram(v, vgm(20, "Lin", 0))
kr0 = krige(PM10~1, s1, grd, f)
## [using ordinary kriging]
range(kr0[[1]])
## [1] 3.999323 29.490683
Repeat the exercise with the a spherical model with a short range and zero nugget, and compare the ranges again.
# use a short range spherical model, range 100 km, zero nugget:
f = vgm(20, "Sph", 100000)
kr.sph = krige(PM10~1, s1, grd, f)
## [using ordinary kriging]
range(kr.sph[[1]])
## [1] 4.146075 28.374769
Repeat the exercise with the a pure nugget effect model (e.g., vgm(20, “Nug”, 0)), and compare the ranges again.
# fit a pure nugget model:
(f = fit.variogram(v, vgm(1, "Nug", 0)))
## model psill range
## 1 Nug 10.16699 0
kr.nug = krige(PM10~1, s1, grd, f)
## [using ordinary kriging]
range(kr.nug[["var1.pred"]])
## [1] 12.50885 12.50885
mean(s1$PM10)
## [1] 12.50885
range(kr.nug[["var1.var"]])
## [1] 10.3234 10.3234
var(s1$PM10)
## [1] 20.12527
mean(variogram(PM10~1, s1, cloud=TRUE)$gamma)
## [1] 16.55404
mean(variogram(PM10~1, s1, cloud=TRUE, cutoff = 1e6)$gamma)
## [1] 20.12527
Compute (approximate) 95% prediction intervals by adding +/- 2 standard errors to the kriging
kr$stderr = sqrt(kr$var1.var)
kr$upper = kr$var1.pred + 2 * kr$stderr
kr$lower = kr$var1.pred - 2 * kr$stderr
plot(merge(kr[c("lower", "upper")]))
Create a map with locations where the threshold of 25 has been exceeded, or might have been exceeded (is inside the prediction interval)
kr$classify = ifelse(kr$lower > 25, 1, ifelse(kr$upper < 25, 3, 2))
plot(kr["classify"]) # legend 1: above 25, 2: ?, 3: below 25
block=c(10000,10000) to estimate 10 km x 10 km block mean valuesf = fit.variogram(v, vgm(20, "Lin", 0, 4))
kr = krige(PM10~1, s1, grd, f) # point kriging
## [using ordinary kriging]
bl = krige(PM10~1, s1, grd, f, block = c(10000, 10000)) # block kriging
## [using ordinary kriging]
kr$point = kr$var1.pred
kr$block = bl$var1.pred
plot(merge(kr[c("point", "block")]))
kr$point.se = sqrt(kr$var1.var)
kr$block.se = sqrt(bl$var1.var)
plot(merge(kr[c("point.se", "block.se")]))
range(kr$point)
## [1] 7.254416 24.375381
range(kr$block)
## [1] 7.282503 24.344914
range(kr$point.se)
## [1] 2.681161 5.069061
range(kr$block.se)
## [1] 1.295284 4.488885