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

Nic*_*len 7 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]
Run Code Online (Sandbox Code Playgroud)

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

  id    A B
1  1    a b
2  2 <NA> b
Run Code Online (Sandbox Code Playgroud)

不幸的是,运行时我得到了这个错误.

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

我可以这样做plyr,但在我的现实世界中,用例plyr内存不足.每次调用fetch都会很快发生,但是当plyr尝试将所有数据合并在一起时会发生内存崩溃.我试图看看是否data.table可以为我解决这个问题.

result <- ddply(data, "id", fetch)
Run Code Online (Sandbox Code Playgroud)

任何想法都赞赏.

Mat*_*wle 7

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
Run Code Online (Sandbox Code Playgroud)

所以在你的例子中你可以使用如下:

library(plyr)

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

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

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

  • @eddi如果后续的`j`返回之前看不到的列名,我想它可以动态地通过引用将该列添加到结果中(为前面的组填充NA).也许这是可行的. (2认同)

42-*_*42- 3

尝试

            data.table(A=NA, B=c("b"))
Run Code Online (Sandbox Code Playgroud)

@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]
Run Code Online (Sandbox Code Playgroud)

  • @NickAllen 将表演者放在“列表”列中怎么样,就像我的回答一样?或者保持长格式而不是宽格式。或者,如果您事先知道将返回的最多列,则使用类似于我的答案末尾的内容使其常规。 (2认同)