Search code examples
rr-raster

If raster value NA search and extract the nearest non-NA pixel


On extracting values of a raster to points I find that I have several NA's, and rather than use a buffer and fun arguments of extract function, instead I'd like to extract the nearest non-NA Pixel to a point that overlaps NA.

I am using the basic extract function:

data.extr<-extract(loc.thr, data[,11:10])

Solution

  • Here's a solution without using the buffer. However, it calculates a distance map separately for each point in your dataset, so it might be ineffective if your dataset is large.

    set.seed(2)
    
    # create a 10x10 raster
    r <- raster(ncol=10,nrow=10, xmn=0, xmx=10, ymn=0,ymx=10)
    r[] <- 1:10
    r[sample(1:ncell(r), size = 25)] <- NA
    
    # plot the raster
    plot(r, axes=F, box=F)
    segments(x0 = 0, y0 = 0:10, x1 = 10, y1 = 0:10, lty=2)
    segments(y0 = 0, x0 = 0:10, y1 = 10, x1 = 0:10, lty=2)
    
    # create sample points and add them to the plot
    xy = data.frame(x=runif(10,1,10), y=runif(10,1,10))
    points(xy, pch=3)
    text(x = xy$x, y = xy$y, labels = as.character(1:nrow(xy)), pos=4, cex=0.7, xpd=NA)
    
    # use normal extract function to show that NAs are extracted for some points
    extracted = extract(x = r, y = xy)
    
    # then take the raster value with lowest distance to point AND non-NA value in the raster
    sampled = apply(X = xy, MARGIN = 1, FUN = function(xy) r@data@values[which.min(replace(distanceFromPoints(r, xy), is.na(r), NA))])
    
    # show output of both procedures
    print(data.frame(xy, extracted, sampled))
    
    #          x        y extracted sampled
    #1  5.398959 6.644767         6       6
    #2  2.343222 8.599861        NA       3
    #3  4.213563 3.563835         5       5
    #4  9.663796 7.005031        10      10
    #5  2.191348 2.354228        NA       2
    #6  1.093731 9.835551         2       2
    #7  2.481780 3.673097         3       3
    #8  8.291729 2.035757         9       9
    #9  8.819749 2.468808         9       9
    #10 5.628536 9.496376         6       6