Dynamic matrix from vectors

Viewed 64

when creating a dynamic matrix from these vectors

V1 <- c(13, 31, 54)
name1 <- c("a", "b2", "c")
V2 <- c(17, 27, 34, 52)
name2 <- c("a", "b1", "b2", "c")
V3  <- c(19, 25, 33, 47, 58, 44)
name3 <- c("a", "b1", "b2", "b3", "c", "d")
V4  <- c(13, 29, 35, 56)
name4 <- c("a", "b1", "b2", "c")
V5<-c(21, 35, 67, 82, 96)
name5<-c("d", "c", "b3", "b1", "b2")
names(V1) <- name1
names(V2) <- name2
names(V3) <- name3
names(V4) <- name4
names(V5) <- name5

and using this code to create a matrix

lst1 <- mget(ls(pattern = '^V\\d+$'))
t(sapply(lst1, `length<-`, max(lengths(lst1))))
lst2 <- mget(ls(pattern = '^name\\d+$'))
library(purrr)    
map2_dfr(lst1, lst2, setNames)

How can I add a column as seen in the picture below with vector names without changing the structure of the matrix?

enter image description here

3 Answers

You can use the ls argument that you had used to capture the variables and assign the rownames.

result <- data.frame(purrr::map2_dfr(lst1, lst2, setNames))
rownames(result) <- ls(pattern = '^V\\d+$')
result

#    a b2  c b1 b3  d
#V1 13 31 54 NA NA NA
#V2 17 34 52 27 NA NA
#V3 19 33 58 25 47 44
#V4 13 35 56 29 NA NA
#V5 NA 96 35 82 67 21

We can also use bind_rows

library(dplyr)
`row.names<-`(as.data.frame(bind_rows(Map(setNames, lst1, lst2))), 
          ls(pattern = '^V\\d+$'))
#   a b2  c b1 b3  d
#V1 13 31 54 NA NA NA
#V2 17 34 52 27 NA NA
#V3 19 33 58 25 47 44
#V4 13 35 56 29 NA NA
#V5 NA 96 35 82 67 21

As an alternative, you can go directly from lst1 to the matrix in just a few steps. lst2 is not required.

lst1 <- mget(ls(pattern = '^V\\d+$'))

# For column names
col <- unlist(sapply(lst1, names), use.names=FALSE)

# An empty matrix. 
# Rows are named after each list item
# Columns are the unique values from "col"
m <- matrix(NA, nrow = length(lst1), ncol = length(unique(col)), 
            dimnames = list(names(lst1), unique(col)))

# Using the lengths of each list to identify the rows,
# and matching col with unique column names, 
# fill in the values by unlisting your list
m[cbind(rep(seq_along(lst1), lengths(lst1)), 
  match(col, colnames(m)))] <- unlist(lst1, use.names=FALSE)
#     a b2  c b1 b3  d
# V1 13 31 54 NA NA NA
# V2 17 34 52 27 NA NA
# V3 19 33 58 25 47 44
# V4 13 35 56 29 NA NA
# V5 NA 96 35 82 67 21
Related