有效地加入2个以上的data.tables

时间:2016-06-22 16:41:09

标签: r data.table data-manipulation

我想知道是否有一种内存有效的方式来加入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之外是否有一种已经被接受的方法可以做到这一点?

2 个答案:

答案 0 :(得分:5)

根据您的数据,以下是您可能拥有的其他一些选项。其他选项除了进行大量合并的明显路径之外,我的意思是:在循环中,使用Reduce或使用hadley' join_all / merge_all / {{1} }。

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

wrap_em_all_up

我假设这些表都由DFlist = list(df1,df2,df3,df4) bycols = key(DFlist[[1]]) 键入。

Stack。如果每个表中的新cols以某种方式相互关联并出现在每个表中的相同位置,那么请考虑只堆叠数据:

bycols

如果由于某种原因你真的想要宽格式的数据,你可以DFlong = rbindlist(DFlist, use.names = FALSE, idcol = TRUE)

dcast

尽管如此,Data.table和R最适合使用长格式数据。

复制cols。如果您知道dcast(DFlong, formula = sprintf("%s ~ .id", paste(bycols, collapse = "+")), value.var = setdiff(names(DFlong), c(bycols, ".id")) ) 在所有表中都采用了所有相同的值,那么只需复制:

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

答案 1 :(得分:0)

在dplyr:

由于您的试验都具有相同的名称(并且您已经清除了NA'),您可以绑定行并进行汇总。

library(dplyr)

DF <- bind_rows(df1,df2,df3,df4) %>%
    group_by(group) %>%
    summarise_each(funs(na.omit))

否则就会有简单的局部最小解决方案:虽然至少用这种方言编码可以节省你自己洋葱的几层。

DF <- 
    df1 %>% 
    full_join(df2) %>% 
    full_join(df3) %>% 
    full_join(df4) 

由于dplyr在C ++中运行而不是S,它应该更快。遗憾的是,我无法说出内存使用效率。

(类似情况见:R: Updating a data frame with another data frame's dplyr sol'n