2

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_tapia May 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.

  • 1
    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
  • 1
    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
2

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
  • 1
    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
2

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[1] < 0.2,
                    0.97,
                    ifelse(
                            x[1] >= 0.2 && x[1] <= 0.5,
                            0.004 + x[2] * 0.986,
                            ifelse(
                                    x[1] > 0.5,
                                    0.99,
                                    NA
    )))) }

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.