#r #list #tibble
#r #Список #tibble
Вопрос:
У меня есть вложенный список списков:
data = list(a = list(1, 2, 3), b = list("foo"), c = list("toast", "onions"))
Как я могу преобразовать это в одну строку data.frame или tibble? Я бы хотел, чтобы списки с более чем одним элементом ( a
и c
здесь ) сохранялись как списки, а одноэлементный ( b
) был обычным значением.
Ожидаемый результат:
# A tibble: 1 x 3
a b c
<list> <chr> <list>
1 <list [3]> foo <list [2]>
Комментарии:
1.
tibble::enframe(data) %>% tidyr::pivot_wider()
?2. Да, это работает для меня, Ронак. Спасибо за вашу помощь. Каков наилучший способ затем преобразовать столбец b в обычный символьный столбец? Я пробовал
... %>% mutate(b = map(b, unlist))
, но это не меняет фактический тип столбца.3. [Ronak]
%>% tidyr::unnest(b) %>% tidyr::unnest(b)
4. Спасибо Ronak. Также работает, если я изменяю
map
map_chr
, т.е. `… %>% mutate(b = map_chr(b, unlist))’.
Ответ №1:
Как насчет этого?
> as_tibble_row(Map(function(x) ifelse(length(x)==1,unlist(x),list(x)),data))
# A tibble: 1 x 3
a b c
<list> <chr> <list>
1 <list [3]> foo <list [2]>
Ответ №2:
Вы можете использовать enframe
pivot_wider
tibble::enframe(data) %>% tidyr::pivot_wider()
# a b c
# <list> <list> <list>
#1 <list [3]> <list [1]> <list [2]>
Чтобы получить длину одного столбца в виде вектора, мы можем добавить :
library(dplyr)
tibble::enframe(data) %>%
tidyr::pivot_wider() %>%
summarise(across(.fns = ~if(length(unlist(.)) == 1) unlist(.) else .))
# a b c
# <list> <chr> <list>
#1 <list [3]> foo <list [2]>
Ответ №3:
data[] <- lapply(data, function(x) if (length(x) == 1) x[[1]] else list(x))
data.table::setDF(data)
# > str(data)
# 'data.frame': 1 obs. of 3 variables:
# $ a:List of 1
# ..$ :List of 3
# .. ..$ : num 1
# .. ..$ : num 2
# .. ..$ : num 3
# $ b: chr "foo"
# $ c:List of 1
# ..$ :List of 2
# .. ..$ : chr "toast"
# .. ..$ : chr "onions"
Ответ №4:
Одним из вариантов является создание набора данных из двух столбцов с aggregate
помощью from base R
aggregate(values ~ ind, stack(data), list)