![](/img/trans.png)
[英]Efficiently joining two data.tables in R (or SQL tables) on date ranges?
[英]Efficiently joining more than 2 data.tables
我想知道是否有一种内存有效的方式来加入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
键入的。
堆。 如果每个表中的新cols以某种方式彼此相关并且出现在每个表中的相同位置,那么考虑只是堆叠数据:
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
,则创建包含所有组合的主表并执行一系列merge-assigns:
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)]
}
在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:用另一个数据帧的dplyr sol'n 更新数据帧 )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.