【问题标题】:Merging two data frames, both with coordinates based on the closest location合并两个数据框,两者的坐标都基于最近的位置
【发布时间】:2015-12-13 03:20:27
【问题描述】:

我有一个包含局部变量的大型数据框(约 130000 行)和另一个包含物种密度的大型数据框(约 7000 行)。两者都有 x 和 y 坐标,但这些坐标并不总是匹配。例如:

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

如果附近有一个点,我想在 df1 中添加一列,其中包含来自 df2 的密度 (Dens)。如果附近没有任何意义,我希望它显示为 NA。例如:

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

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    首先,让我们编写一个函数来为 df1 的单行找到 df2 中的最近点。这里我使用简单的笛卡尔距离(即(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)。

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2018-01-30
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多