【问题标题】:R - fastest way to select the rows of a matrix that satisfy multiple conditionsR - 选择满足多个条件的矩阵行的最快方法
【发布时间】:2013-08-10 07:30:39
【问题描述】:

这是对 R 中returning the rows of a matrix that meet a condition 问题的扩展。假设我有矩阵:

       one two three four
 [1,]   1   6    11   16
 [2,]   2   7    12   17
 [3,]   3   8    11   18
 [4,]   4   9    11   19
 [5,]   5  10    15   20
 [6,]   1   6    15   20
 [7,]   5   7    12   20

我想尽快返回所有行,其中matrix$two == 7 AND matrix$three == 12。这是我知道的方法:

 out <- mat[mat$two == 7,]
 final_out <- out[out$three == 12, ]

显然应该有一种方法可以在单行中获取final_out 的内容,例如:final_out &lt;- which(mat$two == 7 &amp;&amp; mat$three == 12),这比上面的两行代码更快更简洁。

返回这个多条件矩阵查询的最快 R 代码是什么?

【问题讨论】:

    标签: r performance matrix conditional-statements multiple-columns


    【解决方案1】:

    whicharr.ind=TRUE 一起使用,如下所示:

    > mat[which(mat[,"two"]==7 & mat[,"three"] == 12, arr.ind = TRUE),]
      one two three four
    2   2   7    12   17
    7   5   7    12   20
    

    【讨论】:

    • mat[mat[,"two"] == 7 &amp; mat[,"three"] == 12,]
    • 我没有完整阅读这个问题,也没有意识到 OP 已经使用了which
    • $ 子设置是否适合矩阵?我收到一个错误。
    【解决方案2】:

    只需使用 [ 子集和逻辑比较...

    #  Reproducible data
    set.seed(1)
    m <- matrix( sample(12,28,repl=T) , 7 , 4 )
         [,1] [,2] [,3] [,4]
    [1,]    4    8   10    3
    [2,]    5    8    6    8
    [3,]    7    1    9    2
    [4,]   11    3   12    4
    [5,]    3    3    5    5
    [6,]   11    9   10    1
    [7,]   12    5   12    5
    
    
    #  Subset according to condition
    m[ m[,2] == 3 & m[,3] == 12 , ]
    [1] 11  3 12  4
    

    【讨论】:

      【解决方案3】:

      R 中绝对最快的方法是ifelse,与if 不同,它允许向量化条件。您还可以缓存条件向量(例如isSeven &lt;- mat[, 'two'] == 7)并在以后使用/重用它们。

      我这里没有可重现的例子,但我会做类似的事情

      ifelse(mat[, 'two'] == 7 & mat[, 'three'] == 12, "both", "not both")
      

      您可以在其中添加其他条件,或者让它返回任何会导致一致向量的内容。

      【讨论】:

      • 我不认为ifelse 会比逻辑子集更快。毕竟,这正是ifelse 在内部所做的。
      【解决方案4】:

      使用 MICROBENCHMARK 更新:

      使用基准会给出相反的答案。 @SimonO101 给出的答案似乎提供了一个稍微快一点的实现。

      require(microbenchmark)
      set.seed(1)
      m <- matrix( sample(12,100,repl=T) , 25 , 4 )
      colnames(m) <- c("one","two","three","four")
      
      bench1 <- microbenchmark(m[which(m[,'two']==7 & m[,'three'] == 12, arr.ind = TRUE),])
      summary(bench1$time)
         Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
         7700    8750    9449    9688    9800   22400
      
      bench2 <- microbenchmark(m[ m[,2] == 3 & m[,3] == 12 , ])
      summary(bench2$time)
         Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
         6300    7350    7351    7599    8050   15400
      

      旧答案:

      结合@Jiber 和@SimonO101 给出的答案给出了一个稍微快一点的答案,至少在我的电脑上是这样。

      我将矩阵做得更大以分隔计算时间。

      set.seed(1)
      m <- matrix( sample(12,1000000000,repl=T) , 1e8 , 10 )
      colnames(m) <- c("one","two","three","four","five","six","seven","eight","nine","ten")
      
      system.time(m[which(m[,'two']==7 & m[,'three'] == 12, arr.ind = TRUE),])
         user  system elapsed 
         6.49    1.58    8.06 
      system.time(m[ m[,2] == 3 & m[,3] == 12 , ])
         user  system elapsed 
         8.23    1.29    9.52 
      

      这显然假设矩阵列已命名。

      【讨论】:

      • 您应该使用library(microbenchmark) 来计算时间……它更可靠。
      • @Thomas 感谢您的提示。这是我第一次尝试基准测试。安装包后我会更新答案。
      • 这可能需要一点时间...环顾四周,您会看到人们如何使用它的其他示例。
      【解决方案5】:

      如果您有很多行,最好先进行子集化,如以下代码所示

      set.seed(1)
      m <- matrix( sample(12,28,repl=T) , 12e6 , 4 )
      
      #  Subset according to condition
      microbenchmark(sample0=m[ m[,2] == 3 & m[,3] == 12 , ],times = 10L)
      
      microbenchmark(sample1=m[ m[,2] == 3, ],
                 sample2= sample1[sample1[,3] == 12, ],times = 10L)
      

      结果如下:

      microbenchmark(sample0=m[ m[,2] == 3 & m[,3] == 12 , ],times = 10L)
      Unit: milliseconds
      expr        min         lq        mean     median         uq        max neval
      sample0 342.085212 347.333083 381.6039635 349.920741 375.383425 584.068743    10
      microbenchmark(sample1=m[ m[,2] == 3, ],
                    sample2= sample1[sample1[,3] == 12, ],times = 10L)
      Unit: milliseconds
      expr        min         lq        mean      median         uq        max neval cld
       sample1 188.647995 189.832552 215.9355769 194.2375715 199.118962 404.631420    10   b
       sample2   5.097811   5.262028   5.3260160   5.2868025   5.401471   5.571351    10  a 
      

      【讨论】:

        猜你喜欢
        • 2022-07-30
        • 2011-07-20
        • 1970-01-01
        • 1970-01-01
        • 2017-02-20
        • 2021-01-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多