向量和矩阵之间的自动乘法

时间:2011-07-30 22:42:30

标签: r

我有这个R代码:

> coef
[1] 1.5 2.4 3.9 4.4
> y
     [,1] [,2] [,3] [,4]
[1,]    1    2   12   45
[2,]    5    6    7    8
[3,]    9   10    2   12
[4,]   13   14   15   45
[5,]   17   18   39    7

我必须将列的每个值乘以相应的coef。结果应该是:

First column:
1*1.5 
5*1.5 
9*1.5 
13*1.5 
17*1.5

Second column: 
2*2.4 
6*2.4 
10*2.4 
14*2.4 
18*2.4

Third column: 
12*3.9 
7*3.9 
2*3.9 
15*3.9 
39*3.9

Fourth column: 
45*4.4
8*4.4
12*4.4 
45*4.4 
7*4.4

所有列的值都在向量中的相同索引处乘以相同的系数。

我该怎么做这个计算?

解决方案可能是:

> y[,1] <- y[,1] * coef[1]
> y[,2] <- y[,2] * coef[2]
> y[,3] <- y[,3] * coef[3]
> y[,4] <- y[,4] * coef[4]

但似乎没有太优化!还有更好的东西吗?

谢谢!

4 个答案:

答案 0 :(得分:7)

这会给你你想要的东西:

t( t(y) * coef  )

答案 1 :(得分:6)

还有两种可能性:sweepscale(后者只按列操作,在我看来有点像黑客)。

coef <- c(1.5,2.4,3.9,4.4)
y <- matrix(c(seq(1,17,by=4),
              seq(2,18,by=4),
              c(12,7,2,15,39,
                45,8,12,45,7)),
              ncol=4)

t(t(y)*coef)
t(apply(y,1,"*",coef))
sweep(y,2,coef,"*")
scale(y,center=FALSE,scale=1/coef)

library(rbenchmark)

benchmark(t(t(y)*coef),
           y %*% diag(coef),
           t(apply(y,1,"*",coef)),
           sweep(y,2,coef,"*"),
           scale(y,center=FALSE,scale=1/coef),
           replications=1e4)

                                      test replications elapsed relative
5 scale(y, center = FALSE, scale = 1/coef)        10000   0.990 4.342105
4                   sweep(y, 2, coef, "*")        10000   0.846 3.710526
3                t(apply(y, 1, "*", coef))        10000   1.537 6.741228
1                           t(t(y) * coef)        10000   0.228 1.000000
2                         y %*% diag(coef)        10000   0.365 1.600877

编辑:从@baptiste添加y %*% diag(coef) [不是最快的,虽然对于充分优化的BLAS包的大问题可能会如此...] [并且它最快另一个试验,所以我可能没有一个稳定的估计]

修改:修复t(t(y)*coef)中的拼写错误[感谢Timur Shtatland](但更新时间,因此它们可能稍微偏离......)

我也试过library(Matrix); y %*% Diagonal(x=coef),这个例子的非常慢,但对于一个大矩阵(??)可能很快。 (我也尝试过只构造一次对角矩阵,但是在这个例子中,即使乘以预定矩阵也很慢(比最好的慢25倍,而在动态定义矩阵时慢47倍)。

我对sweep有一个温和的偏好,因为我认为它最清楚地表达了正在进行的操作(“将列乘以coef的元素”)

答案 2 :(得分:5)

 apply(y, 1, "*", coef)
#  -- result --    
  [,1] [,2] [,3]  [,4]  [,5]
[1,]   1.5  7.5 13.5  19.5  25.5
[2,]   4.8 14.4 24.0  33.6  43.2
[3,]  46.8 27.3  7.8  58.5 152.1
[4,] 198.0 35.2 52.8 198.0  30.8

答案 3 :(得分:3)

迟到:

coef[col(y)]*y

在我的系统上,这是最快的。

                                      test replications elapsed relative
6                         coef[col(y)] * y        10000   0.068    1.000
5 scale(y, center = FALSE, scale = 1/coef)        10000   0.640    9.412
4                   sweep(y, 2, coef, "*")        10000   0.535    7.868
3                t(apply(y, 1, "*", coef))        10000   0.837   12.309
1                           t(t(y) * coef)        10000   0.176    2.588
2                         y %*% diag(coef)        10000   0.187    2.750