簡體   English   中英

如何使用 dplyr 管道一次性取消嵌套數據幀的多個列表列

[英]How to unnest multiple list columns of a dataframe in one go with dplyr pipe

我有以下小標題,它有兩個嵌套列:

library(tidyverse)
df <- structure(list(a = list(c("a", "b"), "c"), b = list(c("1", "2", 
"3"), "3"), c = c(11, 22)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -2L))

產生:

# A tibble: 2 x 3
  a         b             c
  <list>    <list>    <dbl>
1 <chr [2]> <chr [3]>    11
2 <chr [1]> <chr [1]>    22

我怎樣才能一次將它們解開,產生一個小標題?

我試過這個但失敗了:

> df %>% unnest(a, b)
Error: All nested columns must have the same number of elements.

可能有一種更清潔的方法,但如果你想要列的笛卡爾積,你可以按順序取消它們,如果沒有別的:

> df %>% 
    unnest(a, .drop = FALSE) %>% 
    unnest(b, .drop = FALSE)

# # A tibble: 7 x 3
#       c a     b    
#   <dbl> <chr> <chr>
# 1    11 a     1    
# 2    11 a     2    
# 3    11 a     3    
# 4    11 b     1    
# 5    11 b     2    
# 6    11 b     3    
# 7    22 c     3

tl;博士

使用unnest_cross() (如果 list-cols 缺少數據,請小心 --> keep_empty = TRUE ):

unnest_cross <- function(data, cols, ...) {
    .df_out <- data
    .cols <- tidyselect::eval_select(rlang::enquo(cols), data)
    purrr::walk(
        .cols,
        function(col) {
            .df_out <<- unnest(.df_out, {{ col }}, ...)
        }
    )
    .df_out
}

背景:帶有unnest()的多個列表列

v0.3.0 (2015) 以來, unnest已經處理了多個列。 它目前使用cols參數,該參數接受典型的 tidyverse 選擇方法。

請注意,它專門設計用於反轉nest() ed data.frames 並要求列表列是“並行條目......大小兼容”。 這表示:

  1. 它不適用於 OP 的 data.frame。
df <- structure(list(
    a = list(c("a", "b"), "c"),
    b = list(c("1", "2", "3"), "3"),
    c = c(11, 22)),
    class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L))

tidyr::unnest(df, cols = tidyselect::everything())
#> Error in `fn()`:
#> ! In row 1, can't recycle input of size 2 to size 3.
  1. 它不會產生與順序列表列unnest()相同的輸出(例如笛卡爾積)。
# "parallel"/"compatible" data.frame
df_parallel <- structure(list(
    a = list(c("a", "b", "c"), "c"),
    b = list(c("1", "2", "3"), "3"),
    c = c(11, 22)),
    class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L))

tidyr::unnest(df_parallel, cols = tidyselect::everything())
#> # A tibble: 4 × 3
#>   a     b         c
#>   <chr> <chr> <dbl>
#> 1 a     1        11
#> 2 b     2        11
#> 3 c     3        11
#> 4 c     3        22

unnest_cross()詳細信息

unnest_cross()使用purrr::walk()循環遍歷指定的列並unnest()它們,每次通過超級賦值(使用<<- )保存結果。 它的名字來源於與purrr::cross()的相似性,因為它總是產生 data.frame 中列表列的笛卡爾積,即使它們是“並行條目”和/或“大小兼容”

  1. 它適用於原始 data.frame (具有不等長度的列表列):
# For original data.frame
unnest_cross(df, cols = tidyselect::everything())
#> # A tibble: 7 × 3
#>   a     b         c
#>   <chr> <chr> <dbl>
#> 1 a     1        11
#> 2 a     2        11
#> 3 a     3        11
#> 4 b     1        11
#> 5 b     2        11
#> 6 b     3        11
#> 7 c     3        22
  1. 它創建df_parallel的笛卡爾積,這與unnest()非常不同。
# For df with list-columns of "compatible size"
unnest_cross(df_parallel, cols = tidyselect::everything())
#> # A tibble: 10 × 3
#>    a     b         c
#>    <chr> <chr> <dbl>
#>  1 a     1        11
#>  2 a     2        11
#>  3 a     3        11
#>  4 b     1        11
#>  5 b     2        11
#>  6 b     3        11
#>  7 c     1        11
#>  8 c     2        11
#>  9 c     3        11
#> 10 c     3        22

reprex 包於 2022-06-03 創建 (v2.0.1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM