[R] elegant matrix creation

Kjetil Halvorsen kjetil at acelerate.com
Wed Jul 28 18:44:02 CEST 2004



Robin Hankin wrote:
> Hello everybody.
> 
> I am trying to reproduce a particular matrix in an elegant way.  If I
> have
> 
> jj1 <-
> structure(c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,
> 3,1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,2,3,
> 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,3,1,2,3,1,
> 2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,
> 2),.Dim = as.integer(c(9,9)))
> 
> [ image(jj1) is good here ] then I can get this with
> 
> kronecker(matrix(1,3,1),kronecker(1+outer(0:2,0:2,"+")%%3,matrix(1,1,3)))
> 
> I want to reproduce the following matrices in an equivalent way:
> 
> jj2 <- matrix(c(1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,
> 1,2,3,1,2,3,1,2,3,3,1,2,3,1,2,3,1,2,1,2,3,1,2,
> 3,1,2,3,3,1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1,3,
> 1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1),9,9)
> 
> jj3 <- structure(c(1,2,3,2,3,1,3,1,2,1,2,1,2,3,2,3,1,
> 3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1,2,3,2,3,
> 2,3,1,3,1,2,1,2,1,2,3,2,3,1,3,1,3,1,2,1,2,
> 3,2,3,1,3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1, 2),.Dim =
> as.integer(c(9,9)))
> 

some musings. You have not told us hove jj3 arises naturally, but its 
structure seems to have something to do with magic squares. So

library(magic) # on CRAN
is.magic(jj3) # TRUE
       This is not in accordance with my concept of magic squares, since 
an n*n magic square should have all the numbers from 1 to n^2 exactly 
once. But all rowSums and colSums are equal.

Note that if we view jj3 as a 3*3 block matrix, with each block
a 3*3 matrix, then all the blockx are generated rowwise the following 
way: Let x in 1:3 be the generator, and + be sum modulo 3, but we take 
the rep 3 and not 0.
Then we have

x       x        x
x+1     x+1      x+2
x+2     x        x

and the 3*3 matrix of the generators can be generated in the following way:

 > xx <- ((magic(3) %% 3)+1)[,3:1]
 > xx
      [,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    3    1
[3,]    3    1    2

 > "++" <- function(x,a) {
        if ( (x+a)%%3 == 0 ) 3 else (x+a) %% 3 }

 > makeBlock <- function(x) {
+    matrix( c( rep(x,3), rep("++"(x,1), 2), rep("++"(x,2), 2),
+               rep(x,2) ) , 3,3, byrow=TRUE)  }
 > makeBlock(1)
      [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    3
[3,]    3    1    1

 > ans <- matrix (NA,9,9)
 > for (i in 1:3) for (j in 1:3) {
+   ans[3*(i-1)+1:3, 3*(j-1)+1:3] <- makeBlock(xx[i,j]) }
 > ans
       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
  [1,]    1    1    1    2    2    2    3    3    3
  [2,]    2    2    3    3    3    1    1    1    2
  [3,]    3    1    1    1    2    2    2    3    3
  [4,]    2    2    2    3    3    3    1    1    1
  [5,]    3    3    1    1    1    2    2    2    3
  [6,]    1    2    2    2    3    3    3    1    1
  [7,]    3    3    3    1    1    1    2    2    2
  [8,]    1    1    2    2    2    3    3    3    1
  [9,]    2    3    3    3    1    1    1    2    2
 > ans ==jj3
       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
  [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [2,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [3,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [4,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [5,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [6,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [7,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [8,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
  [9,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE


Kjetil Halvorsen



> [ note that jj1-jj3 each have precisely 3 occurrences of A, B, and C
> along each row, column and (broken) diagonal ].
> 
> Can anyone give me a nice elegant way of creating jj2 and jj3 please?
>




More information about the R-help mailing list