在R中展开嵌套列表并选择数据

disho6za  于 2023-02-27  发布在  其他
关注(0)|答案(2)|浏览(125)

我的数据以大量嵌套列表的形式出现,这些列表看起来像这样,但要大得多:

data_in <-list(a=list(list(info=c(ID="C.1", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="C.2", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="L.1", treatment="L", color="green"), parameters=c(v=2, d=2), data=mtcars)),
               b=list(list(info=c(ID="C.1", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="C.2", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="L.1", treatment="L", color="green"), parameters=c(v=2, d=2), data=mtcars)),
               c=list(list(info=c(ID="C.1", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="C.2", treatment="C", color="green"), parameters=c(v=2, d=2), data=mtcars),
                      list(info=c(ID="L.1", treatment="L", color="green"), parameters=c(v=2, d=2), data=mtcars)))

是否有一个优雅的解决方案(使用map()或unlist()?)将这个列表列表转换为只包含选定数据的 Dataframe 列表?
我期待的结果是这样的:

$a
   ID treatment v d
1 C.1         C 2 2
2 C.2         C 2 2
3 L.1         L 2 2

$b
   ID treatment v d
1 C.1         C 2 2
2 C.2         C 2 2
3 L.1         L 2 2

$c
   ID treatment v d
1 C.1         C 2 2
2 C.2         C 2 2
3 L.1         L 2 2

先谢谢你了!

hzbexzde

hzbexzde1#

如果我们只想使用tidyverse,那么用map循环到内部嵌套层,提取感兴趣的元素('info','parameters'),转换为tibble,删除'color'列,在每个嵌套层中绑定它们(_dfr

library(dplyr)
library(purrr)
map(data_in,  ~
   map_dfr(.x, ~ .x[c("info", "parameters")] %>% 
   map_dfc(as_tibble_row)) %>% select(-color))

或者使用递归函数(rrapply)提取元素并转换为tibble(因为它是一个命名向量),然后绑定内层中的数据集,在使用map循环外部列表时取消嵌套

library(rrapply)
library(tidyr)
rrapply(data_in, condition = \(x, .xname) .xname %in%
    c("info", "parameters"), as_tibble_row, how = "prune"  ) %>% 
  map(~ bind_rows(.x) %>%
   unnest(where(is.list)) %>%
   select(-color))
  • 输出
$a
# A tibble: 3 × 4
  ID    treatment     v     d
  <chr> <chr>     <dbl> <dbl>
1 C.1   C             2     2
2 C.2   C             2     2
3 L.1   L             2     2

$b
# A tibble: 3 × 4
  ID    treatment     v     d
  <chr> <chr>     <dbl> <dbl>
1 C.1   C             2     2
2 C.2   C             2     2
3 L.1   L             2     2

$c
# A tibble: 3 × 4
  ID    treatment     v     d
  <chr> <chr>     <dbl> <dbl>
1 C.1   C             2     2
2 C.2   C             2     2
3 L.1   L             2     2
rta7y2nd

rta7y2nd2#

下面是另一种方法,首先使用rrapply(..., how = "bind")将嵌套列表转换为宽数据.frame,然后使用tidyr进一步取消嵌套。使用base::split()而不是dplyr::group_split()的原因是base::split()会自动命名数据. frame的输出列表,而dplyr::group_split()不会。

library(rrapply)
library(tidyr)
library(dplyr)

rrapply(data_in, how = "bind", options = list(namecols = TRUE)) %>%
  unnest_wider(info) %>%
  unnest_wider(parameters) %>%
  select(-matches("L2|color|data")) %>%
  split(f = as.factor(.$L1))

#> $a
#> # A tibble: 3 × 5
#>   L1    ID    treatment     v     d
#>   <chr> <chr> <chr>     <dbl> <dbl>
#> 1 a     C.1   C             2     2
#> 2 a     C.2   C             2     2
#> 3 a     L.1   L             2     2
#> 
#> $b
#> # A tibble: 3 × 5
#>   L1    ID    treatment     v     d
#>   <chr> <chr> <chr>     <dbl> <dbl>
#> 1 b     C.1   C             2     2
#> 2 b     C.2   C             2     2
#> 3 b     L.1   L             2     2
#> 
#> $c
#> # A tibble: 3 × 5
#>   L1    ID    treatment     v     d
#>   <chr> <chr> <chr>     <dbl> <dbl>
#> 1 c     C.1   C             2     2
#> 2 c     C.2   C             2     2
#> 3 c     L.1   L             2     2

相关问题