Skip to content

Commit cd08058

Browse files
author
David O'Sullivan
committed
updated interpolation materials for 2023
1 parent 1fe0391 commit cd08058

19 files changed

+152
-108
lines changed

labs/interpolation/01-overview-of-the-approach.Rmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# The overall approach to interpolation
44
The *R* ecosystem's approach to spatial interpolation seems pretty complicated at first. It's not exactly simple, although the overall concept is straightforward enough and some of the apparent complexity has more to do with making different data types interact with one another successfully.

labs/interpolation/01-overview-of-the-approach.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# The overall approach to interpolation
44
The *R* ecosystem's approach to spatial interpolation seems pretty complicated at first. It's not exactly simple, although the overall concept is straightforward enough and some of the apparent complexity has more to do with making different data types interact with one another successfully.

labs/interpolation/02-example-dataset.Rmd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# Basics of working with raster data
33
First load some libraries
44

55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
```
1010
The new(ish) to us kid on the block here is `raster` for handling gridded raster datasets. One thing to be very aware of is that `raster` masks the `select` function from `dplyr` so you have to specify `dplyr::select` when using the `select` to tidy up datasets during data preparation.
1111

1212
## Read a raster dataset
1313
We are using a simple example of the elevation of Maungawhau (Mt Eden) in Auckland to demonstrate the interpolation methods. There is a version of this dataset available as standard in *R* but I made raster version of it for us to work with. So load this with the raster package:
1414

1515
```{r}
16-
volcano <- raster("data/maungawhau.tif")
16+
volcano <- rast("data/maungawhau.tif")
1717
```
1818

1919
Confusingly, when you read in a raster dataset it names the associated numerical data using the filename, so we rename that to `height` which is more appropriate for our purposes.

labs/interpolation/02-example-dataset.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# Basics of working with raster data
33
First load some libraries
44

55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
```
1010
The new(ish) to us kid on the block here is `raster` for handling gridded raster datasets. One thing to be very aware of is that `raster` masks the `select` function from `dplyr` so you have to specify `dplyr::select` when using the `select` to tidy up datasets during data preparation.
1111

1212
## Read a raster dataset
1313
We are using a simple example of the elevation of Maungawhau (Mt Eden) in Auckland to demonstrate the interpolation methods. There is a version of this dataset available as standard in *R* but I made raster version of it for us to work with. So load this with the raster package:
1414

1515
```{r}
16-
volcano <- raster("data/maungawhau.tif")
16+
volcano <- rast("data/maungawhau.tif")
1717
```
1818

1919
Confusingly, when you read in a raster dataset it names the associated numerical data using the filename, so we rename that to `height` which is more appropriate for our purposes.

labs/interpolation/03-preparing-for-interpolation.Rmd

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# Preparing for interpolation
44
Run this first to make sure all the data and packages you need are loaded:
55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
library(dplyr)
1010
11-
volcano <- raster("data/maungawhau.tif")
11+
volcano <- rast("data/maungawhau.tif")
1212
names(volcano) <- "height"
1313
```
1414

@@ -34,14 +34,19 @@ interp_ext <- controls %>%
3434
## Control points
3535
For the demonstration data, we already know the result.
3636

37-
Normally, we would have a set of control points in some spatial format and would simply read them with `sf::st_read`. Here, we will make set of random control points to work with in the other steps of these instructions when we are using the Maungawhau data. We start from the interpolation extent, and use `st_sample` to get a specified random number of points in the extent, then convert it to an `sf` dataset. Finally we use the `raster::extract` function to extract values from the raster dataset and assign their values to a height attribute of the `sf` dataset.
37+
Normally, we would have a set of control points in some spatial format and would simply read them with `sf::st_read`. Here, we will make set of random control points to work with in the other steps of these instructions when we are using the Maungawhau data. We start from the interpolation extent, and use `st_sample` to get a specified random number of points in the extent, then convert it to an `sf` dataset. Finally we use the `terra::extract` function to extract values from the raster dataset and assign their values to a height attribute of the `sf` dataset.
3838

3939
```{r}
4040
controls <- interp_ext %>%
4141
st_sample(size = 250) %>%
4242
st_sf() %>%
43-
st_set_crs(st_crs(interp_ext)) %>%
44-
mutate(height = raster::extract(volcano, .))
43+
st_set_crs(st_crs(interp_ext))
44+
45+
heights <- controls %>%
46+
extract(x = volcano)
47+
48+
controls <- controls %>%
49+
mutate(height = heights$height)
4550
```
4651

4752
Every time you run the above you will get a different random set of the specified number of control point locations. It is useful to map them on top of the underlying data and think about how many you might need to get a reasonable representation of the height map of Maungawhau.
@@ -66,7 +71,7 @@ st_read("data/controls.gpkg") %>%
6671
Remember that if you change the control points, you should also change this file to keep them matching.
6772

6873
## Make a set of locations to interpolate
69-
Unlike the previous step which may not be necessary when you are provided with control points to interpolate directly, this step is always required. Basically, *R* wants a raster layer to *interpolate into*. We'll call this `sites` and make `sf`, `raster` and simple xyz versions of these.
74+
Unlike the previous step which may not be necessary when you are provided with control points to interpolate directly, this step is always required. Basically, *R* wants a raster layer to *interpolate into*. We'll call this `sites` and make `sf`, `terra` and simple xyz versions of these.
7075

7176
```{r}
7277
sites_sf <- interp_ext %>% # start with the extent
@@ -75,12 +80,12 @@ sites_sf <- interp_ext %>% # start with the extent
7580
st_set_crs(st_crs(interp_ext))
7681
7782
sites_xyz <- sites_sf %>%
78-
cbind(st_coordinates(.)) %>%
83+
bind_cols(st_coordinates(.)) %>%
7984
st_drop_geometry() %>%
8085
mutate(Z = 0)
8186
8287
sites_raster <- sites_xyz %>%
83-
rasterFromXYZ()
88+
rast(type = "xyz")
8489
crs(sites_raster) <- st_crs(controls)$wkt
8590
```
8691

labs/interpolation/03-preparing-for-interpolation.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# Preparing for interpolation
44
Run this first to make sure all the data and packages you need are loaded:
55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
library(dplyr)
1010
11-
volcano <- raster("data/maungawhau.tif")
11+
volcano <- rast("data/maungawhau.tif")
1212
names(volcano) <- "height"
1313
```
1414

@@ -34,14 +34,19 @@ interp_ext <- controls %>%
3434
## Control points
3535
For the demonstration data, we already know the result.
3636

37-
Normally, we would have a set of control points in some spatial format and would simply read them with `sf::st_read`. Here, we will make set of random control points to work with in the other steps of these instructions when we are using the Maungawhau data. We start from the interpolation extent, and use `st_sample` to get a specified random number of points in the extent, then convert it to an `sf` dataset. Finally we use the `raster::extract` function to extract values from the raster dataset and assign their values to a height attribute of the `sf` dataset.
37+
Normally, we would have a set of control points in some spatial format and would simply read them with `sf::st_read`. Here, we will make set of random control points to work with in the other steps of these instructions when we are using the Maungawhau data. We start from the interpolation extent, and use `st_sample` to get a specified random number of points in the extent, then convert it to an `sf` dataset. Finally we use the `terra::extract` function to extract values from the raster dataset and assign their values to a height attribute of the `sf` dataset.
3838

3939
```{r}
4040
controls <- interp_ext %>%
4141
st_sample(size = 250) %>%
4242
st_sf() %>%
43-
st_set_crs(st_crs(interp_ext)) %>%
44-
mutate(height = raster::extract(volcano, .))
43+
st_set_crs(st_crs(interp_ext))
44+
45+
heights <- controls %>%
46+
extract(x = volcano)
47+
48+
controls <- controls %>%
49+
mutate(height = heights$height)
4550
```
4651

4752
Every time you run the above you will get a different random set of the specified number of control point locations. It is useful to map them on top of the underlying data and think about how many you might need to get a reasonable representation of the height map of Maungawhau.
@@ -66,7 +71,7 @@ st_read("data/controls.gpkg") %>%
6671
Remember that if you change the control points, you should also change this file to keep them matching.
6772

6873
## Make a set of locations to interpolate
69-
Unlike the previous step which may not be necessary when you are provided with control points to interpolate directly, this step is always required. Basically, *R* wants a raster layer to *interpolate into*. We'll call this `sites` and make `sf`, `raster` and simple xyz versions of these.
74+
Unlike the previous step which may not be necessary when you are provided with control points to interpolate directly, this step is always required. Basically, *R* wants a raster layer to *interpolate into*. We'll call this `sites` and make `sf`, `terra` and simple xyz versions of these.
7075

7176
```{r}
7277
sites_sf <- interp_ext %>% # start with the extent
@@ -75,12 +80,12 @@ sites_sf <- interp_ext %>% # start with the extent
7580
st_set_crs(st_crs(interp_ext))
7681
7782
sites_xyz <- sites_sf %>%
78-
cbind(st_coordinates(.)) %>%
83+
bind_cols(st_coordinates(.)) %>%
7984
st_drop_geometry() %>%
8085
mutate(Z = 0)
8186
8287
sites_raster <- sites_xyz %>%
83-
rasterFromXYZ()
88+
rast(type = "xyz")
8489
crs(sites_raster) <- st_crs(controls)$wkt
8590
```
8691

labs/interpolation/04-nn-and-idw.Rmd

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# Near neighbour and inverse-distance weighted interpolation
33
Run this first to make sure all the data and packages you need are loaded. If any data are missing you probably didn't make them in one of the previous instruction pages.
44

55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
library(dplyr)
1010
library(gstat)
1111
12-
volcano <- raster("data/maungawhau.tif")
12+
volcano <- rast("data/maungawhau.tif")
1313
names(volcano) <- "data/height"
1414
1515
controls <- st_read("data/controls.gpkg")
1616
sites_sf <- st_read("data/sites-sf.gpkg")
17-
sites_raster <- raster("data/sites-raster.tif")
17+
sites_raster <- rast("data/sites-raster.tif")
1818
```
1919

2020
## Inverse-distance weighted interpolation
@@ -23,9 +23,9 @@ These two methods are very similar, and IDW is actually *more general* so we'll
2323
As with all the `gstat` methods we use the `gstat::gstat` function to make a statistical model, and then apply it using the `raster::interpolate` function.
2424

2525
```{r}
26-
fit_IDW <- gstat( # makes a model
27-
formula = height ~ 1, # The column `height` is what we are interested in
28-
data = as(controls, "Spatial"), # using sf but converting to sp, which is required
26+
fit_IDW <- gstat( # makes a model
27+
formula = height ~ 1, # The column `height` is what we are interested in
28+
data = as(controls, "Spatial"), # using sf but converting to sp, which is required
2929
set = list(idp = 2),
3030
# nmax = 12, maxdist = 100 # you can experiment with these options later...
3131
)
@@ -37,7 +37,7 @@ Having made the model (called `fit_IDW`) we pass it to the `predict` function to
3737

3838
```{r}
3939
interp_pts_IDW <- predict(fit_IDW, sites_sf)
40-
interp_IDW <- rasterize(as(interp_pts_IDW, "Spatial"), sites_raster, "var1.pred")
40+
interp_IDW <- rasterize(as(interp_pts_IDW, "SpatVector"), sites_raster, "var1.pred")
4141
names(interp_IDW) <- "height" # rename the variable to something more friendly
4242
```
4343

@@ -70,7 +70,7 @@ fit_NN <- gstat( # makes a model
7070
7171
# and interpolate like before
7272
interp_pts_NN <- predict(fit_NN, sites_sf)
73-
interp_NN <- rasterize(as(interp_pts_NN, "Spatial"), sites_raster, "var1.pred")
73+
interp_NN <- rasterize(as(interp_pts_NN, "SpatVector"), sites_raster, "var1.pred")
7474
names(interp_NN) <- "height"
7575
7676
# and display it

labs/interpolation/04-nn-and-idw.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# Near neighbour and inverse-distance weighted interpolation
33
Run this first to make sure all the data and packages you need are loaded. If any data are missing you probably didn't make them in one of the previous instruction pages.
44

55
```{r}
66
library(sf)
77
library(tmap)
8-
library(raster)
8+
library(terra)
99
library(dplyr)
1010
library(gstat)
1111
12-
volcano <- raster("data/maungawhau.tif")
12+
volcano <- rast("data/maungawhau.tif")
1313
names(volcano) <- "data/height"
1414
1515
controls <- st_read("data/controls.gpkg")
1616
sites_sf <- st_read("data/sites-sf.gpkg")
17-
sites_raster <- raster("data/sites-raster.tif")
17+
sites_raster <- rast("data/sites-raster.tif")
1818
```
1919

2020
## Inverse-distance weighted interpolation
@@ -23,9 +23,9 @@ These two methods are very similar, and IDW is actually *more general* so we'll
2323
As with all the `gstat` methods we use the `gstat::gstat` function to make a statistical model, and then apply it using the `raster::interpolate` function.
2424

2525
```{r}
26-
fit_IDW <- gstat( # makes a model
27-
formula = height ~ 1, # The column `height` is what we are interested in
28-
data = as(controls, "Spatial"), # using sf but converting to sp, which is required
26+
fit_IDW <- gstat( # makes a model
27+
formula = height ~ 1, # The column `height` is what we are interested in
28+
data = as(controls, "Spatial"), # using sf but converting to sp, which is required
2929
set = list(idp = 2),
3030
# nmax = 12, maxdist = 100 # you can experiment with these options later...
3131
)
@@ -37,7 +37,7 @@ Having made the model (called `fit_IDW`) we pass it to the `predict` function to
3737

3838
```{r}
3939
interp_pts_IDW <- predict(fit_IDW, sites_sf)
40-
interp_IDW <- rasterize(as(interp_pts_IDW, "Spatial"), sites_raster, "var1.pred")
40+
interp_IDW <- rasterize(as(interp_pts_IDW, "SpatVector"), sites_raster, "var1.pred")
4141
names(interp_IDW) <- "height" # rename the variable to something more friendly
4242
```
4343

@@ -70,7 +70,7 @@ fit_NN <- gstat( # makes a model
7070
7171
# and interpolate like before
7272
interp_pts_NN <- predict(fit_NN, sites_sf)
73-
interp_NN <- rasterize(as(interp_pts_NN, "Spatial"), sites_raster, "var1.pred")
73+
interp_NN <- rasterize(as(interp_pts_NN, "SpatVector"), sites_raster, "var1.pred")
7474
names(interp_NN) <- "height"
7575
7676
# and display it

labs/interpolation/05-trend-surfaces-and-kriging.Rmd

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# Trend surfaces and kriging
44

@@ -7,16 +7,16 @@ Run this first to make sure all the data and packages you need are loaded. If an
77
```{r}
88
library(sf)
99
library(tmap)
10-
library(raster)
10+
library(terra)
1111
library(dplyr)
1212
library(gstat)
1313
14-
volcano <- raster("data/maungawhau.tif")
14+
volcano <- rast("data/maungawhau.tif")
1515
names(volcano) <- "data/height"
1616
1717
controls <- st_read("data/controls.gpkg")
1818
sites_sf <- st_read("data/sites-sf.gpkg")
19-
sites_raster <- raster("data/sites-raster.tif")
19+
sites_raster <- rast("data/sites-raster.tif")
2020
```
2121

2222
There are many different styles of kriging. We'll work here with universal kriging which models variation in the data with two components a *trend surface* and a *variogram* which models how control points vary with distance from one another. So... to perform kriging we have to consider each of these elements in turn.
@@ -38,7 +38,7 @@ The form of the trend surface function is specified by the `degree` parameter an
3838

3939
```{r}
4040
interp_pts_TS <- predict(fit_TS, sites_sf)
41-
interp_TS <- rasterize(as(interp_pts_TS, "Spatial"), sites_raster)
41+
interp_TS <- rasterize(as(interp_pts_TS, "SpatVector"), sites_raster, field = c("var1.pred", "var1.var"))
4242
4343
persp(interp_TS$var1.pred, scale = FALSE, expand = 2, theta = 35, phi = 30, lwd = 0.5)
4444
```
@@ -100,7 +100,7 @@ I have found that it is important to set a fairly low `nmax` with these data. I
100100

101101
```{r}
102102
interp_pts_K <- predict(fit_K, sites_sf)
103-
interp_K <- rasterize(as(interp_pts_K, "Spatial"), sites_raster)
103+
interp_K <- rasterize(as(interp_pts_K, "SpatVector"), sites_raster, field = c("var1.pred", "var1.var"))
104104
105105
persp(interp_K$var1.pred, scale = FALSE, expand = 2, theta = 35, phi = 30, lwd = 0.5)
106106
```

labs/interpolation/05-trend-surfaces-and-kriging.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22

33
# Trend surfaces and kriging
44

@@ -7,16 +7,16 @@ Run this first to make sure all the data and packages you need are loaded. If an
77
```{r}
88
library(sf)
99
library(tmap)
10-
library(raster)
10+
library(terra)
1111
library(dplyr)
1212
library(gstat)
1313
14-
volcano <- raster("data/maungawhau.tif")
14+
volcano <- rast("data/maungawhau.tif")
1515
names(volcano) <- "data/height"
1616
1717
controls <- st_read("data/controls.gpkg")
1818
sites_sf <- st_read("data/sites-sf.gpkg")
19-
sites_raster <- raster("data/sites-raster.tif")
19+
sites_raster <- rast("data/sites-raster.tif")
2020
```
2121

2222
There are many different styles of kriging. We'll work here with universal kriging which models variation in the data with two components a *trend surface* and a *variogram* which models how control points vary with distance from one another. So... to perform kriging we have to consider each of these elements in turn.
@@ -38,7 +38,7 @@ The form of the trend surface function is specified by the `degree` parameter an
3838

3939
```{r}
4040
interp_pts_TS <- predict(fit_TS, sites_sf)
41-
interp_TS <- rasterize(as(interp_pts_TS, "Spatial"), sites_raster)
41+
interp_TS <- rasterize(as(interp_pts_TS, "SpatVector"), sites_raster, field = c("var1.pred", "var1.var"))
4242
4343
persp(interp_TS$var1.pred, scale = FALSE, expand = 2, theta = 35, phi = 30, lwd = 0.5)
4444
```
@@ -100,7 +100,7 @@ I have found that it is important to set a fairly low `nmax` with these data. I
100100

101101
```{r}
102102
interp_pts_K <- predict(fit_K, sites_sf)
103-
interp_K <- rasterize(as(interp_pts_K, "Spatial"), sites_raster)
103+
interp_K <- rasterize(as(interp_pts_K, "SpatVector"), sites_raster, field = c("var1.pred", "var1.var"))
104104
105105
persp(interp_K$var1.pred, scale = FALSE, expand = 2, theta = 35, phi = 30, lwd = 0.5)
106106
```

0 commit comments

Comments
 (0)