Кумулятивная сумма в матрице
у меня есть матрица, как
A= [ 1 2 4
2 3 1
3 1 2 ]
и я хотел бы вычислить его совокупную сумму по строке и столбцу, то есть я хочу, чтобы результат был
B = [ 1 3 7
3 8 13
6 12 19 ]
любые идеи о том, как сделать это в R быстрым способом? (Возможно, используя функцию cumsum) (У меня огромные матрицы)
спасибо!
2 ответов
один-лайнер:
t(apply(apply(A, 2, cumsum)), 1, cumsum))
основное наблюдение заключается в том, что вы можете сначала вычислить кумулятивные суммы по столбцам, а затем кумулятивную сумму этой матрицы по строкам.
Примечание: при выполнении строк вы должны транспонировать полученную матрицу.
ваш пример:
> apply(A, 2, cumsum)
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 3 5 5
[3,] 6 6 7
> t(apply(apply(A, 2, cumsum), 1, cumsum))
[,1] [,2] [,3]
[1,] 1 3 7
[2,] 3 8 13
[3,] 6 12 19
о производительности: теперь я знаю, насколько хорошо этот подход масштабируется до больших матриц. Сложность-это должно быть близко к оптимальному. Как правило, apply
не так уж плохо и в исполнении.
редактировать
теперь мне стало любопытно - какой подход лучше? Короткий тест:
> A <- matrix(runif(1000*1000, 1, 500), 1000)
>
> system.time(
+ B <- t(apply(apply(A, 2, cumsum), 1, cumsum))
+ )
User System elapsed
0.082 0.011 0.093
>
> system.time(
+ C <- lower.tri(diag(nrow(A)), diag = TRUE) %*% A %*% upper.tri(diag(ncol(A)), diag = TRUE)
+ )
User System elapsed
1.519 0.016 1.530
таким образом: применить умножение матрицы превосходит в 15 раз. (Для сравнения: MATLAB требовалось 0,10719 секунды.) Результаты не очень удивляют, так как apply
-версия может быть выполнена в O (n^2), в то время как для умножения матрицы потребуется ок. O (n^2.7) вычисления. Таким образом, все оптимизации это предложение умножения матрицы должно быть потеряно, если n достаточно велико.
вот более эффективная реализация с использованием пакета matrixStats и большего примера матрицы:
library(matrixStats)
A <- matrix(runif(10000*10000, 1, 500), 10000)
# Thilo's answer
system.time(B <- t(apply(apply(A, 2, cumsum), 1, cumsum)))
user system elapsed
3.684 0.504 4.201
# using matrixStats
system.time(C <- colCumsums(rowCumsums(A)))
user system elapsed
0.164 0.068 0.233
all.equal(B, C)
[1] TRUE