将矩阵的行乘以向量?

发布于 2024-09-17 01:12:55 字数 589 浏览 11 评论 0原文

我有一个 25 列和 23 行的数字矩阵,以及一个长度为 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

I have a numeric matrix with 25 columns and 23 rows, and a vector of length 25. How can I multiply each row of the matrix by the vector without using a for loop?

The result should be a 25x23 matrix (the same size as the input), but each row has been multiplied by the vector.

Added reproducible example from @hatmatrix's answer:

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

Desired output:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

南城旧梦 2024-09-24 01:12:56

我认为您正在寻找 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 的核心功能之一,尽管多年来对其进行了改进。

I think you're looking for 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

It's been one of R's core functions, though improvements have been made on it over the years.

数理化全能战士 2024-09-24 01:12:56
> 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
> 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

You could use either:

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

or:

> MyMatrix %*% diag(MyVector)
     [,1] [,2] [,3]
[1,]    1    4    9
[2,]   11   24   39
故事和酒 2024-09-24 01:12:56

实际上,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)。然而,考虑到剩下的选项,在我看来,双重换位似乎比扫描要好得多。


编辑

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

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

Actually, sweep is not the fastest option on my computer:

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

This yields:

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

On top of being the slowest option, the second option reaches the memory limit (2046 MB). However, considering the remaining options, the double transposition seems a lot better than sweep in my opinion.


Edit

Just trying smaller data a repeated number of times:

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
本宫微胖 2024-09-24 01:12:56

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

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

For speed one may create matrix from the vector before multiplying

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
友谊不毕业 2024-09-24 01:12:56

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

If you want speed, you can use Rfast::eachrow. It is the fastest from all...

温柔少女心 2024-09-24 01:12:56

这是另一个选项:

X <- matrix(rep(1:3, 5), nrow = 3)
v <- 1:5

X * v[col(X)]

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

这适用于任何运算,而不仅仅是乘法。

Here is another option:

X <- matrix(rep(1:3, 5), nrow = 3)
v <- 1:5

X * v[col(X)]

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

This works for any operation, not just multiplication.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文