`j`不会为每个组评估相同的列数

时间:2013-09-26 16:13:56

标签: r data.table

我正在尝试使用data.table,其中j函数可以并且将在每次调用时返回不同数量的列。我希望它的行为类似于rbind.fill,因为它会使用NA填充所有缺少的列。

fetch <- function(by) {
    if(by == 1)
        data.table(A=c("a"), B=c("b"))
    else
        data.table(B=c("b"))
}
data <- data.table(id=c(1,2))
result <- data[, fetch(.BY), by=id]

在这种情况下,“结果”最终可能会有两列; A和B.'A'和'B'作为第一次调用'fetch'的一部分返回,只有'B'作为第二次调用返回。我希望示例代码返回此结果。

  id    A B
1  1    a b
2  2 <NA> b

不幸的是,在运行时我遇到了这个错误。

Error in `[.data.table`(data, , fetch(.BY, .SD), by = id) : 
j doesn't evaluate to the same number of columns for each group

我可以使用plyr执行此操作,如下所示,但在我的真实世界中,用例plyr的内存不足。对fetch的每次调用发生得相当快,但是当plyr尝试将所有数据合并在一起时发生内存崩溃。我想看看data.table是否可能为我解决这个问题。

result <- ddply(data, "id", fetch)

任何想法都赞赏。

3 个答案:

答案 0 :(得分:6)

DWin的方法很好。或者您可以返回list列,其中每个单元格本身就是一个向量。这通常是处理可变长度向量的更好方法。

DT = data.table(A=rep(1:3,1:3),B=1:6)
DT
   A B
1: 1 1
2: 2 2
3: 2 3
4: 3 4
5: 3 5
6: 3 6
ans = DT[, list(list(B)), by=A]
ans
   A    V1
1: 1     1
2: 2   2,3     # V1 is a list column. These aren't strings, the
3: 3 4,5,6     # vectors just display with commas

ans$V1[3]
[[1]]
[1] 4 5 6

ans$V1[[3]]
[1] 4 5 6

ans[,sapply(V1,length)]
[1] 1 2 3

因此,在您的示例中,您可以按如下方式使用它:

library(plyr)

rbind.fill(data[, list(list(fetch(.BY))), by = id]$V1)
#     A B
#1    a b
#2 <NA> b

或者,只需返回符合条件的列表:

allcols = c("A","B")
fetch <- function(by) {
    if(by == 1)
        list(A=c("a"), B=c("b"))[allcols]
    else
        list(B=c("b"))[allcols]
}

答案 1 :(得分:4)

这是两种方法。第一个大致遵循你的策略:

data[,list(A=if(.BY==1) 'a' else NA_character_,B='b'), by=id]

第二步分两步完成:

DT <- copy(data)[,`:=`(A=NA_character_,B='b')][id==1,A:='a']

使用by来检查单个值似乎很浪费(可能是计算上的,但也就清晰度而言);当然,可能是你的应用程序不是那样的。

答案 2 :(得分:2)

尝试

            data.table(A=NA, B=c("b"))

@NickAllen:我不肯从评论中了解你是否了解我的建议。 (我用手机发帖限制了我的剪贴功能,我怀疑我的妻子告诉我不要给S0发短信,否则她会和我离婚。)我的意思是:

fetch <- function(by) {
    if(by == 1)
        data.table(A=c("a"), B=c("b"))
    else
        data.table(A=NA, B=c("b"))
}
data <- data.table(id=c(1,2))
result <- data[, fetch(.BY), by=id]