Raster Calculation with 2 Raster Layers [closed]

I am attempting to create a new raster layer based on the values of one raster layer using a formula that is conditional based on the values in another layer.

Two source layers:

> ndvi
class       : RasterLayer
dimensions  : 7741, 7611, 58916751  (nrow, ncol, ncell)
resolution  : 30, 30  (x, y)
extent      : 580185, 808515, 4191885, 4424115  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=15 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : C:/Users/xxx/AppData/Local/Temp/RtmpScc57V/raster/r_tmp_2019-04-22_112901_2168_61926.grd
names       : layer
values      : -1, 1  (min, max)

> pv
class       : RasterLayer
dimensions  : 7741, 7611, 58916751  (nrow, ncol, ncell)
resolution  : 30, 30  (x, y)
extent      : 580185, 808515, 4191885, 4424115  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=15 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : C:/Users/xxx/AppData/Local/Temp/RtmpScc57V/raster/r_tmp_2019-04-22_112936_2168_54474.grd
names       : layer
values      : 0, 1  (min, max)

Layers each have the same dimensions, projection, and extent.

I want to create a new layer, e, that has the value:

0.97 when ndvi < 0.2
0.004 * pv + 0.986 when ndvi >= 0.2 and ndvi <= 0.5
0.99 when ndvi > 0.5

My statement is:

e <- overlay(ndvi, pv, fun = function(ndvi, pv)
{
ifelse(ndvi < 0.2, 0.97, ifelse(ndvi > 0.5, 0.99, 0.004 * pv + 0.986))
}
)

However, when I execute this, I receive the error:

Error in ifelse(ndvi > 0.5, 0.99, 0.004 * pv + 0.986) : argument "pv" is missing, with no default

How can I write this function so that it is compatible with overlay()? Is another approach more appropriate?

I'm somewhat new to R.

Other permutations attempted:

calc_e <- function(ndvi, pv)
{
ifelse(ndvi < 0.2, 0.97, ifelse(ndvi <= 0.5, 0.004 * pv + 0.986, 0.99))
}

e <- overlay(ndvi, pv, fun = calc_e)

Same error was returned.

Then I tried:

ndvi_2 <- ndvi
ndvi_2[ndvi_2 < 0.2] <- 0.92

ndvi_m <- ndvi
ndvi_m[ndvi_m >= 0.2 && ndvi_m <= 0.5] <- 0.004 * pv + 0.986

ndvi_5 <- ndvi
ndvi_5[ndvi_5 > 0.5] <- 0.99

The first and third subset assignments ran. However, I received an error on the second one "ndvi_m[ndvi_m >= 0.2 && ndvi_m <= 0.5] <- 0.004 * pv + 0.986"

Error in ndvi_m >= 0.2 && ndvi_m <= 0.5 : invalid 'x' type in 'x && y'

closed as off-topic by whyzar, Vince, Jochen Schwarze, nmtoken, aldo_tapiaMay 7 at 12:30

This question appears to be off-topic. The users who voted to close gave this specific reason:

• "This problem cannot or can no longer be reproduced. Changes to the system or to the asker's circumstances may have rendered the question obsolete, or the question does not include a procedure to enable potential answerers to reproduce the same symptoms. Such questions are off-topic as they are unlikely to help future readers, but editing them to include more details can lead to re-opening." – Vince, nmtoken
If this question can be reworded to fit the rules in the help center, please edit the question.

• Possible duplicate of R: Overlay using functions containing if/else statements – GISKid Apr 22 at 19:50
• I did see that question/answer prior to posting my question. I even temporarily updated my syntax to use stack() as was used in that question's answer. However, I received the same error and subsequently reverted my syntax. – Michael Wohlstadter Apr 22 at 20:11
• I would define your function outside of the overlay similar to the other answer for starters. As another troubleshooting step, I'd create separate rasters matching your conditions e.g. ndvi2=ndvi ndvi2[ndvi2<0.2]=0.92 see here stackoverflow.com/questions/51716315/… – GISKid Apr 22 at 20:28
• I separated out the function, but the error remained. I will continue with your next suggestion. – Michael Wohlstadter Apr 22 at 20:33
• The solution was to use the function as defined by GISKid and pass that with the raster stack to calc() instead of overlay(). Thank you! – Michael Wohlstadter Apr 23 at 16:06

Try this:

recalc<-function(ndvi,pv){
ifelse(ndvi<0.2,0.92,ifelse(ndvi >= 0.2 & ndvi <= 0.5,0.004 * pv + 0.986,ifelse(ndvi >0.5,0.99,NA)))
}

r<-stack(ndvi,pv)
res <- overlay(r, fun = recalc)

As per updated comment the solution that worked was instead using calc:

res<-calc(r,fun=recalc)

The recalc function is basically saying : If ndvi < 0.2, assign 0.92, if not look at this new ifelse based on these other conditions, assign this new value using this formula, if it doesn't meet this condition try ndvi >0.5 and assign 0.99 for anything that doesn't match those conditions assign it a value of "NA".

• Same error. I'm beginning to wonder if it is something in the data. I need to dig further into that. – Michael Wohlstadter Apr 22 at 21:30
• Try adding a ... argument in the recalc function. You do not actually need to do anything with it as it is providing a passthrough to overlay. – Jeffrey Evans Apr 23 at 0:51

With help from @GISKid and @JeffreyEvans, the solution that finally worked was a combination of both of their comments.

calc_e = function(x) {
return(
ifelse(
x < 0.2,
0.97,
ifelse(
x >= 0.2 && x <= 0.5,
0.004 + x * 0.986,
ifelse(
x > 0.5,
0.99,
NA
)))) }

e <- calc(stack(ndvi, pv), fun = calc_e)