Кумулятивная сумма в матрице

у меня есть матрица, как

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