我想知道是否存在一种内存有效的方式来连接n个data.tables(或数据帧)。例如,如果我有以下4个data.tables:

df1 = data.table(group = c(1L,2L,3L),value = rnorm(3),key = "group")
df2 = data.table(group = c(2L,1L,3L),value2 = rnorm(3),key = "group")
df3 = data.table(group = c(3L,2L,1L),value3 = rnorm(3),key = "group")
df4 = data.table(group = c(1L,3L,2L),value4 = rnorm(3),key = "group")

我可以这样合并它们:
merge(df1,merge(df2,merge(df3,df4)))

但这似乎不是最佳解决方案。我可能潜在地需要合并许多data.tables。有没有一种方法可以在不将每个后续合并复制到内存的情况下概括以上内容?在data.table之外是否有一种已经被接受的方式来做到这一点?

最佳答案

根据您的数据,这里可能还有其他一些选项。除了进行大量合并的明显路径之外,其他选项是:在循环中,使用Reduce或hadley的join_all / merge_all / wrap_em_all_up

这些都是我使用过的方法,在我自己的工作中发现它们更快,但是我不打算尝试一般的基准测试。首先,进行一些设置:

DFlist = list(df1,df2,df3,df4)
bycols = key(DFlist[[1]])

我假设所有表都由bycols键控。

堆栈。 如果每个表中的新列都以某种方式相互关联并且出现在每个表中的相同位置,则考虑仅堆叠数据:
DFlong = rbindlist(DFlist, use.names = FALSE, idcol = TRUE)

如果出于某种原因您确实想要宽格式的数据,则可以dcast:
dcast(DFlong,
  formula = sprintf("%s ~ .id", paste(bycols, collapse = "+")),
  value.var = setdiff(names(DFlong), c(bycols, ".id"))
)

不过,Data.table和R最适合长格式数据。

复制cols。 如果您知道bycols在所有表中都具有相同的值,则只需复制:
DF = DFlist[[1]][, bycols, with=FALSE]
for (k in seq_along(DFlist)){
  newcols = setdiff(names(DFlist[[k]]), bycols)
  DF[, (newcols) := DFlist[[k]][, newcols, with=FALSE]]
}

合并分配。 如果某些表中可能缺少某些级别的bycols,则使用所有组合创建一个主表并执行一系列合并分配:
DF = unique(rbindlist(lapply(DFlist, `[`, j = bycols, with = FALSE)))
for (k in seq_along(DFlist)){
  newcols = setdiff(names(DFlist[[k]]), bycols)
  DF[DFlist[[k]], (newcols) := mget(newcols)]
}

10-06 13:59
查看更多