Автоматическое умножение между вектором и матрицей - PullRequest
4 голосов
/ 31 июля 2011

У меня есть этот код 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

Я должен умножить каждое значение столбца на соответствующий коэффициент. Результат должен быть:

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 ]

7 голосов
/ 31 июля 2011

Это даст вам то, что вы хотите:

t( t(y) * coef  )
6 голосов
/ 31 июля 2011

Еще две возможности: sweep и scale (последняя работает только по столбцам, и мне кажется, это немного хак).

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

edit : добавлено y %*% diag(coef) из @baptiste [не самое быстрое, хотя это может быть так для большой проблемы с достаточно оптимизированным пакетом BLAS ...] [и это было быстрее всего в другом испытании, так что, возможно, у меня не было стабильной оценки]

edit : исправлена ​​опечатка в t(t(y)*coef) [благодаря Тимуру Штатланду] (но не обновлял тайминги, поэтому они могли быть немного не в порядке ...)

Я также попытался library(Matrix); y %*% Diagonal(x=coef), что очень медленно для этого примера, но может быть быстрым для большой матрицы (??). (Я также пытался построить диагональную матрицу только один раз, но даже умножение на заранее определенную матрицу было медленным в этом примере (в 25 раз медленнее, чем в лучшем случае, в 47 раз медленнее при определении матрицы на лету.)

У меня есть мягкое предпочтение sweep, так как я думаю, что оно наиболее четко выражает выполняемую операцию («умножьте столбцы на элементы coef»)

5 голосов
/ 31 июля 2011
 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 голосов
/ 22 октября 2013

Поздняя запись:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...