用 "wildcards" 子集 data.table 中的行

subsetting rows in data.table with "wildcards"

我有一个像这样的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(),该函数 return 按降序排列给定索引 (a,b,c) 的所有数值。例如。 getContent(c(1,1,2)) 世界 return "6 5".

但是给定的索引可以是 NA,我想把它们当作通配符,所以 getContent(c(NA,1,2)) 会 return "6 5 4" 而 getContent(c(2,NA,2)) 会 return “4 3”

我找到了一种方法 return 没有 if/else 逻辑的所有数值:

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]

我如何 return 列表按降序排列而不将其排序为 post 处理步骤? (我想使用 setorderv(DT,c(letters[1:3][!is.na(Indecies)],-num)) 但这不起作用,尽管错误说 'marked as sorted' 就足够了)

所以像这样的东西会很好:

getContent <- function(Indecies){
    DT[as.list(Indecies[!is.na(Indecies)]),num,
       by=.(letters[1:3][!is.na(Indecies)],-num)]
}

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

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

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