使用合并连接的阈值

时间:2019-03-15 22:58:16

标签: r merge dplyr plyr

我对merge()函数(在基数R中)与join()plyr的{​​{1}}函数之间的区别的理解是,dplyr更快并且在处理“大型”数据集时效率更高。

是否有某种方法可以确定何时使用join()而不是join()的阈值,而无需使用启发式方法?

1 个答案:

答案 0 :(得分:3)

我敢肯定,当您从一种功能切换到另一种功能时,将很难找到一条“硬而快速”的规则。正如其他人提到的那样,R中提供了一组工具来帮助您评估性能。 object.sizesystem.time是两个这样的函数,分别查看内存使用率和性能时间。一种通用方法是直接在任意扩展的数据集上测量二者。下面是对此的一种尝试。我们将创建一个带有“ id”列和一组随机数值的数据框,以使数据框能够增长并测量其变化。正如您提到的inner_join,我将在这里使用dplyr。我们将时间计为“已过”时间。

library(tidyverse)

setseed(424)

#number of rows in a cycle
growth <- c(100,1000,10000,100000,1000000,5000000)

#empty lists
n <- 1
l1 <- c()
l2 <- c()

#test for inner join in dplyr
for(i in growth){
  x <- data.frame("id" = 1:i, "value" = rnorm(i,0,1))
  y <- data.frame("id" = 1:i, "value" = rnorm(i,0,1))

  test <- inner_join(x,y, by = c('id' = 'id'))
  l1[[n]] <- object.size(test)

  print(system.time(test <- inner_join(x,y, by = c('id' = 'id')))[3])
  l2[[n]] <- system.time(test <- inner_join(x,y, by = c('id' = 'id')))[3]

  n <- n+1

}

#empty lists
n <- 1
l3 <- c()
l4 <- c()

#test for merge
for(i in growth){
  x <- data.frame("id" = 1:i, "value" = rnorm(i,0,1))
  y <- data.frame("id" = 1:i, "value" = rnorm(i,0,1))

  test <- merge(x,y, by = c('id'))
  l3[[n]] <- object.size(test)
  # print(object.size(test))

  print(system.time(test <- merge(x,y, by = c('id')))[3])
  l4[[n]] <- system.time(test <- merge(x,y, by = c('id')))[3]

  n <- n+1

   }

#ploting output (some coercing may happen, so be it)
plot <- bind_rows(data.frame("size_bytes" = l3, "time_sec" = l4, "id" = "merge"), 
                  data.frame("size_bytes" = l1, "time_sec" = l2, "id" = "inner_join"))

plot$size_MB <- plot$size_bytes/1000000

ggplot(plot, aes(x = size_MB, y =time_sec, color = id)) + geom_line()

enter image description here

merge的性能似乎较差,但实际上大约在20MB左右。这是最后的决定吗?不会。但是这样的测试可以使您了解如何选择功能。