Block-diagonal matrices can be extracted or removed using two small functions implemented here, in addition, non-square matrices are supported.
Block diagonal matrices occur when we combine two dimensions of a data set along one edge of a matrix. For example, trade-flow data in the decompr and gvc package have each country-industry combination occur on each edge of the matrix.
m <- matrix(1:64, nrow=8)
m
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 1 9 17 25 33 41 49 57
## [2,] 2 10 18 26 34 42 50 58
## [3,] 3 11 19 27 35 43 51 59
## [4,] 4 12 20 28 36 44 52 60
## [5,] 5 13 21 29 37 45 53 61
## [6,] 6 14 22 30 38 46 54 62
## [7,] 7 15 23 31 39 47 55 63
## [8,] 8 16 24 32 40 48 56 64
We can now drop everything except a block diagonal.
library(diagonals)
block_matrix(m, steps=4)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 1 9 0 0 0 0 0 0
## [2,] 2 10 0 0 0 0 0 0
## [3,] 0 0 19 27 0 0 0 0
## [4,] 0 0 20 28 0 0 0 0
## [5,] 0 0 0 0 37 45 0 0
## [6,] 0 0 0 0 38 46 0 0
## [7,] 0 0 0 0 0 0 55 63
## [8,] 0 0 0 0 0 0 56 64
Or drop only the block diagonal.
minus_block_matrix(m, steps=2)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 0 0 0 0 33 41 49 57
## [2,] 0 0 0 0 34 42 50 58
## [3,] 0 0 0 0 35 43 51 59
## [4,] 0 0 0 0 36 44 52 60
## [5,] 5 13 21 29 0 0 0 0
## [6,] 6 14 22 30 0 0 0 0
## [7,] 7 15 23 31 0 0 0 0
## [8,] 8 16 24 32 0 0 0 0
The number of steps
can vary, but dimensions should be multiples of steps
. Alternatively we can specify the size of the size
of the step.
block_matrix(m, size=2)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 1 9 0 0 0 0 0 0
## [2,] 2 10 0 0 0 0 0 0
## [3,] 0 0 19 27 0 0 0 0
## [4,] 0 0 20 28 0 0 0 0
## [5,] 0 0 0 0 37 45 0 0
## [6,] 0 0 0 0 38 46 0 0
## [7,] 0 0 0 0 0 0 55 63
## [8,] 0 0 0 0 0 0 56 64
Even non-square matrices are supported, as long as each dimension is a multiple of size.
# create the matrix
nsm <- matrix(1:27, nrow=9, ncol=3 )
# test if the dimensions are multiples of size
# i.e. there are no remainders after the modulo division of dimensions by steps
dim(nsm) %% 3 # we will use 3 (three) steps
## [1] 0 0
Now extract the rectangular diagonal.
rectangle_matrix(nsm, steps=3)
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 2 0 0
## [3,] 3 0 0
## [4,] 0 13 0
## [5,] 0 14 0
## [6,] 0 15 0
## [7,] 0 0 25
## [8,] 0 0 26
## [9,] 0 0 27
Or this.
rectangle_matrix( t(nsm), steps=3 )
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
## [1,] 1 2 3 0 0 0 0 0 0
## [2,] 0 0 0 13 14 15 0 0 0
## [3,] 0 0 0 0 0 0 25 26 27
Lastly, we can also choose a replacement parameter other than zero.
block_matrix(m, steps=4, replacement=-1)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 1 9 -1 -1 -1 -1 -1 -1
## [2,] 2 10 -1 -1 -1 -1 -1 -1
## [3,] -1 -1 19 27 -1 -1 -1 -1
## [4,] -1 -1 20 28 -1 -1 -1 -1
## [5,] -1 -1 -1 -1 37 45 -1 -1
## [6,] -1 -1 -1 -1 38 46 -1 -1
## [7,] -1 -1 -1 -1 -1 -1 55 63
## [8,] -1 -1 -1 -1 -1 -1 56 64
or
minus_rectangle_matrix(nsm, steps=3, replacement=666)
## [,1] [,2] [,3]
## [1,] 666 10 19
## [2,] 666 11 20
## [3,] 666 12 21
## [4,] 4 666 22
## [5,] 5 666 23
## [6,] 6 666 24
## [7,] 7 16 666
## [8,] 8 17 666
## [9,] 9 18 666