Search code examples
rmatrixcombinations

Adding together all combinations of matrices in R so I can call the names later


I have several Matrices of count variables that we can represent as below:

P <- matrix(c(1, 2 ,0, 2, 5, 1, 0, 6, 1), nrow = 3)
Q <- matrix(c(1, 0, 0, 2, 3, 1, 0, 4, 1), nrow = 3)
R <- matrix(c(2, 1, 1, 5, 6, 4, 0, 4, 1), nrow = 3)
S <- matrix(c(9, 7, 5, 4, 7, 3, 2, 6, 3), nrow = 3)

I want to create all combinations of adding these matrices together. Eg. P+Q, P+R, P+S, Q+R, Q+S, R+S, P+Q+R, P+R+S, P+Q+S, Q+R+S...

I know how to manually run this:

PQ <-P+Q

> PQ
     [,1] [,2] [,3]
[1,]    2    4    0
[2,]    2    8   10
[3,]    0    2    2

PQR <- P+Q+R

> PQR
     [,1] [,2] [,3]
[1,]    4    9    0
[2,]    3   14   14
[3,]    1    6    3

But my real dataset has 9 matrices, and that means 501 combinations, which would take a very long time to write out.

So I tried this:

# generate all possible combinations of the matrices
combs <- combn(list(P, Q, R, S), 2, simplify = FALSE)

print(combs)

# sum the matrices in each combination
sums <- lapply(combs, function(x) Reduce("+", x))


# print the result
print(sums)

Which on one hand, does seem to work to make all the combinations. But it does not allow me to know which combination is which.

How can I add all the matrices together and make sure that the names reflect which matrices are being added so that I can call them later?


Solution

  • You can try the code below

    lst <- list(P = P, Q = Q, R = R, S = S)
    out <- do.call(
        c,
        lapply(
            2:length(lst),
            \(k) unlist(
                combn(lst,
                    k, \(...)
                    setNames(
                        list(Reduce(`+`, ...)),
                        paste0(names(...), collapse = "")
                    ),
                    simplify = FALSE
                ),
                recursive = FALSE
            )
        )
    )
    

    where out gives

    $PQ
         [,1] [,2] [,3]
    [1,]    2    4    0
    [2,]    2    8   10
    [3,]    0    2    2
    
    $PR
         [,1] [,2] [,3]
    [1,]    3    7    0
    [2,]    3   11   10
    [3,]    1    5    2
    
    $PS
         [,1] [,2] [,3]
    [1,]   10    6    2
    [2,]    9   12   12
    [3,]    5    4    4
    
    $QR
         [,1] [,2] [,3]
    [1,]    3    7    0
    [2,]    1    9    8
    [3,]    1    5    2
    
    $QS
         [,1] [,2] [,3]
    [1,]   10    6    2
    [2,]    7   10   10
    [3,]    5    4    4
    
    $RS
         [,1] [,2] [,3]
    [1,]   11    9    2
    [2,]    8   13   10
    [3,]    6    7    4
    
    $PQR
         [,1] [,2] [,3]
    [1,]    4    9    0
    [2,]    3   14   14
    [3,]    1    6    3
    
    $PQS
         [,1] [,2] [,3]
    [1,]   11    8    2
    [2,]    9   15   16
    [3,]    5    5    5
    
    $PRS
         [,1] [,2] [,3]
    [1,]   12   11    2
    [2,]   10   18   16
    [3,]    6    8    5
    
    $QRS
         [,1] [,2] [,3]
    [1,]   12   11    2
    [2,]    8   16   14
    [3,]    6    8    5
    
    $PQRS
         [,1] [,2] [,3]
    [1,]   13   13    2
    [2,]   10   21   20
    [3,]    6    9    6
    

    If you want to create variables PQ, PQR and so on as shown in the names of out, you can further use list2env

    list2env(out, envir = .GlobalEnv)