arrays - que - Suma acumulada en una matriz
suma acumulada matlab (2)
Tengo una matriz como
A= [ 1 2 4
2 3 1
3 1 2 ]
y me gustaría calcular su suma acumulada por fila y por columna, es decir, quiero que el resultado sea
B = [ 1 3 7
3 8 13
6 12 19 ]
¿Alguna idea de cómo hacer esto en R de una manera rápida? (Posiblemente usando la función cumsum) (Tengo matrices enormes)
¡Gracias!
Un trazador de líneas:
t(apply(apply(A, 2, cumsum)), 1, cumsum))
La observación subyacente es que primero puede calcular las sumas acumuladas sobre las columnas y luego la suma acumulada de esta matriz sobre las filas.
Nota: Al hacer las filas, debe transponer la matriz resultante.
Tu ejemplo:
> 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
Acerca del rendimiento: ahora tengo idea de cuán bueno es este enfoque para las matrices grandes. Complejidad, esto debería estar cerca de lo óptimo. Por lo general, apply
no es tan malo en el rendimiento también.
Editar
Ahora estaba curioso, ¿qué enfoque es el mejor? Un punto de referencia corto:
> 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
Por lo tanto: Aplicar supera la multiplicación de la matriz por un factor de 15. (Solo para comparación: MATLAB necesitó 0.10719 segundos). Los resultados realmente no sorprenden, ya que la conversión de la apply
se puede hacer en O (n ^ 2), mientras que la multiplicación de la matriz necesitará aprox. O (n ^ 2.7) cálculos. Por lo tanto, todas las optimizaciones que ofrece la multiplicación de matrices deberían perderse si n es lo suficientemente grande.
Aquí hay una implementación más eficiente usando el paquete matrixStats y una matriz de ejemplo más grande:
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