1

I want to replace all NA values in a large raster with 0. I found this answer: Replace NA's with 0 for raster data using R?

#getting a raster
library(raster)
f <- system.file("external/test.grd", package="raster")
f
r <- raster(f) #r is the object of class 'raster'.

# replacing NA's by zero
r[is.na(r[])] <- 0 

but it's not working for my case because the raster is too large thus the computer runs out of memory. Is there an other solution which is more memory efficient?

3

"external/test.grd" isn't the best way to test this. Is a very small raster, so results can't be applied in a large raster.

Here I present a comparison with 4 different approaches, the file used is a mosaic of 12 tiles of ALOS DEM 30m (size per tile: 1x1 degree). Options a and b are the most suitable for small rasters, let's see if they are good for big ones:

library(raster)
library(microbenchmark)

r <- raster('~/path/to/mosaic.tif')

NAvalue(r) <- -9999

r <- setMinMax(r)

plot(r)

enter image description here

plot(is.na(r))

enter image description here

microbenchmark(a = r[is.na(r[])] <- 0,
               b = values(r)[is.na(values(r))] <- 0,
               c = raster::mask(r,is.na(r),maskvalue = 1, updatevalue = 0),
               d = reclassify(r, cbind(NA, NA, 0), right=FALSE),
               times = 100L)

## Unit: seconds
##  expr      min       lq     mean   median       uq      max neval cld
##     a 1.653149 1.898718 2.031415 1.971430 2.120584 3.352690   100 ab 
##     b 1.707620 1.938079 2.126679 2.089398 2.235046 3.033048   100  b 
##     c 4.362750 5.176214 5.413074 5.471538 5.660152 6.599903   100   c
##     d 1.424628 1.791048 1.935061 1.860629 2.044008 2.753409   100 a 

Option d seems to be a slightly efficient, but there isn't significant differences in this case. Maybe in bigger rasters could be.

  • I run into cannot allocate allocate vector of size #Gb with methods a and b. And it takes 4 minutes with reclassify using cbind(NA, NA, 0) vs. reclassify using cbind(NA, 0) that takes 2.3 minutes (I only ran it once). My raster has 7*1E8 cells. – user3386170 Jan 31 at 21:15
  • @user3386170 is an error derived of memory used for this process considering a big raster, use gc() before to apply those functions – aldo_tapia Jan 31 at 21:33
  • BTW, method d seems to be the fastest, so a and b are other good options... c is not the best way to replace NA's – aldo_tapia Jan 31 at 21:34
  • Even with gc(), I still cannot run the a and b methods. My dataset suggests that there is a significant difference between the methods (method d works). Just adding a tidbit of information for other users. – user3386170 Jan 31 at 22:30
1

I think you can use raster::calc() as perhaps a more memory efficient method. So, guessing that you have a single-layer raster you can do the following to replace NA values (used some test data here):

library(raster)

r <- raster(nrow=1E3, ncol=1E3)
values(r) <- NA


replaceNA <- function(x, na.rm, ...){ 
  if(is.na(x[1]))
    return(0)
  else
    return(x)
} 

r <- calc(r, fun = replaceNA)

I was able to run this replacement in a test raster layer with 1E8 NA pixels without running out of memory.

  • This version took 20.83649 mins instead of 2-4 minutes with reclassify with my dataset of 7*10E8. – user3386170 Jan 31 at 22:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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