#r #tidyr
#r #tidyr
Вопрос:
У меня есть этот тип данных с несколькими столбцами списка:
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
))
Моя цель — отменить перечисление трех столбцов left
, node
, и right
. Оба unnest_longer
и unnest_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
Ответ №1:
Мы можем использовать 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, предыдущее решение работает
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 ""
Комментарии:
1. Уважаемый @akrun, пожалуйста, примите мои искренние извинения: как вы и подозревали, я опубликовал неверно
df
. Я обновил его сейчас. С обновленным фреймом данных ваше оригинальное решениеdf %>% unnest(where(is.list))
работает отлично. Большое спасибо. Пожалуйста, обновите, чтобы я мог принять ваш ответ!2. Еще раз извините за ошибочный dput. Теперь это должны быть правильные данные. И еще раз спасибо!
3. Оба решения, опубликованные @akrun, работают отлично!
Ответ №2:
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"
Создано 2021-12-04 пакетом reprex (v2.0.1)