Skip to contents

This vignette shows an easy way to work with submatrices and matrix lists.

The following functions apply to both rectangular and square matrices. In data analysis, a square matrix can emerge, for example, from covariance calculations, or by calculating the distances between all the points belonging to a given set;

(A, B, C)

   A  B  C
A  x  x  x
B  x  x  x
C  x  x  x

a rectangular matrix instead can still emerge between distance calculations, but between two sets with different number of points.

(A, B, C)
(D, E)

   A  B  C
D  x  x  x
E  x  x  x

Basic operations: mean, max, min

Given a matrix, it may be useful to consider its blocks and observe some essential characteristics of each block. To do this you can use the blockmean(), blockmax() and blockmin() functions that take a matrix and the block size as input and return the average, maximum and minimum values of each block respectively.

(mat1 <- matrix(1:64, nrow = 8, byrow = TRUE))
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]    1    2    3    4    5    6    7    8
#> [2,]    9   10   11   12   13   14   15   16
#> [3,]   17   18   19   20   21   22   23   24
#> [4,]   25   26   27   28   29   30   31   32
#> [5,]   33   34   35   36   37   38   39   40
#> [6,]   41   42   43   44   45   46   47   48
#> [7,]   49   50   51   52   53   54   55   56
#> [8,]   57   58   59   60   61   62   63   64

It is important that the blocks fill the entire matrix, that is, that the total number of rows and columns is a multiple of the number of rows and columns in the block. In this case, for example, blocks of size c(2,4), c(4,2) and so on are good. While it is possible to work with rectangular blocks, it is very often useful to work with square blocks. For example we define a 2x2 block and apply the functions:

blockmean(mat1, 2)
#>      [,1] [,2] [,3] [,4]
#> [1,]  5.5  7.5  9.5 11.5
#> [2,] 21.5 23.5 25.5 27.5
#> [3,] 37.5 39.5 41.5 43.5
#> [4,] 53.5 55.5 57.5 59.5

blockmax(mat1, 2)
#>      [,1] [,2] [,3] [,4]
#> [1,]   10   12   14   16
#> [2,]   26   28   30   32
#> [3,]   42   44   46   48
#> [4,]   58   60   62   64

blockmin(mat1, 2)
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    3    5    7
#> [2,]   17   19   21   23
#> [3,]   33   35   37   39
#> [4,]   49   51   53   55

If the block is square it is sufficient to insert only one dimension, while for a rectangular block a vector c(nrow_block, ncol_block) must be passed.

Lists of submatrices

In some situations it may be necessary to perform more complex operations on the blocks.

Suppose we want to multiply each block by a different integer. To do this it is convenient to have control over each block. We can collect all submatrices in one list using blocklist() function.

(list_matrix <- blocklist(mat1, 4))
#> $`1`
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    2    3    4
#> [2,]    9   10   11   12
#> [3,]   17   18   19   20
#> [4,]   25   26   27   28
#> 
#> $`2`
#>      [,1] [,2] [,3] [,4]
#> [1,]    5    6    7    8
#> [2,]   13   14   15   16
#> [3,]   21   22   23   24
#> [4,]   29   30   31   32
#> 
#> $`3`
#>      [,1] [,2] [,3] [,4]
#> [1,]   33   34   35   36
#> [2,]   41   42   43   44
#> [3,]   49   50   51   52
#> [4,]   57   58   59   60
#> 
#> $`4`
#>      [,1] [,2] [,3] [,4]
#> [1,]   37   38   39   40
#> [2,]   45   46   47   48
#> [3,]   53   54   55   56
#> [4,]   61   62   63   64

Like the previous functions, blocklist() takes the matrix and the size of the block as input.

An element of the list can be accessed with a double square bracket: list_matrix[[i]]; however, often for operations on lists it is possible to avoid having to access each element individually thanks to the lapply function.

We multiply each matrix in the list by a different number: the first by 4, the second by 9, the third by 16 and the fourth by 25.

lapply(1:4, function(i, l, v) l[[i]] * v[[i]], list_matrix, c(4, 9, 16, 25))
#> [[1]]
#>      [,1] [,2] [,3] [,4]
#> [1,]    4    8   12   16
#> [2,]   36   40   44   48
#> [3,]   68   72   76   80
#> [4,]  100  104  108  112
#> 
#> [[2]]
#>      [,1] [,2] [,3] [,4]
#> [1,]   45   54   63   72
#> [2,]  117  126  135  144
#> [3,]  189  198  207  216
#> [4,]  261  270  279  288
#> 
#> [[3]]
#>      [,1] [,2] [,3] [,4]
#> [1,]  528  544  560  576
#> [2,]  656  672  688  704
#> [3,]  784  800  816  832
#> [4,]  912  928  944  960
#> 
#> [[4]]
#>      [,1] [,2] [,3] [,4]
#> [1,]  925  950  975 1000
#> [2,] 1125 1150 1175 1200
#> [3,] 1325 1350 1375 1400
#> [4,] 1525 1550 1575 1600

dblocklist

The block diagonal of a matrix can be more importante than the off-diagonal blocks. You can collect the diagonal blocks in a list using the dblocklist() function analogous to blocklist(). The only trick: the blocks must fill the diagonal. This mathematically translates into the fact that the ratio between the number of rows in the matrix and the number of rows in the block must be equal to the ratio between the number of columns in the matrix and the number of columns in the block. Example: for a 16x8 matrix dblocklist() accepts 8x4, 4x2 blocks.

dblocklist(mat1, 2)
#> $`1`
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    9   10
#> 
#> $`2`
#>      [,1] [,2]
#> [1,]   19   20
#> [2,]   27   28
#> 
#> $`3`
#>      [,1] [,2]
#> [1,]   37   38
#> [2,]   45   46
#> 
#> $`4`
#>      [,1] [,2]
#> [1,]   55   56
#> [2,]   63   64

From list of matrices to single matrix

Suppose we need to calculate the mean distance over time between all pairs of two sets of points. For convenience we use list_matrix: each matrix kk in the list is a set of distances at time tkt_k.

The meanMatrix() function returns the mean of each element (i,j)(i, j) of matrix

meanMatrix(list_matrix)
#>      [,1] [,2] [,3] [,4]
#> [1,]   19   20   21   22
#> [2,]   27   28   29   30
#> [3,]   35   36   37   38
#> [4,]   43   44   45   46

Similarly, sumMatrix() and dotMatrix() functions return sum and product of each element (i,j)(i, j) of matrix of the list

sumMatrix(list_matrix)
#>      [,1] [,2] [,3] [,4]
#> [1,]   76   80   84   88
#> [2,]  108  112  116  120
#> [3,]  140  144  148  152
#> [4,]  172  176  180  184

dotMatrix(list_matrix)
#>         [,1]    [,2]    [,3]    [,4]
#> [1,]    6105   15504   28665   46080
#> [2,]  215865  270480  333465  405504
#> [3,]  927129 1069200 1225785 1397760
#> [4,] 2520825 2804880 3111129 3440640