我有一个包含局部变量的大数据框(~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"))
Run Code Online (Sandbox Code Playgroud)
和:
df2 <- data.frame(X = c(2,4,6), Y = c(5,9,7), Dens = c(12, 17, 10))
Run Code Online (Sandbox Code Playgroud)
如果附近有一个点,我想向 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
Run Code Online (Sandbox Code Playgroud)
首先,我们编写一个函数来查找 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)))
}
Run Code Online (Sandbox Code Playgroud)
一旦你有了这个,你只需要将lapply它添加到每一行,并将其添加到你的第一个数据中:
z <- cbind(df1, do.call(rbind, lapply(1:nrow(df1), function(x) mydist(df1[x,]))))
Run Code Online (Sandbox Code Playgroud)
对于您的测试数据,输出如下所示:
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
Run Code Online (Sandbox Code Playgroud)
然后,您可以执行以下操作来过滤掉超出阈值的内容:
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
Run Code Online (Sandbox Code Playgroud)
你的实际数据非常大(同样大小的模拟数据集在我的电脑上大约需要10分钟)。如果可能的话merge,您应该只在那些不完全匹配的情况下运行此命令(请参阅dplyr::anti_join)。
| 归档时间: |
|
| 查看次数: |
2135 次 |
| 最近记录: |