【发布时间】:2015-06-26 06:19:21
【问题描述】:
我有一个这样的data.table(只有更多的列,显然更大^^)
> DT = data.table(a=c(1,1,2,2),b=c(1,1,1,2),c=c(2,2,2,2),num=c(6,5,4,3))
> DT
a b c num
1: 1 1 2 6
2: 1 1 2 5
3: 2 1 2 4
4: 2 2 2 3
我想编写一个函数getContent(),它按降序返回给定指数 (a,b,c) 的所有 num 值。例如。 getContent(c(1,1,2)) 将返回“6 5”。
但是,给定的不定值可以是 NA,我想将它们视为通配符,因此 getContent(c(NA,1,2)) 将返回“6 5 4”,getContent(c(2,NA,2)) 将返回“4 3”
我找到了一种无需 if/else 逻辑即可返回所有 num 值的方法:
getContent <- function(Indecies){
setkeyv(DT,letters[1:3][!is.na(Indecies)])
DT[as.list(Indecies[!is.na(Indecies)]),num]
}
但是有没有更好(即更快)的方法?特别是没有设置DT的密钥?我的意思是getContent(c(2,NA,2)) 可以实现为DT[a==2 & c==2,num]
我如何以降序返回列表而不将其作为后处理步骤进行排序? (我想使用 setorderv(DT,c(letters[1:3][!is.na(Indecies)],-num)) 但这不起作用,尽管错误说“标记为已排序”就足够了)
所以像这样的东西会很好:
getContent <- function(Indecies){
DT[as.list(Indecies[!is.na(Indecies)]),num,
by=.(letters[1:3][!is.na(Indecies)],-num)]
}
非常感谢任何帮助或链接! :-)
【问题讨论】:
-
如果你必须在函数内部设置键(即每次调用函数时),它会相当慢。相反,如果您将密钥设置为完整的索引集
setkey(DT,a,b,c),那么您只需将您的NA/wildcard 替换为unique(b)或任何字母是通配符:sort(DT[J(2,unique(b),2)]$num,decr=TRUE)。 (我没有发布作为答案,因为我不想把它变成一个函数,但其他任何人都可以。) -
我写了一个函数,它允许执行二进制搜索并允许跳过键中任何选定的列。见dwtools::idxv。取而代之的是
NA,您使用TRUE。将比unique(col)更快,因为它保留了预先计算的索引。当data.table#1067 被解决时,它也将被弃用。它仍然不能解决您问题的 按降序排列的值 部分,但它应该通过扩展二进制搜索来加快过滤速度。 -
这样的
unique(col)在某些情况下甚至比矢量扫描还要慢,所以如果你这样做,你应该在你的数据上测试它。 -
@Frank :方法很好,但是我的表很大,在任何列上执行 unique() 都会很慢! (可以作为预处理完成,但这会浪费内存)我是否提到我有可变数量的字母列?并且其中任何一个都可能是每次调用中的 NA .. 不知道如何将其转移到函数中
-
@JanGorecki :感谢您的链接 - 所以我不是唯一一个遇到这个问题的人 - 不幸的是我不能使用 dwtools .. data.table 本身有办法吗?
标签: r parameter-passing data.table