【问题标题】:subsetting rows in data.table with "wildcards"用“通配符”对 data.table 中的行进行子集化
【发布时间】: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 &amp; 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


【解决方案1】:

简单的解决方案对您来说还不够好吗?

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

【讨论】:

  • 哦,这是一个简洁的 eval+parse+paste 表达式!我正在玩一个递归函数来做同样的事情,但这更干净,正是我想要的!谢谢!如果输入都是 NA,可能需要修复 ;-)
  • @Andi 很公平,已添加修复
猜你喜欢
  • 2020-07-24
  • 2016-12-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2021-12-18
  • 2021-12-23
  • 2020-06-13
  • 2016-10-29
相关资源
最近更新 更多