2017-10-20 14 views
4

私は与えられたベクトルを持っていて、それをあるブロック行列に変換したいと思っています。この単純な例を考えてみましょう:ベクトルをブロック行列

k <- c(1,2,3) 
a <- rep(apply(expand.grid(k, k), 1, prod), each=3) 
a 
[1] 1 1 1 2 2 2 3 3 3 2 2 2 4 4 4 6 6 6 3 3 3 6 6 6 9 9 9 

このベクターは、フォームのブロック行列に並んでする必要があります。

rbind(
cbind(diag(a[1:3]), diag(a[4:6]), diag(a[7:9])), 
cbind(diag(a[10:12]), diag(a[13:15]), diag(a[16:18])), 
cbind(diag(a[19:21]), diag(a[22:24]), diag(a[25:27])) 
) 

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 1 0 0 2 0 0 3 0 0 
[2,] 0 1 0 0 2 0 0 3 0 
[3,] 0 0 1 0 0 2 0 0 3 
[4,] 2 0 0 4 0 0 6 0 0 
[5,] 0 2 0 0 4 0 0 6 0 
[6,] 0 0 2 0 0 4 0 0 6 
[7,] 3 0 0 6 0 0 9 0 0 
[8,] 0 3 0 0 6 0 0 9 0 
[9,] 0 0 3 0 0 6 0 0 9 

は今、これは当然のことながら、小型で簡単な例であり、私はこれをやりたいですはるかに大きなベクトル/行列。したがって、私の質問:特定の形式のブロック行列(ループなし)でベクトルを配置する一般的な方法はありますか?

+0

おそらく関連する投稿:https://stackoverflow.com/questions/17495841/block-diagonal-binding-of-matrices – zx8754

答えて

6

代わりに手動で分割を行って、我々は次のようにわずかに異なるベクトルにクロネッカー積を使用して代替がある%/%

k <- 3 
lst <- split(a, (seq_along(a)-1)%/%k + 1) 
do.call(rbind, lapply(split(lst, (seq_along(lst)-1) %/% k + 1), 
     function(x) do.call(cbind, lapply(x, function(y) diag(y))))) 
#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
# [1,] 1 0 0 2 0 0 3 0 0 
# [2,] 0 1 0 0 2 0 0 3 0 
# [3,] 0 0 1 0 0 2 0 0 3 
# [4,] 2 0 0 4 0 0 6 0 0 
# [5,] 0 2 0 0 4 0 0 6 0 
# [6,] 0 0 2 0 0 4 0 0 6 
# [7,] 3 0 0 6 0 0 9 0 0 
# [8,] 0 3 0 0 6 0 0 9 0 
# [9,] 0 0 3 0 0 6 0 0 9 
3

を使用することができます。新たに同じ順序でベクトルaのユニークな値である

# create initial vector 
aNew <- rep(1:3, 3) * rep(1:3, each=3) 
aNew 
[1] 1 2 3 2 4 6 3 6 9 

メモ、つまり、それはunique(a)と等価です。 aNewを3X3行列に変換してから、それと3X3単位行列に対してクロネッカー(Kronecker)プロダクトを実行します。

matrix(aNew, 3, 3) %x% diag(3) 
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 1 0 0 2 0 0 3 0 0 
[2,] 0 1 0 0 2 0 0 3 0 
[3,] 0 0 1 0 0 2 0 0 3 
[4,] 2 0 0 4 0 0 6 0 0 
[5,] 0 2 0 0 4 0 0 6 0 
[6,] 0 0 2 0 0 4 0 0 6 
[7,] 3 0 0 6 0 0 9 0 0 
[8,] 0 3 0 0 6 0 0 9 0 
[9,] 0 0 3 0 0 6 0 0 9