У меня есть таблица данных в R, которая
> data.table(value = "one",list1=list(c(list("one1"),list("one2"),list(c("one3 1","one3 2")))),position=list(c(0,1,2)))
value list1 position
1: one <list[3]> 0,1,2
где элемент <list[3]>
[[1]]
[[1]][[1]]
[1] "one1"
[[1]][[2]]
[1] "one2"
[[1]][[3]]
[1] "one3 1" "one3 2"
Я хочу удлинить таблицу данных, чтобы у меня было
value list1 position
one "one1" 0
one "one2" 1
one "one3 1" 2
one "one3 2" 2
где «one3 2» соответствует позиции 2. До сих пор все мои попытки приводили к тому, что позиция 3 была указана для «one3 2». Это можно как-то исправить?
Вот один из вариантов, если это ваш фактический набор данных, хотя вы не уверены в другой логике, которая может применяться к вашим данным:
library(data.table)
library(tidyverse)
dt <- data.table(
value = "one",
list1=list(c(list("one1"),list("one2"),list(c("one3 1","one3 2")))),
position=list(c(0,1,2))
)
dt %>%
tidyr::unnest_longer(c(list1, position)) %>%
tidyr::unnest_longer(list1) %>%
dplyr::mutate(temp_index = readr::parse_number(list1) - 1) %>%
dplyr::filter(position == temp_index) %>%
dplyr::select(-temp_index)
#> # A tibble: 4 × 3
#> value list1 position
#> <chr> <chr> <dbl>
#> 1 one one1 0
#> 2 one one2 1
#> 3 one one3 1 2
#> 4 one one3 2 2
Использование data.table
library(data.table)
dt1[, .(value, list1 = unlist(list1),
position = c(mapply(\(x, y) rep(x, lengths(y)), position, list1)))]
-выход
value list1 position
1: one one1 0
2: one one2 1
3: one one3 1 2
4: one one3 2 2
Спасибо, я только что понял, что у моего dt1
есть list1
значения, которые представляют собой пустые списки. Это приводит к ошибке Error in rep(x, lengths(y)) : invalid 'times' argument
. У вас есть идеи, как я могу учитывать пустые списки, которые затем приводят к нулевой длине?
@ user321627, вы хотите удалить эти пустые дела или вернуть NA?
@user321627 user321627 можете показать пример. Этот пример dt2 <- data.table(value = "one",list1=list(c(list("one1"),list(NULL),list(c("one3 1","one3 2")))),position=list(c(0,1,2)))
работает с кодом
@ user321627 можешь попробовать yourdat[, c(.(value = value), lapply(seq_along(list1), \(i) {x <- list1[[i]]; l1 <- lengths(x); x[l1==0] <- NA_character_; data.table(list1 = unlist(x), position = rep(position[[i]], lengths(x)))}))]
Я думаю, вы можете использовать unnest
дважды, как показано ниже.
dt %>%
unnest(c(list1, position)) %>%
unnest(list1)
который дает
# A tibble: 4 × 3
value list1 position
<chr> <chr> <dbl>
1 one one1 0
2 one one2 1
3 one one3 1 2
4 one one3 2 2
Вот еще один необычный подход, основанный только на data.table
:
dt[, .(value, list1 = unlist(list1, recursive = FALSE), position = unlist(position))][, .(list1 = unlist(list1)), by = .(value, position)]
#> value position list1
#> 1: one 0 one1
#> 2: one 1 one2
#> 3: one 2 one3 1
#> 4: one 2 one3 2
или немного проще:
dt[, .(value, list1 = list1[[1]], position = position[[1]])][, .(list1 = unlist(list1)), by = .(value, position)]
#> value position list1
#> 1: one 0 one1
#> 2: one 1 one2
#> 3: one 2 one3 1
#> 4: one 2 one3 2
Unnest может обрабатывать несколько столбцов при условии, что каждый из них не вложен в одинаковую длину, поэтому вы можете упростить это решение до двух вызовов unnest.
dt %>% unnest_longer(c(list1, position)) %>% unnest_longer(list1)
.