我正在尝试使用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)
任何想法都赞赏.
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)
尝试
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)