从r中矩阵的每一行中减去一个常数向量

Posted

技术标签:

【中文标题】从r中矩阵的每一行中减去一个常数向量【英文标题】:subtract a constant vector from each row in a matrix in 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

【问题讨论】:

【参考方案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)

【讨论】:

以上是关于从r中矩阵的每一行中减去一个常数向量的主要内容,如果未能解决你的问题,请参考以下文章

如何将矩阵的每一行除以R中的向量元素

将函数应用于矩阵或数据框的每一行

R scale() intergrate

机器学习数据降维方法 PCA主成分分析

将密集向量与 Tensorflow 中稀疏矩阵的每一行相乘

如何将给定矩阵的每一行中的所有元素与给定向量的相应元素相乘并在 MATLAB 中求和?