transpose nested list

后端 未结 5 1740
误落风尘
误落风尘 2021-01-19 03:27

I have a list structure which represents a table being handed to me like this

> l = list(list(1, 4), list(2, 5), list(3, 6))
> str(l)
List of 3
 $ :Lis         


        
相关标签:
5条回答
  • 2021-01-19 03:46

    A second base R method using Reduce and split in two lines is

    # bind lists together into a matrix (of lists)
    temp <- Reduce(rbind, l)
    # split unlisted values using indices of columns
    split(unlist(temp), col(temp))
    $`1`
    [1] 1 2 3
    
    $`2`
    [1] 4 5 6
    

    this assumes that each list item has the same number of elements. You can add names in the second line if desired with setNames:

    setNames(split(unlist(temp), col(temp)), c("x", "y"))
    
    0 讨论(0)
  • 2021-01-19 03:51

    For the specific example, you can use this pretty simple approach:

    split(unlist(l), c("x", "y"))
    #$x
    #[1] 1 2 3
    #
    #$y
    #[1] 4 5 6
    

    It recycles the x-y vector and splits on that.


    To generalize this to "n" elements in each list, you can use:

    l = list(list(1, 4, 5), list(2, 5, 5), list(3, 6, 5)) # larger test case
    
    split(unlist(l, use.names = FALSE), paste0("x", seq_len(length(l[[1L]]))))
    # $x1
    # [1] 1 2 3
    # 
    # $x2
    # [1] 4 5 6
    # 
    # $x3
    # [1] 5 5 5
    

    This assumes, that all the list elements on the top-level of l have the same length, as in your example.

    0 讨论(0)
  • 2021-01-19 03:58

    The sapply extracts the ith element of each component of l creating a numeric vector and the lapply applies it over 1:2 (since there are k=2 elements in each component of l).

    If you know that k is 2 then the first line could be replaced with k <- 2. Also note that in the first line we divide by max(..., 1) to avoid dividing by 0 in the case that l is a zero length list.

    The code below gives the output shown in the question; however, the subject refers to nested lists and if we wanted a list of lists rather than a list of numeric vectors then we could replace sapply with lapply.

    k <- length(unlist(l)) / max(length(l) , 1)
    lapply(seq_len(k), function(i) sapply(l, "[[", i))
    

    giving:

    [[1]]
    [1] 1 2 3
    
    [[2]]
    [1] 4 5 6
    
    0 讨论(0)
  • 2021-01-19 04:06

    Here is one idea with unlisting each list i.e.

    split(do.call(cbind, lapply(l, unlist)), seq(unique(lengths(l))))
    

    which gives,

    $`1`
    [1] 1 2 3
    
    $`2`
    [1] 4 5 6
    
    0 讨论(0)
  • 2021-01-19 04:07

    We can use

    library(tidyverse)
    r1 <- l %>% 
            transpose %>%
            map(unlist)
    identical(r1, unname(lt))
    #[1] TRUE
    
    0 讨论(0)
提交回复
热议问题