John Abercrombie
John Abercrombie

Reputation: 61

Combining a list of matrices into a single matrix while appending new values to previous columns

So I have a list of a 17 matrices that I want to combine into a single master matrix. However, I also want different values for an observation to be appended instead of being overwritten. For a simplified example,

m1 <- matrix( c(1, 0, 0, 0, 1, 0, 0, 0, 1), nrow=3, ncol=3) 
rownames(m1) <- c("x", "y", "z")
colnames(m1) <- c("a", "b", "c")


m2 <- matrix( c(2, 0, 0, 0, 2, 0, 0, 0, 2), nrow=3, ncol=3)
rownames(m2) <- c("a", "d", "e")
colnames(m2) <- c("x", "w", "z")


m3_final <- matrix( c(0, 0, 0, 2, 0, "1;2", 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2), nrow=5, ncol=4)
rownames(m3_final) <- c("a", "b", "c", "d", "e")
colnames(m3_final) <- c("w", "x", "y", "z")

My current thoughts are to run a for loop through the list so that each matrix is iterated into an empty master matrix to begin with, but I am having trouble with appending a new result to a previous result. My current error:

m1 <- matrix( c(1, 0, 0, 0, 1, 0, 0, 0, 1), nrow=3, ncol=3) 
rownames(m1) <- c("x", "y", "z")
colnames(m1) <- c("a", "b", "c")


m2 <- matrix( c(2, 0, 0, 0, 2, 0, 0, 0, 2), nrow=3, ncol=3)
rownames(m2) <- c("a", "d", "e")
colnames(m2) <- c("x", "w", "z")


m3_final <- matrix( c(0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2), nrow=5, ncol=4)
rownames(m3_final) <- c("a", "b", "c", "d", "e")
colnames(m3_final) <- c("w", "x", "y", "z")

Thanks for any help!

Upvotes: 2

Views: 208

Answers (1)

lroha
lroha

Reputation: 34566

One way (which may not win points for efficiency) is to flatten the matrices, bind them, and then reshape them back to wide format concatenating the values of common indices with paste().

library(dplyr)
library(tidyr)
library(purrr)
library(tibble)

list(m1, m2) %>%
  map_df(as.data.frame.table) %>%
  filter(Freq != 0) %>%
  pivot_wider(names_from = Var1, values_from = Freq, values_fn = list(Freq = ~ paste(.x, collapse = ";")), values_fill = list(Freq = "0")) %>% 
  select(Var2, sort(tidyselect::peek_vars())) %>%
  column_to_rownames(var = "Var2") %>%
  as.matrix()

  w   x     y   z  
a "0" "1;2" "0" "0"
b "0" "0"   "1" "0"
c "0" "0"   "0" "1"
d "2" "0"   "0" "0"
e "0" "0"   "0" "2"

Note that you mixed up the row and column names in one of the matrices in your example.

Upvotes: 1

Related Questions