【问题标题】:Find nearest 3 points to a given point in a dataframe在数据框中找到最接近给定点的 3 个点
【发布时间】:2021-09-21 14:44:19
【问题描述】:

我有一个带有经纬度的数据框,如下所示:

x    y     set 
61  -112   
63  -113 
61  -113
62  -111   point 
61  -111
64  -120

我想找到与set 列中标记为point 的点最近的三个点。然后,对于这三个最接近的点,我想将set 列修改为closest。像这样:

x    y     set 
61  -112   closest
65  -113 
62  -113   closest 
62  -111   point 
62  -111   closest
64  -120

我该怎么做?

【问题讨论】:

    标签: r raster sf sp


    【解决方案1】:
    dists <- geosphere::distHaversine(dat[dat$set=="point",c("y","x")], dat[,c("y","x")])
    dists
    # [1] 123339.4 151513.9 153862.4      0.0 111319.5 505814.4
    dat$set[dat$set != "point" & rank(dists) < 5] <- "closest"
    dat
    #    x    y     set
    # 1 61 -112 closest
    # 2 63 -113 closest
    # 3 61 -113        
    # 4 62 -111   point
    # 5 61 -111 closest
    # 6 64 -120        
    

    我们使用&lt; 5 的原因是自己的距离(pointpoint)将是最接近的(0),所以我们需要排名 2-4。这假设有一个"point";如果还有更多,您可能需要outer(生成matrix 的距离)并在填充$set 之前查看每一行。

    我是从标签推断纬度和经度,所以选择Haversine距离计算,因为它速度快,而且粗坐标的出现并不表明对亚毫米精度的要求(即Vincenty Ellipsoid公式) .如果需要,还有其他距离计算。

    【讨论】:

    • 谢谢!!我能问一下吗 - 我的理解是第一行代码在“点”和所有其他坐标之间创建了一个距离矩阵。但是,我无法理解第二行代码,究竟'rank'在这里做什么?
    • (1) This 返回一个向量,而不是矩阵,但如果我们有多个 "point" 点,那么它将是一个矩阵(并且需要更多处理) . (2)rank返回每个值的相对排名;由于此代码将“点”与自身进行比较,其距离为“0”,因此其排名始终为 1;下一个最近的排名为 2,下一个最近的排名为 3,依此类推。它实际上只是对它们进行排名,从最近的 (1) 到最远的(更大的数字)。
    【解决方案2】:

    这里首先是使用geosphere 的另一种方法(使用distm 制作距离矩阵),然后我将展示如何使用terra::nearby 方法(适用于长/纬度和平面坐标)。

    m <- matrix(c(61, -112, 63, -113, 61, -113, 62, -111, 61, -111, 64, -120), ncol=2, byrow=TRUE)
    # note that the order should be long/lat !!!
    m <- m[, 2:1]
    
    d <- geosphere::distm(m)
    diag(d) <- NA
    i <- order(d[4,])[1:3]
    i
    #[1] 5 1 2
    
    m[i,]
    #     [,1] [,2]
    #[1,] -111   61
    #[2,] -112   61
    #[3,] -113   63
    

    现在使用terra。下面获取所有点的最近 3 个邻居。

    library(terra)
    v <- vect(m, crs="+proj=lonlat")
    
    nearby(v, k=3)
    #  id k1 k2 k3
    #1  1  3  5  4
    #2  2  4  3  1
    #3  3  1  5  4
    #4  4  5  1  2
    #5  5  1  3  4
    #6  6  2  3  4
    

    使用 terra 版本 1.3.15(目前是开发版本)您也可以这样做

    nearby(v[4,], v, k=4)
    #     id k1 k2 k3 k4
    #[1,]  1  4  5  1  2
    

    k=4邻居为第一个就是点本身。

    要获取开发版本,请执行 install.packages('terra', repos='https://rspatial.r-universe.dev')

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多