cbind来自多个data.tables的特定列有效

时间:2015-07-15 12:49:52

标签: r data.table cbind

我有一个data.tables列表,我需要cbind,但是,我只需要最后的X列。

我的数据结构如下:

DT.1 <- data.table(x=c(1,1), y = c("a","a"), v1 = c(1,2), v2 = c(3,4))
DT.2 <- data.table(x=c(1,1), y = c("a","a"), v3 = c(5,6))
DT.3 <- data.table(x=c(1,1), y = c("a","a"), v4 = c(7,8), v5 = c(9,10), v6 = c(11,12))

DT.list <- list(DT.1, DT.2, DT.3)
>DT.list
    [[1]]
   x y v1 v2
1: 1 a  1  3
2: 1 a  2  4

[[2]]
   x y v3
1: 1 a  5
2: 1 a  6

[[3]]
   x y v4 v5 v6
1: 1 a  7  9 11
2: 1 a  8 10 12

每个data.tables的列x和y都相同,但列的数量不同。输出不应包含重复的x和y列。它应该如下所示:

   x y v1 v2 v3 v4 v5 v6
1: 1 a  1  3  5  7  9 11
2: 1 a  2  4  6  8 10 12

我想避免使用循环。我能够使用do.call("cbind", DT.list)绑定data.tables,然后手动删除重复项,但是有没有一种方法可以首先创建重复项?此外,效率很重要,因为列表可能很长,数据量很大。表。

感谢

2 个答案:

答案 0 :(得分:2)

这是另一种方式:

Reduce(
  function(x,y){
    newcols = setdiff(names(y),names(x))
    x[,(newcols)] <- y[,newcols,with=FALSE]
    x
  }, 
  DT.list,
  init = copy(DT.list[[1]][,c("x","y"),with=FALSE])
)
#    x y v1 v2 v3 v4 v5 v6
# 1: 1 a  1  3  5  7  9 11
# 2: 1 a  2  4  6  8 10 12

这可以避免修改列表(如@ bgoldst&#39; s <- NULL赋值确实)或复制列表中的每个元素(我认为,lapply方法确实如此)。不过,我可能会在大多数实际应用中做<- NULL事。

答案 1 :(得分:0)

另一种选择是在数据表列表中使用[,,内的lapply索引功能选项,并排除“不需要的”列(在您的情况下为x和{{1} })。这样就不会创建重复的列。

y

A)使用字符向量指示要排除的列

# your given test data
DT.1 <- data.table(x=c(1,1), y = c("a","a"), v1 = c(1,2), v2 = c(3,4))
DT.2 <- data.table(x=c(1,1), y = c("a","a"), v3 = c(5,6))
DT.3 <- data.table(x=c(1,1), y = c("a","a"), v4 = c(7,8), v5 = c(9,10), v6 = c(11,12))
DT.list <- list(DT.1, DT.2, DT.3)

B)与上述相同,但直接在# cbind a list of subsetted data.tables exclude.col <- c("x","y") myDT <- do.call(cbind, lapply(DT.list, `[`,,!exclude.col, with = FALSE)) myDT ## v1 v2 v3 v4 v5 v6 ## 1: 1 3 5 7 9 11 ## 2: 2 4 6 8 10 12 # join x & y columns for final results cbind(DT.list[[1]][,.(x,y)], myDT) ## x y v1 v2 v3 v4 v5 v6 ## 1: 1 a 1 3 5 7 9 11 ## 2: 1 a 2 4 6 8 10 12

中使用字符向量
lapply

C)与上述相同,但全部在一行

myDT <- do.call(cbind, lapply(DT.list, `[`,,!c("x","y")))
myDT
##    v1 v2 v3 v4 v5 v6
## 1:  1  3  5  7  9 11
## 2:  2  4  6  8 10 12
# join x & y columns for final results
cbind(DT.list[[1]][,.(x,y)], myDT)
##    x y v1 v2 v3 v4 v5 v6
## 1: 1 a  1  3  5  7  9 11
## 2: 1 a  2  4  6  8 10 12