代码之家  ›  专栏  ›  技术社区  ›  Steven M. Mortimer

平整度的可控水平

  •  2
  • Steven M. Mortimer  · 技术社区  · 6 年前

    在下面的示例中,我有一个列表,其中一个元素是带有子列表的列表。看来 as_tibble() 在停止之前,正在向下展平,直到列表的第三级。如果能够控制扁平化,那么我就可以在元素中使用子列表保留整个列表,这将是一件好事 "c" 示例的。我怀疑 map() ,则, flatten() 等,但无法解决。

    复制的问题

    as\u tible() 返回2行,但我实际上只需要1行,其中一列对应于每个列表元素(“a”、“b”、“c”)。

    library(dplyr)
    x <- list(a = 1, 
              b = 2, 
              c = list(x=list(y=3, 
                              z=4), 
                       xx=NULL))
    parsed <- as_tibble(x)
    parsed
    #> # A tibble: 2 x 3
    #>       a     b c         
    #>   <dbl> <dbl> <list>    
    #> 1    1.    2. <list [2]>
    #> 2    1.    2. <NULL>
    
    parsed[1,]$c
    #> $x
    #> $x$y
    #> [1] 3
    #> $x$z
    #> [1] 4
    
    parsed[2,]$c
    #> $xx
    #> NULL
    

    期望的行为,其中我仅取消第一级

    parsed <- as_tibble(x)
    parsed
    #> # A tibble: 1 x 3
    #>       a     b c         
    #>   <dbl> <dbl> <list>    
    #> 1    1.    2. <list [2]>
    
    parsed[1,]$c
    #> $x
    #> $x$y
    #> [1] 3
    #> $x$z
    #> [1] 4
    #> $xx
    #> NULL
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Steven M. Mortimer    6 年前

    这并不优雅,但这里有一种方法。

    library(purrr)
    x <- list(a = 1, 
              b = 2, 
              c = list(x=list(y=3, 
                              z=4), 
                       xx=NULL))
    
    # define a function to preserve the list
    unnest_one_level <- function(x){
      if(is.list(x)) list(x) else x
    }
    
    res <- x %>% map_dfr(unnest_one_level)
    res
    #> # A tibble: 1 x 3
    #>       a     b c         
    #>   <dbl> <dbl> <list>    
    #> 1    1.    2. <list [2]>
    
    res$c
    #> [[1]]
    #> [[1]]$x
    #> [[1]]$x$y
    #> [1] 3
    #> 
    #> [[1]]$x$z
    #> [1] 4
    #> 
    #> [[1]]$xx
    #> NULL
    
        2
  •  1
  •   MrFlick    6 年前

    像tibble将重复每个列,循环每个列的值,直到它们都有一个共享的元素数。给你 a b 长度为1,但 c 长度为2。所以看起来你真的想把它当作一个长度为1的列表,你只需要把它嵌套在一个列表中。我想这至少在这种情况下会满足你的要求。

    parsed <- as_tibble(modify_if(x, ~length(.x)>1, list))