Search code examples
rrasterrandom-forestterra

terra::predict() applied directly on spatraster


I created a random forest model in R, and want to apply it to a SpatRaster object using the predict function in terra. I could transform the raster to a data.frame instead of predicting directly on the SpatRaster, however my actual dataset is too large for that.

A reproducible example:

library(terra)
library(ranger)

r <- rast(ncols=95, nrows=90, nlyrs=5, crs="+proj=longlat",
          xmin=5.74167, xmax=6.5333, ymin=49.44167, ymax=50.19167,
          names=c("band1","band2","band3","band4","band5"))

# Fill the raster with random values
set.seed(123)
r$band1 <- runif(n = ncell(r))
r$band2 <- init(r, "cell")
r$band3 <- sample(1:10, ncell(r), replace = T)
r$band4 <- sample(1:10, ncell(r), replace = T)
r$band5 <- sample(1:10, ncell(r), replace = T)

# Extract some random raster values as training data
extr_values <- spatSample(r, 10)
extr_values$response <- as.factor(sample(c(1,2), nrow(extr_values), replace = T))

# Model
rf_model <- ranger(response ~., data = extr_values, num.trees = 50)

# Prediction
prediction <- predict(r, rf_model,  na.rm = TRUE)$predictions

I have tried different types of models (e.g. randomForest package), different rasters and sets of coordinates. Even stranger, I ran old scripts that performed similar tasks and that used to run, they all produce the same error. Maybe linked to a recent update of terra? Any help would be greatly appreciated.


Solution

  • The output of ranger::predict is a list. That is not what is expected.

    p <- predict(rf_model, r[1:2])
    str(p)
    #List of 5
    # $ predictions              : Factor w/ 1 level "1": 1 1
    # $ num.trees                : num 500
    # $ num.independent.variables: num 5
    # $ num.samples              : int 2
    # $ treetype                 : chr "Classification"
    # - attr(*, "class")= chr "ranger.prediction"
    

    You are interested in the "predictions". To get these values into the output raster, you need to provide a custom predict function.

    pfun <- \(...) {
        predict(...)$predictions
    }
    
    p <- predict(r, rf_model,  fun=pfun, na.rm = TRUE)