合并两个数据框,两者都具有基于最近位置的坐标

时间:2015-12-12 16:24:13

标签: r dataframe

我有一个包含局部变量的大型数据帧(~130000行)和一个包含物种密度的其他大型数据帧(~7000行)。两者都有x和y坐标,但这些坐标并不总是匹配。 e.g:

df1 <- data.frame(X = c(2,4,1,2,5), Y = c(6,7,8,9,8), V1 = c("A", "B", "C", "D", "E"), V2 = c("G", "H", "I", "J", "K"))

df2 <- data.frame(X = c(2,4,6), Y = c(5,9,7), Dens = c(12, 17, 10))

如果有合理的近点,我想在df2中添加一个包含密度(Dens)的df1。如果附近没有任何一点,我希望它显示为NA。 e.g:

X Y   V1   V2    Dens
2 6   A    G      12
4 7   B    H      NA     
1 8   C    I      17
2 9   D    J      NA
5 8   E    K      10

1 个答案:

答案 0 :(得分:2)

首先,让我们编写一个函数来找到df2中单个df1的最近点。在这里,我使用简单的笛卡尔距离(即(x1 - x2)^2 + (y1 - y2)^2)。如果您有纬度/经度,您可能希望将其更改为更好的公式:

mydist <- function(row){
  dists <- (row[["X"]] - df2$X)^2 + (row[["Y"]]- df2$Y)^2
  return(cbind(df2[which.min(dists),], distance = min(dists)))
}

完成此操作后,您只需将lapply添加到每一行,然后将其添加到您的第一个数据中:

z <- cbind(df1, do.call(rbind, lapply(1:nrow(df1), function(x) mydist(df1[x,])))) 

对于测试数据,输出如下:

   X Y V1 V2 X Y Dens distance
1  2 6  A  G 2 5   12        1
2  4 7  B  H 4 9   17        4
3  1 8  C  I 2 5   12       10
21 2 9  D  J 4 9   17        4
22 5 8  E  K 4 9   17        2

然后,您可以执行以下操作来过滤掉超过阈值的内容:

threshold <- 5
z$Dens[z$distance > threshold] <- NA

   X Y V1 V2 X Y Dens distance
1  2 6  A  G 2 5   12        1
2  4 7  B  H 4 9   17        4
3  1 8  C  I 2 5   NA       10
21 2 9  D  J 4 9   17        4
22 5 8  E  K 4 9   17        2

您的实际数据非常大(我的计算机上相同大小的模拟数据集大约需要10分钟)。如果可能,您应该merge,然后只对那些不完全匹配的人执行此操作(请参阅dplyr::anti_join)。