使用"通配符"对data.table中的行进行子集化。

时间:2015-04-19 16:15:12

标签: r parameter-passing data.table

我有一个像这样的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(),它按降序返回给定indecies(a,b,c)的所有num-values。例如。 getContent(c(1,1,2)) wourld返回“6 5”。

但是,给定的下限可以是NA,我想将它们视为通配符,因此getContent(c(NA,1,2))将返回“6 5 4”而getContent(c(2,NA,2))将返回“4 3”

我发现了一种在不使用if / else逻辑的情况下返回所有num-values的方法:

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)]
}

非常感谢任何帮助或链接! : - )

1 个答案:

答案 0 :(得分:3)

直截了当的解决方案对你来说不够好吗?

setorder(DT, -num)
getContent = function(idx) {
  if (all(is.na(idx))) return (DT[, num])

  cols = names(DT)[which(!is.na(idx))]
  vals = idx[!is.na(idx)]

  DT[eval(parse(text = paste(cols, vals, sep = " == ", collapse = " & "))), num]
}

getContent(c(1, NA, 2))
#[1] 6 5