R中的空间最近邻分配

afo*_*ssa 5 gis r spatial nearest-neighbor

我正在开展一项研究,试图根据特定个人的地址将颗粒物暴露情况分配给他们。我有两个带有经度和纬度坐标的数据集。一个 if 用于个人,一个 if 用于下午暴露块。我想根据最接近的块为每个主题分配一个下午曝光块。

library(sp)
library(raster)
library(tidyverse)

#subject level data
subjectID<-c("A1","A2","A3","A4")

subjects<-data.frame(tribble(
~lon,~lat,
-70.9821391,    42.3769511,
-61.8668537,    45.5267133,
-70.9344039,    41.6220337,
-70.7283830,    41.7123494
))

row.names(subjects)<-subjectID

#PM Block Locations 
blockID<-c("B1","B2","B3","B4","B5")

blocks<-data.frame(tribble(
~lon,~lat,
-70.9824591,    42.3769451,
-61.8664537,    45.5267453,
-70.9344539,    41.6220457,
-70.7284530,    41.7123454,
-70.7284430,    41.7193454
))

row.names(blocks)<-blockID

#Creating distance matrix
dis_matrix<-pointDistance(blocks,subjects,lonlat = TRUE)

###The above code doesnt preserve the row names. Is there a way to to do 
that?

###I'm unsure about the below code
colnames(dis_matrix)<-row.names(subjects)
row.names(dis_matrix)<-row.names(blocks)

dis_data<-data.frame(dis_matrix)

###Finding nearst neighbor and coercing to usable format 
getname <-function(x) {
row.names(dis_data[which.min(x),])
}

nn<-data.frame(lapply(dis_data,getname)) %>% 
gather(key=subject,value=neighbor)
Run Code Online (Sandbox Code Playgroud)

这段代码给了我有意义的输出,但我不确定有效性和效率。任何有关如何改进和修复此代码的建议都将受到赞赏。我还收到错误消息:

Warning message:
attributes are not identical across measure variables;
they will be dropped 
Run Code Online (Sandbox Code Playgroud)

我无法确定其起源。

谢谢参观!

Rob*_*ans 5

以下是一些示例数据,说明了如何使用pointDistance

library(raster)

#subject level data
subjectID <- c("A1","A2","A3","A4")
subxy <- matrix(c(-65, 42, -60, 4.5, -70, 20, -75, 41 ), ncol=2, byrow=TRUE)
#PM Block Locations 
blockID <- c("B1","B2","B3","B4","B5")
blockxy <- matrix(c(-68, 22, -61, 25, -70, 31, -65, 11,-63, 21), ncol=2, byrow=TRUE)

# distance of all subxy to all blockxy points
d <- pointDistance(subxy, blockxy, lonlat=TRUE)

# get the blockxy record nearest to each subxy record
r <- apply(d, 1, which.min)
r
#[1] 3 4 1 3
Run Code Online (Sandbox Code Playgroud)

所以这些对是:

p <- data.frame(subject=subjectID, block=blockID[r])
p

#  subject block
#1      A1    B3
#2      A2    B4
#3      A3    B1
#4      A4    B3
Run Code Online (Sandbox Code Playgroud)

说明它的工作原理:

plot(rbind(blockxy, subxy), ylim=c(0,45), xlab='longitude', ylab='latitude')
points(blockxy, col="red", pch=20, cex=2)
points(subxy, col="blue", pch=20, cex=2)
text(subxy, subjectID, pos=1)
text(blockxy, blockID, pos=1)
for (i in 1:nrow(subxy)) {
    arrows(subxy[i,1], subxy[i,2], blockxy[r[i],1], blockxy[r[i],2])
}
Run Code Online (Sandbox Code Playgroud)

箭头图