使用data.table存储为列表元素的多个数据帧的完全外连接

时间:2014-10-31 17:46:35

标签: r merge dataframe data.table outer-join

我正在尝试使用data.table对作为列表元素存储的多个数据帧进行完全外连接。我已经使用merge_recurse()包的reshape函数成功完成了这项工作,但是对于更大的数据集来说它非常慢,我想通过使用data.table来加速合并。我不确定data.table处理具有多个数据帧的列表结构的最佳方法。我也不确定我是否在唯一键上正确编写了Reduce()函数,以便在多个数据帧上进行完全外连接。

这是一个小例子:

#Libraries
library("reshape")
library("data.table")

#Specify list of multiple dataframes
filelist <- list(data.frame(x=c(1,1,1,2,2,2,3,3,3), y=c(1,2,3,1,2,3,1,2,3), a=1:9),
                 data.frame(x=c(1,1,1,2,2,2,3,3,4), y=c(1,2,3,1,2,3,1,2,1), b=seq(from=0, by=5, length.out=9)),
                 data.frame(x=c(1,1,1,2,2,2,3,3,4), y=c(1,2,3,1,2,3,1,2,2), c=seq(from=0, by=10, length.out=9)))

#Merge with merge_recurse()
listMerged <- merge_recurse(filelist, by=c("x","y"))

#Attempt with data.table
ids <- lapply(filelist, function(x) x[,c("x","y")])
unique_keys <- unique(do.call("rbind", ids))
dt <- data.table(filelist)
setkey(dt, c("x","y")) #error here

Reduce(function(x, y) x[y[J(unique_keys)]], filelist)

这是我的预期输出:

> listMerged
   x y  a  b  c
1  1 1  1  0  0
2  1 2  2  5 10
3  1 3  3 10 20
4  2 1  4 15 30
5  2 2  5 20 40
6  2 3  6 25 50
7  3 1  7 30 60
8  3 2  8 35 70
9  3 3  9 NA NA
10 4 1 NA 40 NA
11 4 2 NA NA 80

以下是我的资源:

1 个答案:

答案 0 :(得分:3)

这对我有用:

library("reshape")
library("data.table")
##
filelist <- list(
  data.frame(
    x=c(1,1,1,2,2,2,3,3,3), 
    y=c(1,2,3,1,2,3,1,2,3), 
    a=1:9),
  data.frame(
    x=c(1,1,1,2,2,2,3,3,4), 
    y=c(1,2,3,1,2,3,1,2,1), 
    b=seq(from=0, by=5, length.out=9)),
  data.frame(
    x=c(1,1,1,2,2,2,3,3,4), 
    y=c(1,2,3,1,2,3,1,2,2), 
    c=seq(from=0, by=10, length.out=9)))
##
## I used copy so that this would
## not modify 'filelist'
dtList <- copy(filelist)
lapply(dtList,setDT)
lapply(dtList,function(x){
  setkeyv(x,cols=c("x","y"))
})
##
> Reduce(function(x,y){
  merge(x,y,all=T,allow.cartesian=T)
},dtList)
    x y  a  b  c
 1: 1 1  1  0  0
 2: 1 2  2  5 10
 3: 1 3  3 10 20
 4: 2 1  4 15 30
 5: 2 2  5 20 40
 6: 2 3  6 25 50
 7: 3 1  7 30 60
 8: 3 2  8 35 70
 9: 3 3  9 NA NA
10: 4 1 NA 40 NA
11: 4 2 NA NA 80

此外,我注意到您的代码中存在一些问题。 dt <- data.table(filelist)导致了

> dt
       filelist
1: <data.frame>
2: <data.frame>
3: <data.frame>

这很可能是您在上面指出的setkey(dt, c("x","y"))错误的原因。还有,这对你有用吗?

Reduce(function(x, y) x[y[J(unique_keys)]], filelist)

我只是好奇,因为我在尝试运行时遇到错误(使用dtList代替filelist

Error in eval(expr, envir, enclos) : could not find function "J"

我认为这与data.table版本1.8.8以来实施的更改有关,由@Arun在this answer解释。