Function to construct a block diagonal matrix from (a list of) matrices.

bldiag(..., order)

Arguments

...

individual matrices or a list of matrices.

order

optional argument to specify a variable based on which a square block diagonal matrix should be ordered.

Author

Posted to R-help by Berton Gunter (2 Sep 2005) with some further adjustments by Wolfgang Viechtbauer (wvb@metafor-project.org, https://www.metafor-project.org).

See also

rma.mv for the model fitting function that can take such a block diagonal matrix as input (for the V argument).

blsplit for a function that can split a block diagonal matrix into a list of sub-matrices.

Examples

### copy data into 'dat'
dat <- dat.berkey1998
dat
#> 
#>    trial           author year ni outcome      yi     vi    v1i    v2i 
#> 1      1 Pihlstrom et al. 1983 14      PD  0.4700 0.0075 0.0075 0.0030 
#> 2      1 Pihlstrom et al. 1983 14      AL -0.3200 0.0077 0.0030 0.0077 
#> 3      2    Lindhe et al. 1982 15      PD  0.2000 0.0057 0.0057 0.0009 
#> 4      2    Lindhe et al. 1982 15      AL -0.6000 0.0008 0.0009 0.0008 
#> 5      3   Knowles et al. 1979 78      PD  0.4000 0.0021 0.0021 0.0007 
#> 6      3   Knowles et al. 1979 78      AL -0.1200 0.0014 0.0007 0.0014 
#> 7      4  Ramfjord et al. 1987 89      PD  0.2600 0.0029 0.0029 0.0009 
#> 8      4  Ramfjord et al. 1987 89      AL -0.3100 0.0015 0.0009 0.0015 
#> 9      5    Becker et al. 1988 16      PD  0.5600 0.0148 0.0148 0.0072 
#> 10     5    Becker et al. 1988 16      AL -0.3900 0.0304 0.0072 0.0304 
#> 

### construct list with the variance-covariance matrices of the observed outcomes for the studies
V <- lapply(split(dat[c("v1i","v2i")], dat$trial), as.matrix)
V
#> $`1`
#>      v1i    v2i
#> 1 0.0075 0.0030
#> 2 0.0030 0.0077
#> 
#> $`2`
#>      v1i   v2i
#> 3 0.0057 9e-04
#> 4 0.0009 8e-04
#> 
#> $`3`
#>      v1i    v2i
#> 5 0.0021 0.0007
#> 6 0.0007 0.0014
#> 
#> $`4`
#>      v1i    v2i
#> 7 0.0029 0.0009
#> 8 0.0009 0.0015
#> 
#> $`5`
#>       v1i    v2i
#> 9  0.0148 0.0072
#> 10 0.0072 0.0304
#> 

### construct block diagonal matrix
V <- bldiag(V)
V
#>         [,1]   [,2]   [,3]  [,4]   [,5]   [,6]   [,7]   [,8]   [,9]  [,10]
#>  [1,] 0.0075 0.0030 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [2,] 0.0030 0.0077 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [3,] 0.0000 0.0000 0.0057 9e-04 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [4,] 0.0000 0.0000 0.0009 8e-04 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [5,] 0.0000 0.0000 0.0000 0e+00 0.0021 0.0007 0.0000 0.0000 0.0000 0.0000
#>  [6,] 0.0000 0.0000 0.0000 0e+00 0.0007 0.0014 0.0000 0.0000 0.0000 0.0000
#>  [7,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0029 0.0009 0.0000 0.0000
#>  [8,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0009 0.0015 0.0000 0.0000
#>  [9,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0148 0.0072
#> [10,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0072 0.0304

### if we split based on 'author', the list elements in V are in a different order than tha data
V <- lapply(split(dat[c("v1i","v2i")], dat$author), as.matrix)
V
#> $`Becker et al.`
#>       v1i    v2i
#> 9  0.0148 0.0072
#> 10 0.0072 0.0304
#> 
#> $`Knowles et al.`
#>      v1i    v2i
#> 5 0.0021 0.0007
#> 6 0.0007 0.0014
#> 
#> $`Lindhe et al.`
#>      v1i   v2i
#> 3 0.0057 9e-04
#> 4 0.0009 8e-04
#> 
#> $`Pihlstrom et al.`
#>      v1i    v2i
#> 1 0.0075 0.0030
#> 2 0.0030 0.0077
#> 
#> $`Ramfjord et al.`
#>      v1i    v2i
#> 7 0.0029 0.0009
#> 8 0.0009 0.0015
#> 

### can use 'order' argument to reorder the block-diagonal matrix into the correct order
V <- bldiag(V, order=dat$author)
V
#>         [,1]   [,2]   [,3]  [,4]   [,5]   [,6]   [,7]   [,8]   [,9]  [,10]
#>  [1,] 0.0075 0.0030 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [2,] 0.0030 0.0077 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [3,] 0.0000 0.0000 0.0057 9e-04 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [4,] 0.0000 0.0000 0.0009 8e-04 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
#>  [5,] 0.0000 0.0000 0.0000 0e+00 0.0021 0.0007 0.0000 0.0000 0.0000 0.0000
#>  [6,] 0.0000 0.0000 0.0000 0e+00 0.0007 0.0014 0.0000 0.0000 0.0000 0.0000
#>  [7,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0029 0.0009 0.0000 0.0000
#>  [8,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0009 0.0015 0.0000 0.0000
#>  [9,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0148 0.0072
#> [10,] 0.0000 0.0000 0.0000 0e+00 0.0000 0.0000 0.0000 0.0000 0.0072 0.0304