【问题标题】:Speed up merging many dataframes in R加快合并 R 中的许多数据帧
【发布时间】:2016-05-31 16:49:05
【问题描述】:

我目前正在使用以下代码来合并 >130 个数据帧,并且代码需要花费太多时间来运行(实际上我从未在如此大的数据集上完成,仅在子集上完成)。每个表有两列:unit(字符串)和counts(整数)。我正在按单位合并。

tables <- lapply(files, function(x) read.table(x), col.names=c("unit", x))))

MyMerge <- function(x, y){
  df <- merge(x, y, by="unit", all.x= TRUE, all.y= TRUE)
  return(df)
}

data <- Reduce(MyMerge, tables)

有什么方法可以轻松加快速度吗?每个表/数据框分别有大约 500,000 行,其中许多行是该表独有的。因此,通过合并多个表,可以快速获得合并数据帧的行数到数百万..

最后,我将从我的大合并表中删除汇总计数过低的行,但我不想在合并期间这样做,因为那时我的文件顺序很重要..

【问题讨论】:

  • 查看stackoverflow.com/questions/1299871/… 的一些data.table 解决方案(outer joins)。这可能会更快。
  • 谢谢@coffeinjunky。不幸的是,我尝试了基于上述线程的 dplyr 包,但在我的情况下速度较慢。
  • @coffeinjunky 对于较小的数据集之一,我能够从 77 秒缩短到 66 秒。不神奇,但绝对有帮助:)
  • 是否需要存储每个数字来自哪个表的结果?还是要在最后汇总?

标签: r performance dataframe merge


【解决方案1】:

这里是一个小比较,首先是一个相当小的数据集,然后是一个更大的数据集:

library(data.table)
library(plyr)
library(dplyr)
library(microbenchmark)

# sample size: 
n = 4e3

# create some data.frames:
df_list <- lapply(1:100, function(x) {
  out <- data.frame(id = c(1:n), 
                    type = sample(c("coffee", "americano", "espresso"),n, replace=T))
  names(out)[2] <- paste0(names(out)[2], x)
  out})

# transform dfs into data.tables:
dt_list <- lapply(df_list, function(x) {
  out <- as.data.table(x)
  setkey(out, "id")
  out
})

# set options to outer join for all methods:    
mymerge <- function(...) base::merge(..., by="id", all=T)
mydplyr <- function(...) dplyr::full_join(..., by="id")
myplyr <- function(...) plyr::join(..., by="id", type="full")
mydt <- function(...) merge(..., by="id", all=T)

# Compare:
microbenchmark(base = Reduce(mymerge, df_list),
               dplyr= Reduce(mydplyr, df_list),
               plyr = Reduce(myplyr, df_list),
               dt = Reduce(mydt, dt_list), times=50)

这给出了以下结果:

Unit: milliseconds
  expr       min        lq      mean    median        uq       max neval  cld
  base  944.0048  956.9049  974.8875  962.9884  977.6824 1221.5301    50   c 
 dplyr  316.5211  322.2476  329.6281  326.9907  332.6721  381.6222    50 a   
  plyr 2682.9981 2754.3139 2788.7470 2773.8958 2812.5717 3003.2481    50    d
    dt  537.2613  554.3957  570.8851  560.5323  572.5592  757.6631    50  b  

我们可以看到两位选手分别是dplyrdata.table。将样本大小更改为 5e5 会产生以下比较,表明确实 data.table 占主导地位。请注意,我在@BenBolker 的建议之后添加了这部分。

microbenchmark(dplyr= Reduce(mydplyr, df_list),
               dt = Reduce(mydt, dt_list), times=50)

Unit: seconds
expr      min       lq     mean   median       uq      max neval cld
dplyr 34.48993 34.85559 35.29132 35.11741 35.66051 36.66748    50   b
   dt 10.89544 11.32318 11.61326 11.54414 11.87338 12.77235    50  a 

【讨论】:

  • 也许data.table 占主导地位(OP 希望合并具有 5e5 行而不是 4e3 行的帧...)...?
  • 你是对的@BenBolker,我的样本量太小了。更新了我的解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2021-10-04
  • 2018-06-29
  • 1970-01-01
  • 2013-01-03
相关资源
最近更新 更多