3

I'm working in R and I have a matrix with dimensions 6n x 6n. I would like to replace all elements out of a 6x6 block diagonal matrix with zero. Any suggestions?

For example (reporting just a 12x12 sample)

# create a sample 12x12 matrix
> mat <- matrix(1:144, nrow=12, ncol=12)
> mat
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] 
 [1,]    1   13   25   37   49   61   73   85   97   109   121   133
 [2,]    2   14   26   38   50   62   74   86   98   110   122   134
 [3,]    3   15   27   39   51   63   75   87   99   111   123   135
 [4,]    4   16   28   40   52   64   76   88  100   112   124   136
 [5,]    5   17   29   41   53   65   77   89  101   113   125   137
 [6,]    6   18   30   42   54   66   78   90  102   114   126   138
 [7,]    7   19   31   43   55   67   79   91  103   115   127   139
 [8,]    8   20   32   44   56   68   80   92  104   116   128   140
 [9,]    9   21   33   45   57   69   81   93  105   117   129   141
[10,]   10   22   34   46   58   70   82   94  106   118   130   142
[11,]   11   23   35   47   59   71   83   95  107   119   131   143
[12,]   12   24   36   48   60   72   84   96  108   120   132   144

What I would like to obtain is

new_mat
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] 
 [1,]    1   13   25   37   49   61    0    0    0     0     0     0  
 [2,]    2   14   26   38   50   62    0    0    0     0     0     0  
 [3,]    3   15   27   39   51   63    0    0    0     0     0     0 
 [4,]    4   16   28   40   52   64    0    0    0     0     0     0  
 [5,]    5   17   29   41   53   65    0    0    0     0     0     0  
 [6,]    6   18   30   42   54   66    0    0    0     0     0     0  
 [7,]    0    0    0    0    0    0   79   91  103   115   127   139
 [8,]    0    0    0    0    0    0   80   92  104   116   128   140
 [9,]    0    0    0    0    0    0   81   93  105   117   129   141
[10,]    0    0    0    0    0    0   82   94  106   118   130   142
[11,]    0    0    0    0    0    0   83   95  107   119   131   143
[12,]    0    0    0    0    0    0   84   96  108   120   132   144
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
gcoder
  • 41
  • 6

4 Answers4

5

Take the kronecker product of an identity matrix and a matrix of all 1's and multiply mat by that.

mat * (diag(nrow(mat) / 6) %x% matrix(1, 6, 6))

giving:

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1   13   25   37   49   61    0    0    0     0     0     0
 [2,]    2   14   26   38   50   62    0    0    0     0     0     0
 [3,]    3   15   27   39   51   63    0    0    0     0     0     0
 [4,]    4   16   28   40   52   64    0    0    0     0     0     0
 [5,]    5   17   29   41   53   65    0    0    0     0     0     0
 [6,]    6   18   30   42   54   66    0    0    0     0     0     0
 [7,]    0    0    0    0    0    0   79   91  103   115   127   139
 [8,]    0    0    0    0    0    0   80   92  104   116   128   140
 [9,]    0    0    0    0    0    0   81   93  105   117   129   141
[10,]    0    0    0    0    0    0   82   94  106   118   130   142
[11,]    0    0    0    0    0    0   83   95  107   119   131   143
[12,]    0    0    0    0    0    0   84   96  108   120   132   144
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
2

Try

library(Matrix)
as.matrix(bdiag(replicate(2, matrix(1, 6, 6), simplify = FALSE)) * mat)

-output

       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1   13   25   37   49   61    0    0    0     0     0     0
 [2,]    2   14   26   38   50   62    0    0    0     0     0     0
 [3,]    3   15   27   39   51   63    0    0    0     0     0     0
 [4,]    4   16   28   40   52   64    0    0    0     0     0     0
 [5,]    5   17   29   41   53   65    0    0    0     0     0     0
 [6,]    6   18   30   42   54   66    0    0    0     0     0     0
 [7,]    0    0    0    0    0    0   79   91  103   115   127   139
 [8,]    0    0    0    0    0    0   80   92  104   116   128   140
 [9,]    0    0    0    0    0    0   81   93  105   117   129   141
[10,]    0    0    0    0    0    0   82   94  106   118   130   142
[11,]    0    0    0    0    0    0   83   95  107   119   131   143
[12,]    0    0    0    0    0    0   84   96  108   120   132   144
akrun
  • 874,273
  • 37
  • 540
  • 662
1

You can also do the replacement directly. One benefit of this approach is that it does not depend on the type of the matrix or the replacement value.

## Number of rows in square matrix
n <- nrow(mat)
## Number of rows in rectangular block
b <- 6L

## Index of block diagonal elements
k <- sequence(rep.int(b, n), 
              rep(seq.int(1L, n, b), each = b) + seq.int(0L, n * n - 1L, n))

## Replacement
mat[-k] <- 0L
mat
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1   13   25   37   49   61    0    0    0     0     0     0
 [2,]    2   14   26   38   50   62    0    0    0     0     0     0
 [3,]    3   15   27   39   51   63    0    0    0     0     0     0
 [4,]    4   16   28   40   52   64    0    0    0     0     0     0
 [5,]    5   17   29   41   53   65    0    0    0     0     0     0
 [6,]    6   18   30   42   54   66    0    0    0     0     0     0
 [7,]    0    0    0    0    0    0   79   91  103   115   127   139
 [8,]    0    0    0    0    0    0   80   92  104   116   128   140
 [9,]    0    0    0    0    0    0   81   93  105   117   129   141
[10,]    0    0    0    0    0    0   82   94  106   118   130   142
[11,]    0    0    0    0    0    0   83   95  107   119   131   143
[12,]    0    0    0    0    0    0   84   96  108   120   132   144

Having said that, for matrices of type "double" or "complex", multiplying elementwise by a suitable Kronecker product is probably the right (most transparent) answer.

Mikael Jagan
  • 9,012
  • 2
  • 17
  • 48
1

You can use kronecker like below to create a mask matrix

> mat * kronecker(diag(c(1, 1)), matrix(1, 6, 6))
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1   13   25   37   49   61    0    0    0     0     0     0
 [2,]    2   14   26   38   50   62    0    0    0     0     0     0
 [3,]    3   15   27   39   51   63    0    0    0     0     0     0
 [4,]    4   16   28   40   52   64    0    0    0     0     0     0
 [5,]    5   17   29   41   53   65    0    0    0     0     0     0
 [6,]    6   18   30   42   54   66    0    0    0     0     0     0
 [7,]    0    0    0    0    0    0   79   91  103   115   127   139
 [8,]    0    0    0    0    0    0   80   92  104   116   128   140
 [9,]    0    0    0    0    0    0   81   93  105   117   129   141
[10,]    0    0    0    0    0    0   82   94  106   118   130   142
[11,]    0    0    0    0    0    0   83   95  107   119   131   143
[12,]    0    0    0    0    0    0   84   96  108   120   132   144
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81