Умножение одной матрицы на набор скаляров

У меня есть сценарий R, который систематически выполняет изменения в матрице 3x3 путем скалярного умножения следующим образом.

R <- matrix(rexp(9, rate=.1), ncol=3);
for (i in 1:360) {
K = i*R;
...
}

и использовать модифицированную матрицу для дальнейших вычислений внутри цикла. Однако сам цикл вложен в два других цикла for, что делает скрипт очень медленным. Итак, мой вопрос: как я могу векторизовать этот самый внутренний цикл так, чтобы вместо этого результатом был трехмерный массив A размером 3x3x360, где

A[,,i] = i*R;

для всех я в диапазоне от 1 до 360?


person Christofer Östlin    schedule 22.07.2015    source источник
comment
Интересный вопрос. Результирующий массив будет вполне регулярным и предсказуемым, поскольку каждый слой будет связан со всеми другими слоями набором скаляров. Есть ли способ, которым ваш код может обойти необходимость создания массива, который будет большим. Вы можете использовать Alyr <- function(i){R*i}.   -  person CJB    schedule 22.07.2015
comment
В вашем цикле начинать с R и каждый раз добавлять к нему R? Я не думаю, что умножение замедляет вас. Я почти уверен, что это занимает очень мало времени.   -  person Frank    schedule 22.07.2015
comment
Модификация здесь упрощена. На самом деле я использую формулу вращения Родригеса в матричной записи для вычисления большое количество матриц вращения. Затем я применяю их к большому набору векторов и оцениваю результат. Таким образом, реальная модификация выглядит примерно так: K = I + sin(thetapi/180)*T + (1-cos(thetapi/180))*(T%*%T), где I — единичная матрица, а T — матрица перекрестного произведения. Так что, к сожалению, разные слои в массиве НЕ НАСТОЛЬКО предсказуемы...   -  person Christofer Östlin    schedule 22.07.2015


Ответы (1)


Как насчет некоторого базового умножения и изменения формы

set.seed(15) #for reproducibility
R <- matrix(rexp(9, rate=.1), ncol=3);
R
#           [,1]      [,2]      [,3]
# [1,]  2.042281  1.760375 2.9230182
# [2,] 19.466458  6.628580 0.1818078
# [3,]  2.544348 27.541514 4.1325714

dd <- array(sapply(1:360, `*`, R), dim=c(dim(R), 360))
dd[,,1]
#           [,1]      [,2]      [,3]
# [1,]  2.042281  1.760375 2.9230182
# [2,] 19.466458  6.628580 0.1818078
# [3,]  2.544348 27.541514 4.1325714
dd[,,2]
#           [,1]      [,2]      [,3]
# [1,]  4.084562  3.520749 5.8460364
# [2,] 38.932916 13.257161 0.3636157
# [3,]  5.088697 55.083027 8.2651427
dd[,,10]
#           [,1]      [,2]      [,3]
# [1,]  20.42281  17.60375 29.230182
# [2,] 194.66458  66.28580  1.818078
# [3,]  25.44348 275.41514 41.325714
person MrFlick    schedule 22.07.2015
comment
Простой! Можно ли по-прежнему использовать sapply для более сложных модификаций? Например, K = I + sin(i*pi/180)*R, где I — единичная матрица 3x3? - person Christofer Östlin; 22.07.2015
comment
Конечно, там, где я использовал `*`, вы можете поставить любую функцию function(i,R) I+sin(i*pi/180)*R) - person MrFlick; 22.07.2015