繁体   English   中英

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

[英]Calculating nearest distance to specific points using st_distance

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

我的数据包含学校地址。 对于每所学校,我想计算到最近学校的距离。 我的数据还包含有关学校“特色”的信息。 此变量 (sps) 编码为 1(“具有特殊功能”)或 0(“无特殊功能”)。 我想计算从“有特色”的学校到“没有特色”的学校的距离。 这是我的数据的样子:

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 命令和以下代码计算到最近学校的距离。 不幸的是,在使用此代码时,在某些情况下最近的学校都有“特殊功能”。 我只想要从 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)

二维欧氏空间(毕达哥拉斯)中两点之间的距离公式:

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

我们可以创建一个 function 来计算它(您可以为%>%运算符调用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到 go 更方便,我们通过转换覆盖我们的列表它变成一个矩阵:

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM