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

时间:2016-09-30 10:42:08

标签: 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

我想要做的就是从a中选择所有行,cols中保存名称的列中的所有值均高于0。

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

       n x y z
2: case2 2 1 1

我使用了与all()组合使用,但我认为使用data.table可以更快地完成此操作。我的原始数据当然要大得多,cols包含80个列名。谢谢你的帮助!

===编辑===

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

a[ a[, do.call(pmin, .SD) > 0, .SDcols=cols] ]

我还使用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秒

再次:谢谢!

3 个答案:

答案 0 :(得分:8)

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

!

或者正如评论中提到的@Frank一样,a[a[, !Reduce(`+`, lapply(.SD, `<=`, 0)),.SDcols = cols]] # n x y z #1: case2 2 1 1 也可以使用

pmin

答案 1 :(得分:4)

你可以尝试

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

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

答案 2 :(得分:1)

您可以apply逐行,然后检查all该行中的值是否大于0.

a[apply(a[, cols, with = FALSE], 1, function(x) all(x>0))]

#       n x y z
#1: case2 2 1 1