如果特定列符合条件,请快速检查data.table中的每一行

swo*_*olf 11 r data.table

我无法理解这个非常简单的任务,阅读本网站上的相关问题并没有帮助.

我创建了一个最小的例子:

a <- data.table(n = c("case1", "case2", "case3"), x = c(0,2,5), y = c(1,1,4), z = c(1,1,0))
cols <- c("x", "y", "z")
a
       n x y z
1: case1 0 1 1
2: case2 2 1 1
3: case3 5 4 0
Run Code Online (Sandbox Code Playgroud)

我想要做的就是从a名称保存在的列中的所有值中选择所有行都在cols0以上.

所以我想在这种情况下得到的是:

       n x y z
2: case2 2 1 1
Run Code Online (Sandbox Code Playgroud)

我使用了apply with all(),但我认为data.table有一个更快的方法来做到这一点.我的原始数据当然要大得多,cols包含80个列名.谢谢你的帮助!

===编辑===

谢谢您的回答!所有这些都有效,但显然性能不同.请检查已接受答案的评论以获得基准.实现这一目标的最快方法是:

a[ a[, do.call(pmin, .SD) > 0, .SDcols=cols] ]
Run Code Online (Sandbox Code Playgroud)

我还使用rbenchmark软件包和我的原始数据集复制了不同解决方案的基准,参数略有不同(880,000行,64列,其中62个被选中)并且可以确认不同解决方案的速度等级(已经进行了10次重复) :

z[z[, !Reduce(`+`, lapply(.SD, `<`, 11)),.SDcols = col.names]]:3.32秒

z[apply(z[, col.names, with = FALSE], 1, function(x) all(x>10))]:37.41秒

z[ z[, do.call(pmin, .SD) > 10, .SDcols=col.names] ]:2.03秒

z[rowSums(z[, lapply(.SD, `<`, 11), .SDcols=col.names])==0]:4.84秒

再次谢谢你!

akr*_*run 9

我们可以使用Reduce.SDcols.指定感兴趣的列.SDcols,循环遍历Data.table(.SD)的子集,检查它是否等于0,得到每行的总和Reduce,否定(!)得到一个逻辑向量,当没有0个元素时返回TRUE用它来对"a"行进行子集化

a[a[, !Reduce(`+`, lapply(.SD, `<=`, 0)),.SDcols = cols]]
#       n x y z
#1: case2 2 1 1
Run Code Online (Sandbox Code Playgroud)

或者像评论中提到的@Frank一样,pmin也可以使用

a[a[, do.call(pmin, .SD), .SDcols = cols]>0]
Run Code Online (Sandbox Code Playgroud)

  • 一个类似的选项:`a [a [,do.call(pmin,.SD)> 0,.SDcols = cols]] ......实际上,我猜你的可能需要调整,因为OP想要"高于零"而不是"不是". (6认同)
  • 仅供参考,如果你是有意义的话,对于1e7行和功能如下:f1.`a [rowSums(a [,lapply(.SD,"<=",0),. SDcols = cols])== 0]`f2.`a [a [,!Reduce("+",lapply(.SD,"<=",0)),. SDcols = cols]]`f3.`a [apply(a [,cols,with = FALSE],1,function(x)all(x> 0))]`**f4.`a [a [,do.call(pmin,.SD)> 0,.SDcols = cols]]`**中位执行时间为:f1 = 684 ms,f2 = 539 ms,f3 = 32724 ms,**f4 = 260毫秒**. (4认同)

Cat*_*ath 5

你可以试试

a[rowSums(a[, lapply(.SD, `<=`, 0), .SDcols=cols])==0]
#       n x y z
#1: case2 2 1 1
Run Code Online (Sandbox Code Playgroud)

它选择没有cols值小于或等于零的列的行(您也可以使用条件x> 0并检查==length(cols)是否愿意)。