【问题标题】:Multiply rows of matrix by vector?将矩阵的行乘以向量?
【发布时间】:2011-04-08 07:08:58
【问题描述】:

我有一个具有 25 列和 23 行的数字 matrix,以及一个长度为 25 的向量。如何在不使用 for 循环的情况下将矩阵的每一行乘以向量?

结果应该是一个 25x23 矩阵(与输入大小相同),但每一行都乘以向量。

从@hatmatrix 的回答中添加了可重现的示例:

matrix <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE)

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    1    1
[2,]    2    2    2    2    2
[3,]    3    3    3    3    3

vector <- 1:5

期望的输出:

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    2    4    6    8   10
[3,]    3    6    9   12   15

【问题讨论】:

    标签: r vector matrix multiplication


    【解决方案1】:

    如果你想要速度,你可以使用Rfast::eachrow。它是所有速度中最快的......

    【讨论】:

      【解决方案2】:

      使用outer()collapse::TRA()These 解决方案明显快于此处建议的任何方法。

      【讨论】:

        【解决方案3】:

        我认为您正在寻找sweep()

        # Create example data and vector
        mat <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE)
             [,1] [,2] [,3] [,4] [,5]
        [1,]    1    1    1    1    1
        [2,]    2    2    2    2    2
        [3,]    3    3    3    3    3
        
        vec <- 1:5
        
        # Use sweep to apply the vector with the multiply (`*`) function
        #  across columns (See ?apply for an explanation of MARGIN) 
        sweep(mat, MARGIN=2, vec, `*`)
             [,1] [,2] [,3] [,4] [,5]
        [1,]    1    2    3    4    5
        [2,]    2    4    6    8   10
        [3,]    3    6    9   12   15
        

        它一直是 R 的核心功能之一,尽管多年来已经对其进行了改进。

        【讨论】:

          【解决方案4】:

          为了速度,可以在乘法之前从向量创建矩阵

          mat <-  matrix(rnorm(1e6), ncol=1e4)
          vec <- c(1:1e4)
          mat * matrix(vec, dim(mat)[1], length(vec))
          
          library(microbenchmark)
          microbenchmark(
            transpose = t(t(mat) * vec), 
            make_matrix = mat * matrix(vec, dim(mat)[1], length(vec), byrow = TRUE),
            sweep = sweep(mat,MARGIN=2,vec,`*`))
          #Unit: milliseconds
          #       expr      min        lq     mean    median       uq      max neval cld
          #  transpose 9.940555 10.480306 14.39822 11.210735 16.19555 77.67995   100   b
          #make_matrix 5.556848  6.053933  9.48699  6.662592 10.74121 74.14429   100   a 
          #      sweep 8.033019  8.500464 13.45724 12.331015 14.14869 77.00371   100   b
          

          【讨论】:

            【解决方案5】:

            实际上,sweep 并不是我电脑上最快的选项:

            MyMatrix <- matrix(c(1:1e6), ncol=1e4, byrow=TRUE)
            MyVector <- c(1:1e4)
            
            Rprof(tmp <- tempfile(),interval = 0.001)
            t(t(MyMatrix) * MyVector) # first option
            Rprof()
            MyTimerTranspose=summaryRprof(tmp)$sampling.time
            unlink(tmp)
            
            Rprof(tmp <- tempfile(),interval = 0.001)
            MyMatrix %*% diag(MyVector) # second option
            Rprof()
            MyTimerDiag=summaryRprof(tmp)$sampling.time
            unlink(tmp)
            
            Rprof(tmp <- tempfile(),interval = 0.001)
            sweep(MyMatrix ,MARGIN=2,MyVector,`*`)  # third option
            Rprof()
            MyTimerSweep=summaryRprof(tmp)$sampling.time
            unlink(tmp)
            
            Rprof(tmp <- tempfile(),interval = 0.001)
            t(t(MyMatrix) * MyVector) # first option again, to check order 
            Rprof()
            MyTimerTransposeAgain=summaryRprof(tmp)$sampling.time
            unlink(tmp)
            
            MyTimerTranspose
            MyTimerDiag
            MyTimerSweep
            MyTimerTransposeAgain
            

            这会产生:

            > MyTimerTranspose
            [1] 0.04
            > MyTimerDiag
            [1] 40.722
            > MyTimerSweep
            [1] 33.774
            > MyTimerTransposeAgain
            [1] 0.043
            

            第二个选项除了是最慢的选项外,还达到了内存限制 (2046 MB)。但是,考虑到其余选项,在我看来,双重换位似乎比sweep好很多。


            编辑

            只是重复多次尝试较小的数据:

            MyMatrix <- matrix(c(1:1e3), ncol=1e1, byrow=TRUE)
            MyVector <- c(1:1e1)
            n=100000
            
            [...]
            
            for(i in 1:n){
            # your option
            }
            
            [...]
            
            > MyTimerTranspose
            [1] 5.383
            > MyTimerDiag
            [1] 6.404
            > MyTimerSweep
            [1] 12.843
            > MyTimerTransposeAgain
            [1] 5.428
            

            【讨论】:

            • 根据我的经验,如果你将一堆NAs 扔到矩阵中,diag 所花费的时间似乎已经到了顶峰。对于包含 1E5 NAs 的 1E4x1E4 垫子,我得到:MyTimerTranspose=0.014、MyTimerSweep=0.042、MyTimerDiag=67.738。我会复制,但我很不耐烦......只是要记住一些事情。
            • 我真的很喜欢双转置答案,主要是因为如果我们将“行”替换为“列”,它会显示答案是什么,使答案成为微不足道的 A*x,除非您真正了解 R 如何处理矩阵。
            【解决方案6】:
            > MyMatrix <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol=3, byrow=TRUE)
            > MyMatrix
                 [,1] [,2] [,3]
            [1,]    1    2    3
            [2,]   11   12   13
            > MyVector <- c(1:3)
            > MyVector
            [1] 1 2 3
            

            你可以使用:

            > t(t(MyMatrix) * MyVector)
                 [,1] [,2] [,3]
            [1,]    1    4    9
            [2,]   11   24   39
            

            或:

            > MyMatrix %*% diag(MyVector)
                 [,1] [,2] [,3]
            [1,]    1    4    9
            [2,]   11   24   39
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-03-29
              • 2021-12-04
              • 1970-01-01
              相关资源
              最近更新 更多