R function to match closest points to second point set?
On Mon, 28 Nov 2005, Rick Reeves wrote:
Hello all: I checked inside most of the R spatial analysis packages, without success, so I'll ask the list: I have a set of data collection points georeferenced with lat/long coordinates. The task is to find the closest (in lat/long) matching point in a second set of points (polygon centroids, that I created with R get.Pcent() function). both point sets are stored in data frames, I would like to record the index of the matching point as a new column on the first data frame. Is there an existing R function or package that would support this, or get close? Thanks for any assistance.
Using the Census 2000 county shapefiles for North and South Carolina as an example:
library(maptools)
nc <- readShapePoly("co37_d00.shp",
+ proj4string=CRS("+proj=longlat datum=NAD83"))
sc <- readShapePoly("co45_d00.shp",
+ proj4string=CRS("+proj=longlat datum=NAD83"))
nc_cents <- t(sapply(slot(nc, "polygons"), function(x) slot(x,
+ "labpt")))
nc_n <- nrow(nc_cents) sc_cents <- t(sapply(slot(sc, "polygons"), function(x) slot(x,
+ "labpt")))
sc_n <- nrow(sc_cents)
res <- vector(mode="integer", length=nc_n)
for (i in 1:nc_n) {
+ dists <- spDistsN1(sc_cents, nc_cents[i,], longlat=TRUE) + res[i] <- which.min(dists) + }
bbox(sc) bbox(nc) plot(nc, ylim=c(32,36.6), axes=TRUE) plot(sc, add=TRUE, border="blue") for (i in 1:nc_n) segments(nc_cents[i,1], nc_cents[i,2],
+ sc_cents[res[i],1], sc_cents[res[i],2]) The results in km are in the dists matrix, the spDistsN1() function is in the sp package which maptools loads. Since you've got your centroids already, you don't need the extra stuff, so spDistsN1() in a loop will get you there, I needed it for the example. Add the res vector to your data frame. Roger
Thanks, Rick R
Roger Bivand Economic Geography Section, Department of Economics, Norwegian School of Economics and Business Administration, Helleveien 30, N-5045 Bergen, Norway. voice: +47 55 95 93 55; fax +47 55 95 95 43 e-mail: Roger.Bivand at nhh.no