【问题标题】:Unnest multiple columns取消嵌套多个列
【发布时间】:2022-01-10 15:50:24
【问题描述】:

我有这种类型的数据有多个列表列:

df <- structure(list(go = c("go after it", "here we go", "he went bust", 
                            "go get it go", "i 'm gonna go", "she 's going berserk"), left = list(
                              "", "we", "he", c("", "it"), c("'m", "gonna"), "'s"), node = list(
                                "go", "go", "went", c("go", "go"), c("gonna", "go"), "going"), 
                     right = list("after", "", "bust", c("get", ""), c("go", ""
                     ), "berserk")), class = "data.frame", row.names = c(NA, -6L
                     ))

我的目标是取消列出leftnoderight 这三个列。 unnest_longerunnest_auto 似乎都是朝着正确方向迈出的一步,但我不确定如何从那里着手:

library(tidyr)
df %>%
  unnest_longer(node) # or:   unnest_auto(node)
# A tibble: 8 × 4
  go                   left      node   right    
  <chr>                <list>    <chr>  <list>   
1 go after it          <chr [0]> go     <chr [1]>
2 here we go           <chr [1]> go     <chr [0]>
3 he went bust         <chr [1]> went   <chr [1]>
4 go get it go         <chr [1]> go     <chr [1]>
5 go get it go         <chr [1]> go     <chr [1]>
6 i 'm gon na go       <chr [2]> gon na <chr [1]>
7 i 'm gon na go       <chr [2]> go     <chr [1]>
8 she 's going berserk <chr [1]> going  <chr [1]>

预期结果是这样的:

# go                         left      node     right  
# <chr>                      <chr>    <chr>     <chr>  
# 1 go after it                         go       after  
# 2 here we go                 we       go       
# 3 he went bust               he       went     bust   
# 4 go get it go                        go       get    
# 5 go get it go               it       go           
# 6 i 'm gon na go             'm       gon na   go     
# 7 i 'm gon na go         gon na       go            
# 8 she 's going berserk       's       going    berserk 

【问题讨论】:

    标签: r tidyr


    【解决方案1】:
    library(tidyverse)
    
    df %>% unnest(c(left, node, right), keep_empty = TRUE)
    #> # A tibble: 8 × 4
    #>   go                   left    node  right    
    #>   <chr>                <chr>   <chr> <chr>    
    #> 1 go after it          ""      go    "after"  
    #> 2 here we go           "we"    go    ""       
    #> 3 he went bust         "he"    went  "bust"   
    #> 4 go get it go         ""      go    "get"    
    #> 5 go get it go         "it"    go    ""       
    #> 6 i 'm gonna go        "'m"    gonna "go"     
    #> 7 i 'm gonna go        "gonna" go    ""       
    #> 8 she 's going berserk "'s"    going "berserk"
    

    reprex package (v2.0.1) 于 2021-12-04 创建

    【讨论】:

      【解决方案2】:

      我们可能会使用where

      library(dplyr)
      library(tidyr)
      library(purrr)
      df %>% 
         mutate(mx = invoke(pmax, across(where(is.list), lengths))) %>% 
         mutate(across(where(is.list), ~ map2(.x, mx, ~ {
              length(.x) <- .y
              if(cur_column() == "left") .x <- .x[order(!is.na(.x))]
              .x})), mx = NULL) %>%
         unnest(where(is.list))
      # A tibble: 8 × 4
        go                   left  node   right  
        <chr>                <chr> <chr>  <chr>  
      1 go after it          <NA>  go     after  
      2 here we go           we    go     <NA>   
      3 he went bust         he    went   bust   
      4 go get it go         <NA>  go     get    
      5 go get it go         it    go     <NA>   
      6 i 'm gon na go       'm    gon na go     
      7 i 'm gon na go       na    go     <NA>   
      8 she 's going berserk 's    going  berserk
      

      更新

      基于 OP 的 cmets,以前的解决方案有效

      df %>%
          unnest(where(is.list))
      

      如果有NULL元素,指定keep_empty = TRUE(在OP的数据中,一些元素是空白的("")而不是NULL,所以前一个应该也可以工作

      df %>%
           unnest(where(is.list), keep_empty = TRUE)
      # A tibble: 8 × 4
        go                   left    node  right    
        <chr>                <chr>   <chr> <chr>    
      1 go after it          ""      go    "after"  
      2 here we go           "we"    go    ""       
      3 he went bust         "he"    went  "bust"   
      4 go get it go         ""      go    "get"    
      5 go get it go         "it"    go    ""       
      6 i 'm gonna go        "'m"    gonna "go"     
      7 i 'm gonna go        "gonna" go    "" 
      

      【讨论】:

      • 亲爱的@akrun,请接受我诚挚的歉意:因为你怀疑我确实发布了错误的df。我现在已经更新了。使用更新的数据框,您的原始解决方案 df %&gt;% unnest(where(is.list)) 可以完美运行。非常感谢。请更新,以便我接受您的回答!
      • 再次抱歉输入错误。现在它应该是正确的数据。再次感谢!
      • @akrun 发布的两种解决方案都能完美运行!
      猜你喜欢
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-18
      • 2021-10-01
      • 1970-01-01
      • 2018-09-16
      • 2015-03-06
      相关资源
      最近更新 更多