r - 使用 R 或 RCpp 计算矩阵中有多少行全部为 TRUE 的最快方法是什么?

标签 r performance rcpp

概要

我想找到最快的方法来计算一个子集的次数 vec 从逻辑矩阵中定义的 cols all TRUE:

最小示例:

mlgl <- structure(c(FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, 
                    FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, 
                    FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, 
                    TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, 
                    FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, 
                    FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, 
                    TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, 
                    FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE), .Dim = c(15L, 5L
                    ), .Dimnames = list(NULL, c("l1", "l2", "l3", "l4", "l5")))
mlgl
#>          l1    l2    l3    l4    l5
#>  [1,] FALSE FALSE FALSE FALSE FALSE
#>  [2,]  TRUE FALSE FALSE FALSE  TRUE
#>  [3,] FALSE  TRUE FALSE FALSE FALSE
#>  [4,] FALSE FALSE  TRUE FALSE FALSE
#>  [5,]  TRUE  TRUE FALSE FALSE  TRUE
#>  [6,]  TRUE FALSE  TRUE FALSE  TRUE
#>  [7,]  TRUE FALSE FALSE  TRUE  TRUE
#>  [8,] FALSE  TRUE  TRUE FALSE FALSE
#>  [9,] FALSE  TRUE FALSE  TRUE FALSE
#> [10,] FALSE FALSE  TRUE  TRUE FALSE
#> [11,]  TRUE  TRUE  TRUE FALSE  TRUE
#> [12,]  TRUE  TRUE FALSE  TRUE  TRUE
#> [13,]  TRUE FALSE  TRUE  TRUE  TRUE
#> [14,] FALSE  TRUE  TRUE  TRUE FALSE
#> [15,]  TRUE  TRUE  TRUE  TRUE  TRUE

和一个向量子集,由 vec 定义:

vec <- c("l1", "l3")

我想知道 vec 中的所有变量 TRUE 有多少次。为了 这个 vec 的预期答案是 4(第 6、11、13 和 15 行)。最快的 我能想到的方法是:

sum(rowSums(mlgl[,vec]) == length(vec))
#> [1] 4

compiler::cpmfun 对这些都没有帮助:

microbenchmark(
  sum(apply(mlgl[, vec], 1, all)), 
  sum(rowSums(mlgl[,vec]) == length(vec)),
  unit = "eps"
  )
#> Unit: evaluations per second
#>                                      expr       min       lq     mean
#>           sum(apply(mlgl[, vec], 1, all))  4416.649 14013.85 13696.17
#>  sum(rowSums(mlgl[, vec]) == length(vec)) 27348.557 63477.96 67712.96
#>    median       uq      max neval cld
#>  14210.30 14397.81 14766.03   100  a 
#>  65017.46 75503.08 81175.42   100   b

我希望有一些替代解决方案或建议比 这在 R 或 RCpp 中。

更新:添加了一些有助于解决问题的解决方案……不过,另一个数量级会更好。

最佳答案

我们可以通过使用整数向量而不是字符向量来选择列来提高速度。使用此方法,不会在后台发生名称匹配或使用任何属性。我们将试一试 fmatch()match()

下面标记为 integer 的行显示了单独使用整数向量的速度。

library(fastmatch)
microbenchmark(
    fmatch  = sum(rowSums(mlgl[, fmatch(vec, colnames(mlgl))]) == length(vec)),
    match   = sum(rowSums(mlgl[, match(vec, colnames(mlgl))]) == length(vec)),
    integer = sum(rowSums(mlgl[, c(1L, 3L)]) == length(vec)),
    unit = "eps"
 )
# Unit: evaluations per second
#     expr      min       lq     mean   median       uq      max neval
#   fmatch 16146.74 49468.25 50143.24 50823.34 52064.45 54404.00   100
#    match 45108.03 58503.55 59741.99 59724.68 61135.91 64930.85   100
#  integer 41023.96 80411.72 81827.19 83004.78 85429.93 88944.23   100

实际上似乎我们根本不需要加载fastmatch,因为match() 做得更好。总的来说,使用整数向量而不是字符名称匹配肯定会提高速度。

我相信很快就会发布一个很好的快速 Rcpp 答案。

更新:这是使用 which()length() 的另一种方法,它也非常好。

microbenchmark(
    which = length(which(rowSums(mlgl[, vec]) == length(vec))),
    unit = "eps"
)
# Unit: evaluations per second
#   expr      min       lq     mean   median      uq     max neval
#  which 26816.12 81502.91 81858.62 83156.76 84566.6 87850.3   100

关于r - 使用 R 或 RCpp 计算矩阵中有多少行全部为 TRUE 的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32752521/

相关文章:

linux - 什么时候关闭 atime 和 diratime 是个好主意?

c++ - 在 C++ Rcpp 中实现 R 函数

NumericMatrix 的 Rcpp 糖

arrays - 从数组中删除行

R 性能差异(Solaris 与 Windows)

r - 在向量中查找字母数字元素

r - 将包含 "#"个字符的文本的表导入到 R

ruby-on-rails - helpers 真的比 partials 快吗?弦乐 build 呢?

performance - Boost Graph 识别顶点

c++ - 如何在 Rcpp 中加快 xts 数据到 Datetime Vector 的转换?