Rendyk — Published On May 21, 2021
Advanced Machine Learning Programming Project Python

This article was published as a part of the Data Science Blogathon

After my last article about spatial correlation, this time I am going to discuss spatial interpolation. In this case, we have a dataset of point features with spatial location. Below is the fictional data we will be using for this article.

Spatial Interpolation evaporation and temp
Fig. 1 Map of data points

There are distributed 56 data points. Each point has evapotranspiration and temperature values. X and y are the location coordinates. Note that, once again, the data are fictional, NOT from real field measurement. There is a linear correlation between temperature and evapotranspiration. This means that we can apply linear regression or other regressors to predict evapotranspiration with temperature as the predictor. The result is a model or equation. Using the equation we can predict unknown evapotranspiration, but by requiring the predictor. This is a common Machine Learning task.

But, our task now is to predict the location in the white areas above so that they all have values. In other words, the task is to interpolate the data points into raster areas with evapotranspiration values. The white areas in the map above have no evapotranspiration and temperature information. Allocating more resources to collect more data in more detail spatial interval is a good idea, but acquiring field data may be costly and limited.

For instance, an Earth Scientist can have a few borehole data. Borehole data have the information on how depth every material or rock type is in vertical layers from the ground to the belowground at a point. The borehole data are acquired from drilling several locations. The data are expensive and the scientist cannot possibly request to drill the ground in every meter. The scientist has to interpolate and predict what is between every 2 or more borehole data. Another example is soil sampling. Soil scientist collects several soil samples for laboratory test.

The number of soil samples is limited to the budget. Even though the budget is unlimited, the soil scientist cannot take all the soil in his study area. The scientist has to generalize the soil type of his study area according to only a limited number of samples. This a common problem in spatial studies, like Geography, Geology, Meteorology, Soil Science, and so on.

Spatial interpolation is the solution for this task. Spatial interpolation fills the areas with no values according to the surrounding data points. We can interpolate the evapotranspiration data points into a raster. Later, we can also use temperature as the predictor to assist the interpolation process. This article focuses on describing the interpolation methods, but I will brief a little about evapotranspiration. Evapotranspiration is the combined process of evaporation and transpiration which emits water vapor to the atmosphere. This is a common topic in Hydrology.

Evaporation is the process of evaporating water bodies. The evaporation pan is an example of a field method for measuring the evaporation rate. An evaporation pan is a pan filled with water at a certain height and put in an open space. The water height will decrease in days or months due to evaporation. Then, the evaporation rate can be calculated with a coefficient. The transpiration rate is measured using the gravimetric tool. Transpiration is the process of plants releasing water vapor into the atmosphere.

Just like the cases of borehole data and soil sampling, we do not measure the evapotranspiration and temperature at every inch of our study area. It is not efficient. We can only install a limited number of tools at some location points.

Evapotranspiration rate is continuous in the spatial dimension. If there are two points with different evapotranspiration rates, the middle of the two points is likely to have the evapotranspiration rate between those of the points. This condition allows spatial interpolation. Other examples of continuous variables are elevation, water depth, rainfall, and so on. These variables can be interpolated spatially.

In the dataset, there is temperature as another variable. Temperature is also measured at every monitoring point. Temperature and evapotranspiration correlate linearly. Higher temperature affects higher evapotranspiration. This condition makes it possible to interpolate evapotranspiration using temperature as the predictor. We will practice this later as one of the interpolation methods.

Before we run the interpolation, we need to specify the spatial output extent. In GIS software, this step has been done by default. The output extent by default is a rectangle covering the minimum and maximum of both the x-axis and y-axis. In R, the output extent has to be defined by code.  The output extent can be enlarged to cover more areas. Below is the code to import packages, load the data, and create the output extent.

# Import packages
# Interpolation packages
library(gstat)  # Nearest Neighbour, IDW, Kriging
library(fields) # TPS
library(mgcv)   # GAM
library(interp) # TIN
library(automap)# Automatic Kriging
# Load point data
ET_data <- read_excel("z:/OpenMarket_Supplier/07_CarbonAssesment_project/2021/05 May/hps/dat.xlsx", sheet="Sheet2")
# Output extent
ET_sf <- st_as_sf(ET_data, coords=c("x", "y"), crs="+proj=longlat +datum=WGS84")
boundary <- c(
  "xmin" = min(ET_data$x),
  "ymin" = min(ET_data$y),
  "xmax" = max(ET_data$x),
  "ymax" = max(ET_data$y)
extent_grid <- expand.grid(
  X = seq(from=boundary["xmin"], to=boundary["xmax"], by=0.002),
  Y = seq(from=boundary["ymin"], to=boundary["ymax"], by=0.002)
# Output extent to raster
extent_grid_raster <- extent_grid %>%
  dplyr::mutate(Z = 0) %>%
    crs = "+proj=longlat +datum=WGS84")

Inverse Distance Weighted and Nearest Neighbour

After having the output extent, interpolation can be applied. The output of the interpolation will be put into the output extent. In this article, I will demonstrate 8 methods of interpolation. The last one is designed to use predictor(s). But, let’s start with the simplest method. It is the Inverse Distance Weighted (IDW). IDW predicts values of unknown locations based on the weighted average neighboring known values.

The simple form of IDW is called Nearest Neighbour. Below is the code to run Nearest Neighbor interpolation. The minimum and maximum number of data points to fit are set to be 5 and 8 respectively. The second and third IDW below is still similar, but the IDP is set to be 3 and 1 respectively. Examine that IDW with larger IDP tends to form a circular pattern around the knowns data points.

# 1. Nearest Neighbor
# Create gstat object
NN <- gstat(formula = ET ~ 1, data=ET_sf, nmax=8, nmin=5) # Number of neighbouring data points for fitting
# Interpolate
NN_intr <- interpolate(extent_grid_raster, model=NN)
# Visualize raster
plot(NN_intr, main = "Nearest Neighbour")
# 2a. Inverse Distance Weighted
IDW <- gstat(formula = ET ~ 1, data=ET_sf, nmax=8, nmin=5, set=list(idp=3)) # inverse distance power
IDW_intr <- interpolate(extent_grid_raster, model=IDW)
plot(IDW_intr, main = "Inverse Distance Weighted idp=3")
# 2b. Inverse Distance Weighted
IDW1 <- gstat(formula = ET ~ 1, data=ET_sf, nmax=8, nmin=5, set=list(idp=1)) # inverse distance power
IDW_intr1 <- interpolate(extent_grid_raster, model=IDW1)
plot(IDW_intr1, main = "Inverse Distance Weighted idp=1")


Spatial Interpolation nearest neighbour
Fig. 2 Nearest Neighbor


Spatial Interpolation inverse
Fig. 3 IDW


Thin Plate Spline Regression

Thin Plate Spline Regression (TPS) interpolates the data points by creating a smoothened thin plate connecting all the data points. Below is the code to run TPS.

# 3. Thin Plate Spline Regression
TPS <- Tps(x = as.matrix(ET_data[, c("x", "y")]), Y=ET_data$ET, miles=FALSE)
TPS_intr <- interpolate(extent_grid_raster, model=TPS)
plot(TPS_intr, main = "Thin Plate Spline Regression")


Spatial Interpolation plate spline regression
Fig. 4 TPS


Generalized Additive Model

Generalized Additive Model (GAM) interpolation works with the following code.

# 4. Generalized Additive Model
GAM <- gam(ET ~ s(x, y), data=ET_data)
extent_grid_gam <- extent_grid
names(extent_grid_gam) <- c("x", "y")
GAM_intr <- extent_grid %>% 
  mutate(Z = predict(GAM,extent_grid_gam)) %>% 
  rasterFromXYZ(crs="+proj=longlat +datum=WGS84")
plot(GAM_intr, main="Generalized Additive Model")


Spatial Interpolation GAM
Fig. 5 GAM


Triangulated Irregular Network

Triangulated Irregular Network (TIN) has the data points to create circumcircles. The intersections of those circumcircles form dots. Every dot is then connected to the neighboring 2 dots forming a triangular surface network. Below is the code to run TIN interpolation.

# 5. Triangular Irregular Network
TIN <- interp(x=ET_data$x, y=ET_data$y, z=ET_data$ET,
              xo = extent_grid$X, yo = extent_grid$Y,
              output = "points") %>% bind_cols()
TIN_intr <- rasterFromXYZ(TIN, crs="+proj=longlat +datum=WGS84")
plot(TIN_intr, main="Triangular Irregular Network")


Fig. 6 TIN


Ordinary Kriging and AutoKriging

Kriging also uses the same package as IDW does. Kriging predicts interpolation by fitting a variogram. Another method is AutoKriging. AutoKriging can automatically fit the variogram model for the interpolation. The Autokriging results below provide the interpolation prediction result, standard error, and the variogram.

# 6. Ordinary kriging
var <- variogram(ET~1, ET_sf, cutoff=100) # Variogram
var_fit <- fit.variogram(var, vgm(1, "Sph", 5, 1))
Kriging <- gstat(NULL, "ET", ET~1, ET_sf, model=var_fit)
Kriging_intr <- interpolate(extent_grid_raster, Kriging)
plot(Kriging_intr, main = "Ordinary Kriging")
# 7. Automatic Kriging
# Create SpatialPointsDataFrame
ET_df <- 
coordinates(ET_df) <- ~ x+y
# Create Spatial Pixels
extent_grid_pix <- extent_grid
gridded(extent_grid_pix) =~ X+Y
# run AutoKriging
AutoKriging = autoKrige(ET~1, ET_df, extent_grid_pix)
AutoKriging_2 <- autoKrige(ET~1, ET_df) %>% .$krige_output  %>% %>% select(X = x1, Y = x2, Z = var1.pred) 
AutoKriging_intr <- rasterFromXYZ(AutoKriging_2, crs="+proj=longlat +datum=WGS84")
extent(AutoKriging_intr) <- extent(Kriging_intr)
plot(AutoKriging_intr, main="AutoKriging")


Fig. 7 Ordinary Kriging


Fig. 8 AutoKriging


Fig. 9 Autokriging prediction, standard error, and variogram



All of the above interpolation methods only rely on the target variable, in this case, is evapotranspiration. The last method we are discussing is co-Kriging which performs spatial interpolation by using predictor(s). Given that temperature affects evapotranspiration, we want to interpolate the evapotranspiration by accounting for temperature as the predictor too. Here is the code to do so.

# 8. Co-kriging
# Gstat for target and independent variables
coKriging <- gstat(NULL, 'ET', ET~1, ET_sf)
coKriging <- gstat(coKriging, 'Temp', Temp~1, ET_sf)
# Variogram
vario <- variogram(coKriging)
plot(vario, type='b', main='Co-variogram')
# Fitting
coKriging_fit <- fit.lmc(vario, coKriging, vgm(model='Sph', range=1000))
plot(vario, coKriging_fit, main='Co-variogram After Fitting')
# Interpolation
coKriging_intr <- interpolate(extent_grid_raster, coKriging_fit)
# Visualize
plot(coKriging_intr, main = "Co-Kriging")
Fig. 10 Co-Kriging

Now that we have 9 interpolation results, we can check the Root Mean Squared Error (RMSE). The RMSE is used to compare how close the interpolation results to the recorded data points. The code below extracts each value from the 9 raster datasets where the recorded data points are located. Then, RMSE is computed to compare the extracted raster values with the true values of the data points. It seems that IDW with IDP=3 has the smallest RMSE.

# Stack the rasters and extrace the values
overlay <- stack(NN_intr, IDW_intr, IDW_intr1, TPS_intr,
                 GAM_intr, TIN_intr, Kriging_intr,
pred <-, ET_sf))
names(pred) <- c("NN", "IDW", "IDW1", "TPS", "GAM", "TIN", "Kriging", "coKriging")
pred2 <-, ET_sf))
names(pred2) <- c("AutoKriging")
pred <- cbind(ET_data, pred, pred2)
sqrt(sum((pred$ET-pred$NN)^2, na.rm=TRUE)/nrow(pred)) # 0.1576134
sqrt(sum((pred$ET-pred$IDW)^2, na.rm=TRUE)/nrow(pred)) # 0.01212739
sqrt(sum((pred$ET-pred$IDW1)^2, na.rm=TRUE)/nrow(pred)) # 2.029118
sqrt(sum((pred$ET-pred$TPS)^2, na.rm=TRUE)/nrow(pred)) # 3.518021
sqrt(sum((pred$ET-pred$GAM)^2, na.rm=TRUE)/nrow(pred)) # 5.136027
sqrt(sum((pred$ET-pred$TIN)^2, na.rm=TRUE)/nrow(pred)) #2.060511
sqrt(sum((pred$ET-pred$Kriging)^2, na.rm=TRUE)/nrow(pred)) # 5.614179
sqrt(sum((pred$ET-pred$AutoKriging)^2, na.rm=TRUE)/nrow(pred)) # 4.947287
sqrt(sum((pred$ET-pred$coKriging)^2, na.rm=TRUE)/nrow(pred)) # 0.6766445


About Author

Connect with me here.

The media shown in this article are not owned by Analytics Vidhya and is used at the Author’s discretion. 

About the Author

Our Top Authors

Download Analytics Vidhya App for the Latest blog/Article

Leave a Reply Your email address will not be published. Required fields are marked *