【问题标题】:Calculating nearest distance to specific points using st_distance使用 st_distance 计算到特定点的最近距离
【发布时间】:2020-06-10 08:11:25
【问题描述】:

我刚刚开始使用 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)

【问题讨论】:

    标签: r geospatial distance sf


    【解决方案1】:

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

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

    我们可以创建一个函数来计算它(您可以调用library(magrittr) 来获取%&gt;% 运算符):

    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里面的所有数据,所以我们只选择sps == 1或者sps == 0里面的数据,用0比较方便,我们通过将其转换为矩阵来覆盖我们的列表 :

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

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

    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)]
                                                    })
    

    【讨论】:

    • 嘿@dvd280,感谢您的回复!该代码有效,但我不确定计算后如何继续。如何附加到相应学校的距离?最后,我想要一个变量(例如dist)与下一所学校的距离
    • @Bigott 我编辑了我的问题,以便为您提供有关如何使用我的解决方案的更多指导,希望一切正常。
    • 又工作了:)!但是我为了进一步使用距离,我需要一个看起来像这样的数据集(我编辑了我的主要帖子,所以你可以看到!)
    • @Bigott xxxx 是什么意思?这是从对面的sps到最近学校的距离吗?
    • 是的;可能我表达的不是很清楚:我想计算从有特色的学校(sps=1)到下一所学校的距离。在大多数情况下,这是一所没有特殊功能的学校(sps=0)。但是在某些地区,下一个学校也有特殊的功能(sps=1)。在这种情况下,我想在没有特殊功能的情况下与下一所学校保持距离(sps=0)。非常感谢您抽出宝贵时间!!
    猜你喜欢
    • 2019-03-23
    • 1970-01-01
    • 2021-03-31
    • 2014-07-21
    • 2021-10-16
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多