【问题标题】:Find nearest points of latitude and longitude from different data sets with different length从不同长度的不同数据集中查找最近的经纬度点
【发布时间】:2014-12-12 11:17:16
【问题描述】:

我有两个不同站点的数据集。数据基本上是带有坐标、经度和纬度的数据帧。给定第一个数据集(反之亦然),我想为另一个数据集中的每个站点找到最近的站点。我的主要问题是坐标没有排序并且数据集有不同的长度。例如,第一个包含 2228 个站点,第二个包含 1782 个。所以,我不知道如何处理。 我知道函数 rdist.earth 并尝试使用它。这是一个简短的示例:

      #First data set of stations
        set1 <- structure(list(lon = c(13.671114, 12.866947, 15.94223, 11.099736,  
         12.958342, 14.203892, 11.86389, 16.526674, 16.193064, 17.071392
        ), lat = c(48.39167, 48.148056, 48.721111, 47.189167, 47.054443, 
         47.129166, 47.306667, 47.84, 47.304167, 48.109444)), .Names = c("lon", 
       "lat"), row.names = c(NA, 10L), class = "data.frame")

      #Second data set
      set2 <- structure(list(lon = structure(c(14.4829998016357, 32.4000015258789, 
      -8.66600036621094, 15.4670000076294, 18.9160003662109, 19.0160007476807, 
      31.0990009307861, 14.3660001754761, 9.59899997711182, 11.0830001831055
       ), .Dim = 10L), lat = structure(c(35.8499984741211, 34.75, 70.9329986572266, 
      78.25, 69.6829986572266, 74.515998840332, 70.3659973144531, 67.265998840332, 
       63.6990013122559, 60.1990013122559), .Dim = 10L)), .Names = c("lon", 
      "lat"), row.names = c(NA, 10L), class = "data.frame")
       #computing distance
       dd<- rdist.earth(set1,set2,miles=FALSE)

现在我有了矩阵 dd 和距离……但我不知道如何找到每个点的信息。我的意思是,例如,从数据集 1 中,第一个点,第二个数据集中最近的站点是什么?有什么想法吗??

非常感谢。

【问题讨论】:

标签: r


【解决方案1】:

这是另一种可能的解决方案:

library(rgeos)
set1sp <- SpatialPoints(set1)
set2sp <- SpatialPoints(set2)
set1$nearest_in_set2 <- apply(gDistance(set1sp, set2sp, byid=TRUE), 1, which.min)

head(set1)
       lon      lat nearest_in_set2
## 1 13.67111 48.39167              10
## 2 12.86695 48.14806              10
## 3 15.94223 48.72111              10
## 4 11.09974 47.18917               1
## 5 12.95834 47.05444               1
## 6 14.20389 47.12917               1

【讨论】:

  • 我有同样的问题,但这个解决方案对我不起作用。我收到错误消息:$&lt;-.data.frame(*tmp*,nearest_in_OBS, value = c(1 = 1L, 中的错误:替换有 12375 行,数据有 504 上述解决方案是否不适用于不同长度的数据集?
【解决方案2】:

您可以使用一系列应用命令来执行此操作。请注意,函数中的 x 和 y 指的是 set1 和 set2 而不是 lat lon 坐标 - lat lon 坐标指定为 p1 和 p2。 [注意:已编辑以更正计算中 set1 和 set2 的顺序 - 该顺序确定您计算的 set2 中的值是否最接近 set 1 中的每个值,反之亦然)

distp1p2 <- function(p1,p2) {
    dst <- sqrt((p1[1]-p2[1])^2+(p1[2]-p2[2])^2)
    return(dst)
}

dist2 <- function(y) min(apply(set2, 1, function(x) min(distp1p2(x,y))))

apply(set1, 1, dist2)

或者,如果您希望车站具有最近点而不是最小距离,请将 dist2() 中的 min 更改为 which.min

dist2b <- function(y) which.min(apply(set2, 1, function(x) min(distp1p2(x,y))))
apply(set1, 1, dist2b)

并获得该站的经纬度

set2[apply(set1, 1, dist2b),]

【讨论】:

    【解决方案3】:

    如果您有非常大的数据集,使用距离命令可能会很麻烦,因为它必须为参考数据中的每个点计算到替代数据中所有点的距离。 'yaImpute' 包中的 'ann' 命令是一个非常快速的近似最近邻例程,适用于大距离计算。它将返回您想要的许多“最近”记录(k 的值)以及到每个记录的距离。

    注意:尽管是近似最近的邻居,但在重复运行相同数据时,结果是稳定的。它不包括随机选择的点或任何东西。请参阅文档。

    FWIW,我真的不是在开玩笑。我用它来查找两个矩阵的 knn 距离,每个矩阵都有数百万个点。为此制作一个距离矩阵或逐行迭代地执行它要么不可行,要么非常缓慢。

    快速示例:

    # Hypothetical coordinate data
    set.seed(2187); foo1 <- round(abs(data.frame(x=runif(5), y=runif(5))*100))
    set.seed(2187); foo2 <- round(abs(data.frame(x=runif(10), y=runif(10))*100))
    foo1; foo2
    
    # the 'ann' command from the 'yaImpute' package
    install.packages("yaImpute")
    library(yaImpute)
    
    # Approximate nearest-neighbour search, reporting 2 nearest points (k=2)
    # This command finds the 3 nearest points in foo2 for each point in foo1
    # In the output:
    #   The first k columns are the row numbers of the points
    #   The next k columns (k+1:2k) are the *squared* euclidean distances
    knn.out <- ann(as.matrix(foo2), as.matrix(foo1), k=3)
    knn.out$knnIndexDist
    
         [,1] [,2] [,3] [,4] [,5] [,6]
    [1,]    1    5    4  729 1658 2213
    [2,]    2    3    7   16  100 1025
    [3,]    9    7    5   40   81  740
    [4,]    4    1    6   16  580  673
    [5,]    5    7    9    0  677  980
    

    https://cran.r-project.org/web/packages/yaImpute/index.html

    【讨论】:

    • 232 行参考和 14,124 行替代的系统时间比较:1) 应用方法 = 3.89 秒 2) 安方法 = 0.02 秒
    【解决方案4】:

    我不完全知道你想要什么,但也许这会给你一些提示
    如果您想获取每列的最小值

      dd <- as.data.frame(dd)
      sapply(dd, min)
      paste(rownames(dd), ":", apply(dd,2,which.min)) #or
    

    【讨论】:

      【解决方案5】:

      s2 包中的函数 s2_closest_feature() 从不同的数据集中找到最近的点。

      例如,使用您的数据:

      library(s2)
      set1_s2 <- s2_lnglat(set1$lon, set1$lat)
      set2_s2 <- s2_lnglat(set2$lon, set2$lat)
      set1$closest <- s2_closest_feature(set1_s2, set2_s2)
      set1
      #>         lon      lat closest
      #> 1  13.67111 48.39167      10
      #> 2  12.86695 48.14806      10
      #> 3  15.94223 48.72111      10
      #> 4  11.09974 47.18917       1
      #> 5  12.95834 47.05444       1
      #> 6  14.20389 47.12917       1
      #> 7  11.86389 47.30667       1
      #> 8  16.52667 47.84000       1
      #> 9  16.19306 47.30417       1
      #> 10 17.07139 48.10944       1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多