提问人:littleworth 提问时间:5/30/2019 最后编辑:Z.Linlittleworth 更新时间:6/4/2022 访问量:5778
如何使用 dplyr 管道一次性取消嵌套 DataFrame 的多个列表列
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.
答:
8赞
Jared Wilber
5/30/2019
#1
可能有一种更简洁的方法可以做到这一点,但如果你想要列的笛卡尔积,你可以按顺序取消嵌套它们,如果不出意外的话:
> 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
评论
3赞
drastega
10/3/2020
如何为许多列编写通用函数(无管道)?
5赞
Allen Baron
6/4/2022
#2
tl;博士
使用(如果 list-cols 缺少数据,请小心 --> ):unnest_cross()
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()
unnest
自 2015 年以来处理了多个列。它目前使用参数,该参数接受典型的 tidyverse 选择方法。v0.3.0
cols
请注意,它是专门为反转 data.frames 而设计的,并要求列表列是“并行条目......兼容尺寸”。这意味着:nest()
- 它不适用于 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.
- 它不会产生与顺序列表列相同的输出(例如笛卡尔乘积)。
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()
用于循环显示指定的列及其列,每次通过 superassignment (with ) 保存结果。它的名字来源于相似性,因为它总是在 data.frame 中生成列表列的笛卡尔乘积,即使它们是“并行条目”和/或“大小兼容”purrr::walk()
unnest()
<<-
purrr::cross()
- 它按原始 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
- 它创造了 的笛卡尔积,这与 有很大不同。
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
创建于 2022-06-03 由 reprex 软件包 (v2.0.1)
评论