ia200
ia200

Reputation: 359

How to format 'const' argument in Terra::Predict?

Question: How do I format the 'const' argument for the predict function in the Terra package?

Background and details:

I am using Terra's predict function to create spatial maps from a model. The function worked as expected when I created full rasters for my three constant values. When I saw predict has an argument 'const' for constants, I decided to use that instead. Unfortunately, the help document doesn't specify how to structure the data beyond that they should be in a dataframe.

Argument description for 'const' from ?terra::predict:

data.frame. Can be used to add a constant value as a predictor variable so that you do not need to make a SpatRaster layer for it

The argument is not used in any of the examples listed at the bottom of the document either.

What I tried:

I tried formating the dataframe as a single row with named columns for each constant value that is required in the model. The function accepted it with the warning:

Warning messages: 1: In data.frame(..., check.names = FALSE) : row names were found from a short variable and have been discarded

But this produced clearly incorrect values in the resulting outputs. Possibly it was just using the first value for all three constants, but I don't know.

I also tried formating the dataframe with two columns, one for the variable name and one for the variable values. This failed with the following error:

Error in h(simpleError(msg, call)) : error in evaluating the argument 'x' in selecting a method for function 'writeRaster': arguments imply differing number of rows: 10000, 3

10000 may be referring to the dimenions of the raster data (10k x 10k) and the 3 is likely referring to the three rows in the constant dataframe I supplied.

I don't want to go back to writing rasters for each constant because I am producing many maps and each one would require 3 10k x 10k rasters to be generated with the constant values, which is time consuming and may lead to memory issues.

Any suggestions would be greatly appreciated!

Upvotes: 2

Views: 287

Answers (1)

Robert Hijmans
Robert Hijmans

Reputation: 47481

Here is an illustration

library(terra)
logo <- rast(system.file("ex/logo.tif", package="terra"))   
names(logo) <- c("red", "green", "blue")
p <- matrix(c(48, 48, 48, 53, 50, 46, 54, 70, 84, 85, 74, 84, 95, 85, 66, 42, 26, 4, 19, 17, 7, 14, 26, 29, 39, 45, 51, 56, 46, 38, 31, 22, 34, 60, 70, 73, 63, 46, 43, 28), ncol=2)
a <- matrix(c(22, 33, 64, 85, 92, 94, 59, 27, 30, 64, 60, 33, 31, 9,  99, 67, 15, 5, 4, 30, 8, 37, 42, 27, 19, 69, 60, 73, 3, 5, 21,37, 52, 70, 74, 9, 13, 4, 17, 47), ncol=2)
xy <- rbind(cbind(1, p), cbind(0, a))
e <- extract(logo, xy[,2:3])
v <- data.frame(cbind(pa=xy[,1], e))

model <- glm(formula=pa~., data=v)

names(model$coefficients)[-1]
#[1] "red"   "green" "blue" 
names(logo)
#[1] "red"   "green" "blue" 

# standard approach
r <- predict(logo, model)

# one or more constants 
r <- predict(logo[[2:3]], model, const=data.frame(red=0))
r <- predict(logo$blue, model, const=data.frame(red=100, green=0))

# you could even use constants only 
x <- logo[[1]]
names(x) <- "A"
r <- predict(x, model, const=data.frame(blue=50, red=100, green=0))

The output is as expected:

predict(model, data.frame(blue=50, red=100, green=0))
#        1 
#-4.538653 

r[1]
#          A
#1 -4.538653

Upvotes: 2

Related Questions