取消嵌套数据框列中的列表列表
Unnesting a list of lists in a data frame column
要取消嵌套数据框,我可以使用:
df <- data_frame(
x = 1,
y = list(a = 1, b = 2)
)
tidyr::unnest(df)
但是如何取消嵌套数据框列内的列表内的列表?
df <- data_frame(
x = 1,
y = list(list(a = 1, b = 2))
)
tidyr::unnest(df)
错误:
Each column must either be a list of vectors or a list of data frames [y]
注意:忽略原文和Update 1;更新 2 对于 tidyverse 的当前状态更好。
原文:
使用 purrr
,非常适合列表,
library(purrr)
df %>% dmap(unlist)
## # A tibble: 2 x 2
## x y
## <dbl> <dbl>
## 1 1 1
## 2 1 2
或多或少等同于
as.data.frame(lapply(df, unlist))
## x y
## a 1 1
## b 1 2
更新 1:
dmap
已被弃用并移至 purrrlyr,这里有一些有趣但命运多舛的函数,现在会向您发出大量弃用警告。您可以将基本 R 习语翻译成 tidyverse:
df %>% map(unlist) %>% as_tibble()
这对于这种情况会很好,但不会超过一行(所有这些方法都面临的问题)。一个更强大的解决方案可能是
library(tidyverse)
df %>% bind_rows(df) %>% # make larger sample data
mutate_if(is.list, simplify_all) %>% # flatten each list element internally
unnest() # expand
#> # A tibble: 4 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
#> 3 1 1
#> 4 1 2
更新二:
自从有人提出这个问题后,tidyr::unnest()
进行了更新,不再出错,因此您可以直接执行
df %>%
unnest(y) %>%
unnest(y)
#> # A tibble: 2 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
如果你关心列表中的名字,先把它们拉出来,然后同时取消名字和列表的嵌套:
df %>%
mutate(label = map(y, names)) %>%
unnest(c(y, label)) %>%
unnest(y)
#> # A tibble: 2 × 3
#> x y label
#> <dbl> <dbl> <chr>
#> 1 1 1 a
#> 2 1 2 b
为了连贯性,我将保留之前的答案,但这更简单。
自从 tidyr 1.0.0 以来,使用 unnest_longer()
可以通过一个简单的步骤完成此操作:
df <- tibble::tibble(
x = 1,
y = list(list(a = 1, b = 2))
)
library(tidyr)
unnest_longer(df,y,indices_include = FALSE)
#> # A tibble: 2 x 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
由 reprex package (v0.3.0)
于 2019-09-14 创建
现在所有答案都已弃用;对于给定的任务,我看到了两个解决方案:
tidyr::unnest(df, y) %>% tidyr::unnest(y)
如你所愿
dplyr::mutate(df, y = purrr::map(y, unlist)) |> tidyr::unnest(y)
虽然更长。我真的没有看到在一个操作中取消嵌套多个列表列的好案例,因为在同一行内处理不同大小的列表会导致问题。
要取消嵌套数据框,我可以使用:
df <- data_frame(
x = 1,
y = list(a = 1, b = 2)
)
tidyr::unnest(df)
但是如何取消嵌套数据框列内的列表内的列表?
df <- data_frame(
x = 1,
y = list(list(a = 1, b = 2))
)
tidyr::unnest(df)
错误:
Each column must either be a list of vectors or a list of data frames [y]
注意:忽略原文和Update 1;更新 2 对于 tidyverse 的当前状态更好。
原文:
使用 purrr
,非常适合列表,
library(purrr)
df %>% dmap(unlist)
## # A tibble: 2 x 2
## x y
## <dbl> <dbl>
## 1 1 1
## 2 1 2
或多或少等同于
as.data.frame(lapply(df, unlist))
## x y
## a 1 1
## b 1 2
更新 1:
dmap
已被弃用并移至 purrrlyr,这里有一些有趣但命运多舛的函数,现在会向您发出大量弃用警告。您可以将基本 R 习语翻译成 tidyverse:
df %>% map(unlist) %>% as_tibble()
这对于这种情况会很好,但不会超过一行(所有这些方法都面临的问题)。一个更强大的解决方案可能是
library(tidyverse)
df %>% bind_rows(df) %>% # make larger sample data
mutate_if(is.list, simplify_all) %>% # flatten each list element internally
unnest() # expand
#> # A tibble: 4 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
#> 3 1 1
#> 4 1 2
更新二:
自从有人提出这个问题后,tidyr::unnest()
进行了更新,不再出错,因此您可以直接执行
df %>%
unnest(y) %>%
unnest(y)
#> # A tibble: 2 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
如果你关心列表中的名字,先把它们拉出来,然后同时取消名字和列表的嵌套:
df %>%
mutate(label = map(y, names)) %>%
unnest(c(y, label)) %>%
unnest(y)
#> # A tibble: 2 × 3
#> x y label
#> <dbl> <dbl> <chr>
#> 1 1 1 a
#> 2 1 2 b
为了连贯性,我将保留之前的答案,但这更简单。
自从 tidyr 1.0.0 以来,使用 unnest_longer()
可以通过一个简单的步骤完成此操作:
df <- tibble::tibble(
x = 1,
y = list(list(a = 1, b = 2))
)
library(tidyr)
unnest_longer(df,y,indices_include = FALSE)
#> # A tibble: 2 x 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
#> 2 1 2
由 reprex package (v0.3.0)
于 2019-09-14 创建现在所有答案都已弃用;对于给定的任务,我看到了两个解决方案:
tidyr::unnest(df, y) %>% tidyr::unnest(y)
如你所愿
dplyr::mutate(df, y = purrr::map(y, unlist)) |> tidyr::unnest(y)
虽然更长。我真的没有看到在一个操作中取消嵌套多个列表列的好案例,因为在同一行内处理不同大小的列表会导致问题。