0
votes

I have been struggling with an issue for several hours and I am currently having a very hard trying to find a workaround.

I want to use the overlay function of the raster package. This function combines multiple rasters (or raster layers of a stack) into a new raster according to a specific function, such as a mathematical function.

Here is a practical example:

library(raster)
# First we create an example raster stack with two layers
a <- matrix(rep(dnorm(1:100, 50, sd = 25)),
            nrow = 100, ncol = 100, byrow = TRUE)
env <- stack(raster(a * dnorm(1:100, 50, sd = 25) * 10000),
             raster(a * 1:100))
names(env) <- c("variable1", "variable2")
plot(env)

enter image description here

# Second, we combine them with a simple addition
raster3 <- overlay(env, fun = function(variable1, variable2) variable1 + variable2)
plot(raster3)

The resulting raster after combination with overlay

So, in the example above, our raster has two variables called variable1 and variable2, and we apply the formula variable1 + variable2 on them.

The problem

I am trying to use overlay within a function, in which I have:

  • the input raster stack (the number of layers is variable, as well as the names of layers). A typical example is the stack env above.
  • the formula (the formula is always written based on layer names of the input raster stack). Typical examples are variable1 + variable2 or variable1 * variable2 + 3 * variable1.

My (unsuccessful) attempts

I was able to use a formula previously stored as a string in an object:

form <- "variable1 + 3 * variable2"
raster4 <- overlay(env, fun = function(variable1, variable2) eval(parse(text = form)))

This works; however, you can notice that I still had to specify variable1 and variable2 as arguments. I am not able to figure out how to automatically provide layer names as arguments in fun.

I tried:

overlay(env, fun = function(...) eval(parse(text = form)))
overlay(env, fun = function(names(env)) eval(parse(text = form)))

but these obviously did not work. I am already using the terrible eval(parse()) procedure within the function, I would like to find a solution which will not require me to write a general eval(parse()) script encompassing the whole overlay.

Any insights will be greatly appreciated ;)

2

2 Answers

0
votes

Here is an ugly workaround using eval(parse())

The aim is to create a function which adapts to the input raster and formula.

  • Example with the formula variable1 + variable2

.

form <- "variable1 + variable2"
input.raster <- env
eval(parse(text = paste("custom.overlay <- function(",
                        paste(names(input.raster), collapse = ", "),
                        ") {",
                        form,
                        "}"
)))
raster4 <- overlay(env, fun = custom.overlay)
plot(raster4)

enter image description here

  • Another example with the formula variable1^2 + 3 * variable2

.

form <- "variable1^2 + 3 * variable2"
input.raster <- env
eval(parse(text = paste("custom.overlay <- function(",
                        paste(names(input.raster), collapse = ", "),
                        ") {",
                        form,
                        "}"
)))
raster5 <- overlay(env, fun = custom.overlay)
plot(raster5)

enter image description here

It works in both cases. But it's not a very elegant solution

0
votes

You should not refer to the variable names, but to their position. Then you can do, for example:

library(raster)
a <- matrix(rep(dnorm(1:100, 50, sd = 25)), nrow = 100, ncol = 100, byrow = TRUE)
env <- stack(raster(a * dnorm(1:100, 50, sd = 25) * 10000), raster(a * 1:100))

v <- overlay(env, fun=function(x,y) x * y + 3 - sqrt(y / x))

And without the "eval(parse(text = form)" business, your example works fine for me:

raster4 <- overlay(env, fun = function(variable1, variable2) variable1 + 3 * variable2)