rmatrixplotlayout

Making Replicable Layout Matrices for R Plots


I am making a figure that has the following layout matrix.

(Individual_Layout_Matrix <- matrix(c(1, 1, 2, 3, 4, 4), byrow = TRUE, ncol = 2))

#      [,1] [,2]
# [1,]    1    1
# [2,]    2    3
# [3,]    4    4

This figure has a blank plot at the top for an overall figure title, two side-by-side plots, and a blank plot at the bottom for a legend.

I have a study with multiple levels of multiple factors and I want to create panels that follow this format where each panel contains a figure formatted exactly like my Individual_Layout_Matrix object above. (Actually, I want to create an algorithm that can handle other types of cases beyond mine too.)

The final figure I want to make will have the following layout matrix, with each panel in this layout matrix itself being comprised of my 4-panel figure from above.

(Overall_Layout_Matrix <- matrix(c(1, 1, 2, 2, 8, 3, 4, 5, 6, 8, 0, 7, 7, 0, 8), byrow = TRUE, ncol = 5))

#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    1    2    2    8
# [2,]    3    4    5    6    8
# [3,]    0    7    7    0    8

Therefore, if each plot is generated in succession and placed in the final plot layout matrix in order, the final layout matrix will have the following form.

(Final_Layout_Matrix <- matrix(c(1, 1, 1, 1, 5, 5, 5, 5, 29, 29, 2, 2, 3, 3, 6, 6, 7, 7, 29, 29, 4, 4, 4, 4, 8, 8, 8, 8, 29, 29, 9, 9, 13, 13, 17, 17, 21, 21, 30, 31, 10, 11, 14, 15, 18, 19, 22, 23, 30, 31, 12, 12, 16, 16, 20, 20, 24, 24, 30, 31, 0, 0, 25, 25, 25, 25, 0, 0, 32, 32, 0, 0, 26, 26, 27, 27, 0, 0, 32, 32, 0, 0, 28, 28, 28, 28, 0, 0, 32, 32), byrow = TRUE, ncol = 10))

#       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#  [1,]    1    1    1    1    5    5    5    5   29    29
#  [2,]    2    2    3    3    6    6    7    7   29    29
#  [3,]    4    4    4    4    8    8    8    8   29    29
#  [4,]    9    9   13   13   17   17   21   21   30    31
#  [5,]   10   11   14   15   18   19   22   23   30    31
#  [6,]   12   12   16   16   20   20   24   24   30    31
#  [7,]    0    0   25   25   25   25    0    0   32    32
#  [8,]    0    0   26   26   27   27    0    0   32    32
#  [9,]    0    0   28   28   28   28    0    0   32    32

I have two questions.


Solution

  • A messy piece of code:

    layout_augment <- function(x, y) {
      y_dim <- dim(y)
      y_max <- max(y)
      mat <- res <- kronecker(x, array(1, y_dim))
      for(i in unique(x[x != 0])) {
        z_ind <- which(mat == i, arr.ind = TRUE)
        z_dim <- apply(z_ind, 2, \(col) diff(range(col)) + 1)
        r <- z_dim / y_dim
        y2 <- y[rep(seq_len(y_dim[1]), each = r[1]),
                rep(seq_len(y_dim[2]), each = r[2])] + (i-1)*y_max
        if(nrow(z_ind) != length(y2)) {
          stop("number ", i, " does not appear in a standalone rectangle")
        }
        res[z_ind] <- y2
      }
      return(res)
    }
    

    Case 1

    layout_augment(Overall_Layout_Matrix, Individual_Layout_Matrix)
    
    #      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    # [1,]    1    1    1    1    5    5    5    5   29    29
    # [2,]    2    2    3    3    6    6    7    7   29    29
    # [3,]    4    4    4    4    8    8    8    8   29    29
    # [4,]    9    9   13   13   17   17   21   21   30    31
    # [5,]   10   11   14   15   18   19   22   23   30    31
    # [6,]   12   12   16   16   20   20   24   24   30    31
    # [7,]    0    0   25   25   25   25    0    0   32    32
    # [8,]    0    0   26   26   27   27    0    0   32    32
    # [9,]    0    0   28   28   28   28    0    0   32    32
    

    Case 2

    Bad_Layout_Matrix <- matrix(c(1, 1, 1, 2, 2, 3, 4, 4, 5, 4, 4, 4), byrow = TRUE, ncol = 3)
    layout_augment(Bad_Layout_Matrix, Individual_Layout_Matrix)
    

    Error in layout_augment(Bad_Layout_Matrix, Individual_Layout_Matrix) :
    number 4 does not appear in a standalone rectangle