Friday 18 November 2016

Distance to nearest point for every point same SpatialPointsDataFrame in R


I have a SpatialPointsDataFrame that I'm working with in R. I want to add a new vector to the dataframe that contains, for every point, the distance to the nearest other point in the SpatialPointsDataFrame. I've looked at knearneigh in the spdep package as well as spDistsN1 and spDists in the sp package, but neither of those give me exactly what I want. To be clear, all of these points are in ONE SpatialPointsDataFrame.



Answer



There are several ways you can tackle this in R, including spDists in sp and gDistance in rgeos. An efficient way, that is expandable to multiple kNN ID's and distances, is to use spdep.


require(spdep)
data(meuse)

coordinates(meuse) = ~x+y
meuse <- meuse[1:10,]
meuse@data$IDS <- 1:10

# Neighbor row indices and add neighbor attribute ID's
( knn1 <- knearneigh(coordinates(meuse), k=1)$nn )
meuse@data$nnID <- meuse@data[knn1,]$IDS

# Add neighbor distance
meuse.dist <- dnearneigh(coordinates(meuse), 0, 1000)

dist.list <- nbdists(meuse.dist, coordinates(meuse))
meuse@data$nnDist <- unlist(lapply(dist.list, FUN=function(x) min(x)))

meuse@data

Another, very fast way, is the nabor package. Since distance is returned along with the neighbor ID you can add both simultaneously. The nabor::knn function does return self-neighbors so, you have to set k to >= 2 and drop the first column in the resulting matrices. One advantage here is that, as long as the matrices are the same dimension, you can get neighbors from the same or independent data.


library(nabor)
library(sp)

data(meuse)

coordinates(meuse) = ~x+y
meuse <- meuse[1:10,]
meuse@data$IDS <- 1:10

knn1 <- knn( coordinates(meuse), coordinates(meuse), k=2)
( knn1 <- data.frame( knn=knn1[[1]][,2], knn.dist=knn1[[2]][,2] ) )

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...