Search code examples
rrasterterra

Set as NA specific columns in multi-layer terra objects


Given:

library(terra)
r <- rast(nrows=512, ncols=640,nlyrs=1, res=1,crs="local",extent=c(0,640,0,512))
values(r) <- rnorm(ncell(r),100,10)
x <- c(r, r*2, r*3, r*0.5)
plotRGB(x, stretch="lin")

and

weirds <- data.frame(bands=c(1,3), mincol=c(5,100), maxcol=c(7,103))
weirds
> weirds
  bands mincol maxcol
     1      5      7
     3    100    103

I have to set as NA those cells within mincol and maxcol in weirds for the given bands. I achieve in this way:

y <- x
for (i in 1:nrow(weirds)) {
  y[[weirds$bands[i]]][,weirds$mincol[i]:weirds$maxcol[i]]  <- NA
}
plotRGB(y, stretch="lin")

But I am sure there are more efficient ways. Can anyone make suggestions?


Solution

  • With terra 1.6-24 (currently the development version) you can use indexing for layers.

    Example data

    library(terra)
    #terra 1.6.24
    r <- rast(nrows=30, ncols=30, nlyrs=1,extent=c(0,640,0,512))
    values(r) <- rnorm(ncell(r), 100, 10)
    x <- c(r, r*2, r*3)
    w <- data.frame(bands=c(1,3), mincol=c(5,20), maxcol=c(7,23))
    

    First approach. This is very similar to what you had, but perhaps a little cleaner.

    y <- x
    for (i in 1:nrow(w)) {
      y[ , w$mincol[i]:w$maxcol[i], w$bands[i]] <- NA
    }
    plot(y)
    

    Second approach. Using a list for one or more of the indices i (row), j (col), or k (lyr) you can do multiple replacements at once.

    z <- x
    cols <- lapply(1:nrow(w), function(i) seq(w[i, 2], w[i, 3]))
    z[ , cols, w$bands] <- NA
    plot(z, nc=3)
    

    enter image description here

    I would assume that this is the better approach and that you can probably directly create the cols list, instead of deriving it from w

    You can install the development version of "terra" with install.packages('terra', repos='https://rspatial.r-universe.dev')