我有两个数据框,一个是带有x和Y坐标的80万行,另一个数据框是带有X和Y坐标的70000行。我想知道R中的逻辑和代码,我想将第1帧的数据点与数据帧2中的最近点相关联。是否有任何标准包可以这样做?
我正在运行嵌套for循环。但这非常缓慢,因为它的迭代次数为80万* 70000次,非常耗时。
请帮忙 -
答案 0 :(得分:2)
我找到了一种使用data.table
库获得预期结果的更快方法:
library(data.table)
time0 <- Sys.time()
以下是一些随机数据:
df1 <- data.table(x = runif(8e5), y = runif(8e5))
df2 <- data.table(x = runif(7e4), y = runif(7e4))
假设(x,y)是标准坐标系中的坐标,您可以计算距离的平方如下:
dist <- function(a, b){
dt <- data.table((df2$x-a)^2+(df2$y-b)^2)
return(which.min(dt$V1))}
现在您可以将此功能应用于您的数据以获得预期结果:
results <- df1[, j = list(Closest = dist(x, y)), by = 1:nrow(df1)]
time1 <- Sys.time()
print(time1 - time0)
我花了大约30分钟才把结果放在慢速计算机上。
修改强>
根据要求,我使用sapply
或使用adply
包中的plyr
尝试了其他几种解决方案。我已经在较小的数据帧上测试了这些解决方案,以使其更快。
library(data.table)
library(plyr)
library(microbenchmark)
########################
## Test 1: data.table ##
########################
dt1 <- data.table(x = runif(1e4), y = runif(1e4))
dt2 <- data.table(x = runif(5e3), y = runif(5e3))
dist1 <- function(a, b){
dt <- data.table((dt2$x-a)^2+(dt2$y-b)^2)
return(which.min(dt$V1))}
results1 <- function() return(dt1[, j = list(Closest = dist1(x, y)), by = 1:nrow(dt1)])
###################
## Test 2: adply ##
###################
df1 <- data.frame(x = runif(1e4), y = runif(1e4))
df2 <- data.frame(x = runif(5e3), y = runif(5e3))
dist2 <- function(df){
dt <- data.table((df2$x-df$x)^2+(df2$y-df$y)^2)
return(which.min(dt$V1))}
results2 <- function() return(adply(.data = df1, .margins = 1, .fun = dist2))
####################
## Test 3: sapply ##
####################
df1 <- data.frame(x = runif(1e4), y = runif(1e4))
df2 <- data.frame(x = runif(5e3), y = runif(5e3))
dist2 <- function(df){
dt <- data.table((df2$x-df$x)^2+(df2$y-df$y)^2)
return(which.min(dt$V1))}
results3 <- function() return(sapply(1:nrow(df1), function(x) return(dist2(df1[x,]))))
microbenchmark(results1(), results2(), results3(), times = 20)
#Unit: seconds
# expr min lq mean median uq max neval
# results1() 4.046063 4.117177 4.401397 4.218234 4.538186 5.724824 20
# results2() 5.503518 5.679844 5.992497 5.886135 6.041192 7.283477 20
# results3() 4.718865 4.883286 5.131345 4.949300 5.231807 6.262914 20
第一种解决方案似乎明显快于其他解决方案。对于更大的数据集来说更是如此。