R `j`dons';t为每组计算相同数量的列

R `j`dons';t为每组计算相同数量的列,r,data.table,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 <- d

我正在尝试使用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]
我可以用
plyr
完成这项工作,如下所示,但在我的实际用例中
plyr
内存不足。每次调用
fetch
都会很快发生,但是当
plyr
尝试将所有数据合并回一起时,内存崩溃就会发生。我正在尝试查看
data.table
是否可以为我解决此问题

result <- ddply(data, "id", fetch)
结果尝试

@尼卡伦:从评论中我不确定你是否理解我的建议。(我用手机发帖,这限制了我的剪贴功能,我怀疑我妻子是在告诉我不要再发短信给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]

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

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
库(plyr)
rbind.fill(数据[,列表(列表(fetch(.BY))),BY=id]$V1)
#A B
#1 a b
#2 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]
}
allcols=c(“A”、“B”)

fetch这里有两种方法。第一种方法大致遵循您的策略:

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']

DT我想这不是我想要的。我试图对一个数据表应用一个函数,这将导致另一个数据表。那么我一定问错了问题。:)我不想手动创建这样的数据表。这只是我想做的一个例子。对不起,我不清楚。如果我描述一下我的真实用例,也许会有所帮助。上面的My fetch()函数发出一个web服务调用,该调用提取一些关于事件的JSON数据;音乐会、运动会等。一项活动可以有一名或多名表演者。我获取每个事件的JSON数据,并将其平铺到数据表中。第一个事件可能有3列;事件id、执行者1、执行者2。第二个事件可能有两列;事件id,执行者1。所以我需要将所有这些事件合并到一个数据帧中。由于第二个事件没有第二个执行者,它在performer_2列中应该有NA。@NickAllen如我的回答所示,将performer粘贴在
列表中如何?或者保持长格式而不是宽格式。或者,如果你事先知道将返回的列数最多,那么使用类似于我答案末尾的内容将其固定。是的,这些都是好主意。我认为,将这些数据“广泛”地保存在训练中是不可行的。但保持“长时间”可能是可行的。Thanksrbind.fill(.data.table)应该是默认值behavior@eddi不幸的是,我不知道该如何实施<代码>数据。表的速度来自于在第一组结果已知后进行猜测。此时(猜测的)行数和列数将提前分配。然后在分组开始时直接填充。
rbind.fill
功能需要预先获得所有结果,才能知道返回的所有列。@eddi如果后续的
j
返回以前未看到的列名,我想它可以通过引用(为以前的组填充NA)动态地将该列添加到结果中。也许它是可行的。field-只是要补充一点,对于较新版本的
data.table
,现在可以使用
rbindlist(data[,,(.(fetch(.BY))),BY=id]$V1,use.names=TRUE,fill=TRUE)
我也有同样的问题。我正在按组计算data.table中的函数,myDT[,fun(.SD),ID]为每个组输出不同大小的向量。如何为向量的每个元素生成新行,而不是列表?。我试过使用t()、list(list())、as.data.table()、cbind()和许多其他组合。@skan您的问题可能值得在一个新问题中作为一个可复制的示例发布。我认为我们不能仅根据您在评论中的描述来调试它(因为我觉得它应该已经可以工作了)
allcols = c("A","B")
fetch <- function(by) {
    if(by == 1)
        list(A=c("a"), B=c("b"))[allcols]
    else
        list(B=c("b"))[allcols]
}
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']