Home > Enterprise >  R transform a list of vectors with differing lengths into a matrix
R transform a list of vectors with differing lengths into a matrix

Time:07-30

I have the following list that I would like to transform into the matrix M:

L<-list(c(2L, 29L, 30L), c(1L, 3L, 30L, 31L), c(2L, 31L, 32L), c(5L, 
60L), c(4L, 6L, 60L, 61L), c(5L, 7L, 61L, 62L))

[[1]]
[1]  2 29 30

[[2]]
[1]  1  3 30 31

[[3]]
[1]  2 31 32

[[4]]
[1]  5 60

[[5]]
[1]  4  6 60 61

[[6]]
[1]  5  7 61 62

Matrix M:

2 29 30 NA
1 3 30 31
2 31 32 NA
5 60 NA NA
4 6 60 61
5 7 61 62

I want each list to be a row of the matrix and to fill in any missing values with NA.

CodePudding user response:

Append NA at the end of each list element based on the max length of the list element with length<- and then use rbind with do.call

mx <- max(lengths(L))
do.call(rbind, lapply(L, `length<-`, mx))

-output

    [,1] [,2] [,3] [,4]
[1,]    2   29   30   NA
[2,]    1    3   30   31
[3,]    2   31   32   NA
[4,]    5   60   NA   NA
[5,]    4    6   60   61
[6,]    5    7   61   62

CodePudding user response:

You could also use stri_list2matrix function from stringi package. This converts the vectors of list to character matrix so you should convert it to numeric if necessary like this:

L<-list(c(2L, 29L, 30L), c(1L, 3L, 30L, 31L), c(2L, 31L, 32L), c(5L, 
                                                                 60L), c(4L, 6L, 60L, 61L), c(5L, 7L, 61L, 62L))


library(stringi)
m <- stri_list2matrix(L, byrow=TRUE)
class(m) <- "numeric"
m
#>      [,1] [,2] [,3] [,4]
#> [1,]    2   29   30   NA
#> [2,]    1    3   30   31
#> [3,]    2   31   32   NA
#> [4,]    5   60   NA   NA
#> [5,]    4    6   60   61
#> [6,]    5    7   61   62

Created on 2022-07-29 by the reprex package (v2.0.1)

CodePudding user response:

There would be better ways, but this works:

L<-list(c(2L, 29L, 30L), c(1L, 3L, 30L, 31L), c(2L, 31L, 32L), c(5L, 
60L), c(4L, 6L, 60L, 61L), c(5L, 7L, 61L, 62L))

out <- matrix(nrow=6, ncol=4)
for(i in 1:length(L)) {
  out[i, ] <- c(L[[i]], rep(NA, (4-length(L[[i]]))))
}

out

#      [,1] [,2] [,3] [,4]
# [1,]    2   29   30   NA
# [2,]    1    3   30   31
# [3,]    2   31   32   NA
# [4,]    5   60   NA   NA
# [5,]    4    6   60   61
# [6,]    5    7   61   62

CodePudding user response:

Another possible solution, based on purrr::map_dfr:

library(tidyverse)

map_dfr(L, ~ .x %>% set_names(LETTERS[1:length(.x)])) %>% 
  as.matrix %>% unname

#>      [,1] [,2] [,3] [,4]
#> [1,]    2   29   30   NA
#> [2,]    1    3   30   31
#> [3,]    2   31   32   NA
#> [4,]    5   60   NA   NA
#> [5,]    4    6   60   61
#> [6,]    5    7   61   62

And more simply:

tibble(L) %>% unnest_wider(L) %>% suppressMessages %>% as.matrix %>% unname
  •  Tags:  
  • r
  • Related