使用 st_distance 计算到特定点的最近距离

Calculating nearest distance to specific points using st_distance

我刚刚开始使用 R 和空间分析,所以我缺少很多基础知识!

我的数据包含学校地址。对于每所学校,我想计算到最近学校的距离。我的数据还包含有关 "special features" 所学校的信息。此变量 (sps) 编码为 1 ("with special features") 或 0 ("without special features")。我想计算从学校 "with special features" 到学校 "without special features" 的距离。这是我的数据的样子:

head(data01)
 id     lon      lat         sps
1 11725  6.932546 50.38269    0
2 11739  6.975160 50.48649    1
3 26883  6.987575 50.50857    0

到目前为止,我设法使用 st_distance 命令和以下代码计算到最近学校的距离。不幸的是,在使用此代码时,在某些情况下最近的学校都有 "special features"。我只想要从 1 -> 0 或 0 ->1 而不是 1->1!

的距离
my_sf <- st_as_sf(data01,
                  coords = c("lon", "lat"), # x, y (order matters)
                  crs = 4326)

dist.mat <- st_distance(my_sf) # Great Circle distance since in lat/lon
# Number within 1.5km: Subtract 1 to exclude the point itself
num.1500 <- apply(dist.mat, 1, function(x) {
  sum(x < 1500) - 1
})

# Calculate nearest distance
nn.dist <- apply(dist.mat, 1, function(x) {
  return(sort(x, partial = 2)[2])
})
# Get index for nearest distance
nn.index <- apply(dist.mat, 1, function(x) { order(x, decreasing=F)[2] })

n.data <- data01
colnames(n.data)[1] <- "neighbor"
colnames(n.data)[2:ncol(n.data)] <- 
  paste0("n.", colnames(n.data)[2:ncol(n.data)])
mydata2 <- data.frame(data01,
                      n.data[nn.index, ],
                      n.distance = nn.dist,
                      radius1500 = num.1500)
rownames(mydata2) <- seq(nrow(mydata2))

感谢帮助!!

干杯,k

编辑:

我的最终数据集应该是这样的:

 head(data01)                                                                                                            
 id     lon      lat        sps     dist
 11725  6.932546 50.38269    0    xxxx
 11739  6.975160 50.48649    1    xxxx
 26883  6.987575 50.50857    0    xxxx                                    

Dist 是到下一所学校的距离(0-> 1 或 1 -> 0)

二维欧几里德中两点之间距离的公式space(毕达哥拉斯):

sqrt( (x1-x2)**2 + (y1-y2)**2)

我们可以创建一个函数来计算它(您可以为 %>% 运算符调用 library(magrittr)):

dist = function(x1,x2,y1,y2){ 
   sqrt( (x1-x2)**2 + (y1-y2)**2) %>% return()
}

创建一个条件向量(不是强制性的,但它会使代码更具可读性。如果你知道如何,你可以直接内联条件)

condition = data01$sps %>% as.logical()

现在我们可以使用 lapply:

    lapply(1:nrow(data01), function(x){
                            if(condition[x]){
                                dist(data01$lon[!condition],
                                     data01$lon[x],
                                     data01$lat[!condition],
                                     data01$lat[x])
                            }else{
                                dist(data01$lon[condition],
                                     data01$lon[x],
                                     data01$lat[condition],
                                     data01$lat[x])
                            }
     }) 

该代码未经测试,但它应该会生成一个向量列表,每个向量应该给出到具有相反 sps 值的学校的距离。第一个向量将对应于所有其他向量到它的距离等...

此解决方案还保留了邻居的顺序,这样向量中​​的第一个距离将始终对应于对面 sps 组的第一个邻居。

关于如何处理向量列表的问题,当然你可以将其作为列表保存到名为distList:

的变量中
distList = lapply(....
                                                     )

您可以使用它轻松创建距离矩阵:

我们希望列和行的名称为 id,让我们首先将 ID 分成两个向量,其中一个具有 sps == 0,另一个具有 sps == 1 ,幸运的是,我们通过创建 condition 向量做了一个很好的赌注:

 Sps = data01$id[condition] %>% as.character
 Nsps = data01$id[!condition] %>% as.character

现在我们创建矩阵,

matrix(nrow = sum(condition),ncol = sum(!condition))

我们并不真的需要 distList 中的所有数据,因此我们只 select sps == 1sps == 0 中的数据,使用 0 更方便,我们通过将其转换为矩阵来覆盖我们的列表 :

distList = distList[!condition] %>% 
                                   do.call(what = "cbind")

现在我们将列和行命名为 school id(请注意,我们保持初始列表的顺序对我们有很大帮助):

rownames(distList) = Sps
colnames(distList) = Nsps

就是这样...现在您应该能够查询任何一对 id。例如: distList["11725","11739"] 应该给你学校之间的距离 11725 和学校 11739.

编辑 #2: 要查找关闭 sps == 0 学校到任何 sps == 1 学校,您可以执行以下操作:

 distList  = cbind(distList,
                   apply(distList,1,function(x){
                                            x[which.min(x)]
                                                })