10

I want to fill the NA values using the average values of the nearest neighbors:

r <- raster(matrix(1:16, nrow=8, ncol=8))
r[r==12] <- NA

1 Answer 1

19

You can fill in the NA values using the focal function with the na.rm argument set to FALSE and pad to TRUE.

library(raster)
  r <- raster(matrix(1:16, nrow=8, ncol=8))
  r[r==12] <- NA

Function to replace the focal value with the mean of a 3x3 window if NA. If the window size increases the index value [i] needs to change as well (eg., for a 5x5 window the index would be 13).

fill.na <- function(x, i=5) {
  if( is.na(x)[i] ) {
    return( round(mean(x, na.rm=TRUE),0) )
  } else {
    return( round(x[i],0) )
  }
}  

Pass the fill.na function to raster::focal and check results. The pad argument creates virtual rows/columns of NA values to keep the vector length constant along the edges of the raster. This is why we can always expect the fifth value of the vector to be the focal value in a 3x3 window thus, the index i=5 in the fill.na function.

r2 <- focal(r, w = matrix(1,3,3), fun = fill.na, 
            pad = TRUE, na.rm = FALSE )

as.matrix(r)
as.matrix(r2)
9
  • Thanks, I think this function takes the mean of the every 3 by 3 pixels and smooths the whole raster. I want to fill the gaps of the NA cell only.
    – Geo-sp
    Commented Feb 16, 2016 at 21:49
  • Yes, but you can write your own function that only replaces NA values. In this case na.rm would be FALSE. This is what the fun argument is for. Commented Feb 17, 2016 at 3:05
  • Thanks for the answer! do you know how I can apply this to a raster stack? I want to use that for each layer in of stack. Thanks!
    – Geo-sp
    Commented Feb 17, 2016 at 17:14
  • You will have to iterate through the stack using a for loop and an index and either replace each raster in the stack (eg., r[[1]] <- my.function(r[[1]]) ) or create a new stack with each filled raster. Commented Feb 17, 2016 at 18:56
  • 2
    If you want to do this in R it is likely that you will have to perform multiple passes in order to fill in all the gaps. However, this is not a very satisfying answer for filling areas that represent large data voids. An interpolation approach would certainly produce better results. Without coding a specific model in R, there are no out of the box solutions. There is an interpolation based nodata filling routine available in SAGA GIS. Commented Aug 11, 2017 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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