首页 > 解决方案 > 将列表中的小标题加入一个小标题

问题描述

我有两个数据框的列表

a = list(
        mtcars %>% as_tibble() %>% select(-vs), 
        mtcars %>% as_tibble() %>% sample_n(17)
    ) 

并通过以下方式向数据集添加一个新列

b = a %>% 
    map(~ mutate(.x, class = floor(runif(nrow(.x), 0, 2)))) %>%
    map(~ nest(.x, -class))

现在我想将两个列表元素加入到一个基于class. 具体来说,我正在寻找一种“更顺畅”的解决方案,inner_join(pluck(b, 1), pluck(b, 2), "class")它可以提供所需的结果,但如果列表中涉及更多数据集,很快就会变得混乱a

标签: rdplyrtidyversetidyrpurrr

解决方案


这个问题不是很清楚,但似乎有足够的用例可以解决。我向 中添加了更多数据框a,构造类似,因为您使用的样本太小,无法真正看到您需要处理的内容。

library(tidyverse)

set.seed(123)
a <- list(
  mtcars %>% as_tibble() %>% select(-vs), 
  mtcars %>% as_tibble() %>% sample_n(17),
  mtcars %>% as_tibble() %>% slice(1:10),
  mtcars %>% as_tibble() %>% select(mpg, cyl, disp)
) 
# same construction of b as in the question

您可以使用重复purrr::reduce执行inner_join调用,返回嵌套数据帧的单个数据帧。这很简单,但我想不出一种为联接提供suffix参数的好方法,联接分配.x.y默认区分重复的列名。所以你会得到这些奇怪的名字:

b %>%
  reduce(inner_join, by = "class")
#> # A tibble: 2 x 5
#>   class data.x            data.y           data.x.x         data.y.y       
#>   <dbl> <list>            <list>           <list>           <list>         
#> 1     1 <tibble [11 × 10… <tibble [8 × 11… <tibble [3 × 11… <tibble [17 × …
#> 2     0 <tibble [21 × 10… <tibble [9 × 11… <tibble [7 × 11… <tibble [15 × …

您可能可以通过在 . 之前创建类似 , 等的名称来处理名称data1data2reduce我决定的最快的事情是用列表中每个数据帧的索引替换后缀b。更复杂的命名方案将是针对不同问题的任务。

b %>%
  reduce(inner_join, by = "class") %>%
  rename_at(vars(starts_with("data")), 
            str_replace, "(\\.\\w)+$", as.character(1:length(b))) %>%
  names()
#> [1] "class" "data1" "data2" "data3" "data4"

推荐阅读