【问题标题】:subtract a constant vector from each row in a matrix in r从r中矩阵的每一行中减去一个常数向量
【发布时间】:2021-08-13 04:39:37
【问题描述】:

我有一个 5 列 4 行的矩阵。我也有一个 3 列的向量。我想在矩阵的每一行分别从第 3,4 和 5 列中减去向量中的值。

b <- matrix(rep(1:20), nrow=4, ncol=5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

c <- c(5,6,7)

得到

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    4    7   10
[2,]    2    6    5    8   11
[3,]    3    7    6    9   12
[4,]    4    8    7   10   13

【问题讨论】:

    标签: r vector matrix


    【解决方案1】:

    这正是 sweep 的用途:

    b <- matrix(rep(1:20), nrow=4, ncol=5)
    x <- c(5,6,7)
    
    b[,3:5] <- sweep(b[,3:5], 2, x)
    b
    
    #     [,1] [,2] [,3] [,4] [,5]
    #[1,]    1    5    4    7   10
    #[2,]    2    6    5    8   11
    #[3,]    3    7    6    9   12
    #[4,]    4    8    7   10   13
    

    ..甚至没有子集或重新分配:

    sweep(b, 2, c(0,0,x))
    

    【讨论】:

      【解决方案2】:

      也许没有那么优雅,但是

      b <- matrix(rep(1:20), nrow=4, ncol=5)
      x <- c(5,6,7)
      
      b[,3:5] <- t(t(b[,3:5])-x)
      

      应该可以解决问题。我们对矩阵进行子集化以仅更改我们需要的部分,并使用t()(转置)来翻转矩阵,因此简单的向量回收将负责从正确的行中减去。

      如果你想避免转置,你可以这样做

      b[,3:5] <- b[,3:5]-x[col(b[,3:5])]
      

      也是。在这里,我们进行了两次子集化,并使用第二次为x 中的每个值获取正确的列,因为这两个矩阵将以相同的顺序索引。

      我认为@thelatemail 链接的问题中我最喜欢的是

      b[,3:5] <- sweep(b[,3:5], 2, x, `-`)
      

      【讨论】:

      • 遗憾的是,副本中最快的解决方案 (mat %*% diag(1/dev)) 无法轻松转换为减法。 (mat %*% diag(1/dev) -1) %*% diag(dev) 比双转置既丑又慢:\
      【解决方案3】:

      另一种方式,应用:

      b[,3:5] <- t(apply(b[,3:5], 1, function(x) x-c))
      

      【讨论】:

        【解决方案4】:

        一个简单的解决方案:

        b <- matrix(rep(1:20), nrow=4, ncol=5)
        c <- c(5,6,7)
        
        for(i in 1:nrow(b)) {
          b[i,3:5] <- b[i,3:5] - c
        }
        

        【讨论】:

          【解决方案5】:

          这可以通过rray package 以非常令人满意的方式完成(使用其(类似numpy)广播- 运算符%b-%):

          #install.packages("rray")
          library(rray)
          
          b <- matrix(rep(1:20), nrow=4, ncol=5)
          x <- c(5, 6, 7)
          
          b[, 3:5] <- b[, 3:5] %b-% matrix(x, 1)
          b
          #>      [,1] [,2] [,3] [,4] [,5]
          #> [1,]    1    5    4    7   10
          #> [2,]    2    6    5    8   11
          #> [3,]    3    7    6    9   12
          #> [4,]    4    8    7   10   13
          

          对于大型矩阵,这甚至比sweep 更快:

          #install.packages("bench")
          res <- bench::press(
            size = c(10, 1000, 10000),
            frac_selected = c(0.1, 0.5, 1),
            {
            B <- matrix(sample(size*size), nrow=size, ncol=size)
            B2 <- B
            x <- sample(size, size=ceiling(size*frac_selected))
            idx <- sample(size, size=ceiling(size*frac_selected))
          
            bench::mark(rray = {B2[, idx] <- B[, idx, drop = FALSE] %b-% matrix(x, nrow = 1); B2}, 
                        sweep = {B2[, idx] <- sweep(B[, idx, drop = FALSE], MARGIN = 2, x); B2}
            )
            }
          )
          plot(res)
          

          【讨论】:

            猜你喜欢
            • 2014-08-22
            • 1970-01-01
            • 2015-05-15
            • 2011-07-17
            • 2014-12-07
            • 1970-01-01
            • 1970-01-01
            • 2019-01-12
            • 1970-01-01
            相关资源
            最近更新 更多