从不同长度的不同数据集中查找纬度和经度的最近点

时间:2014-12-12 11:17:17

标签: r

我有两个不同电台的数据集。数据基本上是具有坐标,经度和纬度的数据框架。给定第一个数据集(反之亦然),我想找到其他数据集中每个站的最近站。我的主要问题是坐标没有排序,数据集的长度不同。例如,第一个包含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,第一点,第二个数据集中最近的站点是什么?有什么想法??

非常感谢。

5 个答案:

答案 0 :(得分:15)

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

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

答案 1 :(得分:4)

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

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)

或者,如果你想让站点距离最近点而不是最小距离改变min,那么.min in dist2()

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

获得该站的lat-lon

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

答案 2 :(得分:3)

如果您有非常大的数据集,使用距离命令可能很麻烦,因为它必须计算参考数据中每个点的替代数据中所有点的距离。 &#39; ann&#39;来自&#39; yaImpute&#39; package是一个非常快速的近似最近邻程序,适用于大距离计算。然而,它会返回许多最近的&#34;你想要的记录(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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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