私は次のようなマトリックスを持っています
A= [ 1 2 4
2 3 1
3 1 2 ]
行ごとと列ごとの累積合計を計算したいのですが、結果は次のようになります。
B = [ 1 3 7
3 8 13
6 12 19 ]
これをRですばやく作成する方法についてのアイデアはありますか?(おそらく関数cumsumを使用しています)(私は巨大な行列を持っています)
ありがとう!
私は次のようなマトリックスを持っています
A= [ 1 2 4
2 3 1
3 1 2 ]
行ごとと列ごとの累積合計を計算したいのですが、結果は次のようになります。
B = [ 1 3 7
3 8 13
6 12 19 ]
これをRですばやく作成する方法についてのアイデアはありますか?(おそらく関数cumsumを使用しています)(私は巨大な行列を持っています)
ありがとう!
ワンライナー:
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秒が必要です)。-versionapply
は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
私の解決策:関数cumsum_row()(以下を参照)は行列Mを取り、Mの行の累積合計の行列を返します。関数cumsum_col()は、列に対して同じことを行います。
cumsum_row <- function(M) {
M2 <- c()
for (i in 1:nrow(M))
M2 <- rbind(M2, cumsum(M[i,]))
return (M2)
}
cumsum_col <- function(M) {
return (t(cumsum_row(t(M))))
}
例:
> M <- matrix(rep(1, 9), nrow=3)
> M
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 1 1
[3,] 1 1 1
> cumsum_row(M)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 2 3
[3,] 1 2 3