r - 如何使用 purrr 中的 map 和 dplyr::mutate 根据列对创建多个新列

标签 r purrr dplyr

我必须使用 R 来解决问题。简而言之,我想根据数据框中不同列对的计算在数据框中创建多个新列。

数据如下所示:

df <- data.frame(a1 = c(1:5), 
                 b1 = c(4:8), 
                 c1 = c(10:14), 
                 a2 = c(9:13), 
                 b2 = c(3:7), 
                 c2 = c(15:19))
df
a1 b1 c1 a2 b2 c2
1  4 10  9  3 15
2  5 11 10  4 16
3  6 12 11  5 17
4  7 13 12  6 18
5  8 14 13  7 19

输出应该如下所示:
a1 b1 c1 a2 b2 c2 sum_a sum_b sum_c
1  4 10  9  3 15    10     7    25
2  5 11 10  4 16    12     9    27
4  7 13 12  6 18    16    13    31
5  8 14 13  7 19    18    15    33

我可以使用 dplyr 通过以下方式进行一些手动工作来实现这一点:
df %>% rowwise %>% mutate(sum_a = sum(a1, a2),
                          sum_b = sum(b1, b2),
                          sum_c = sum(c1, c2)) %>% 
  as.data.frame()

所以正在做的是:获取包含字母“a”的列,逐行计算总和,并创建一个名为 sum_[letter] 的新列。对具有不同字母的列重复此操作。

但是,如果我有一个包含 300 个不同列对的大型数据集,那么手动输入将很重要,因为我必须编写 300 个 mutate 调用。

我最近偶然发现了 R 包“purrr”,我的猜测是这将解决我以更自动化的方式做我想做的事情的问题。

特别是,我认为能够使用 purrr:map2 向其中传递两个列名列表。
  • list1 = 编号为 1 的所有列
  • list2 = 编号为 2 的所有列

  • 然后我可以计算每个匹配列表条目的总和,格式如下:
    map2(list1, list2, ~mutate(sum))
    

    但是,我无法弄清楚如何使用 purrr 最好地解决这个问题。我对使用 purrr 很陌生,所以我非常感谢在这个问题上提供任何帮助。

    最佳答案

    这是另一种仅使用管道且不需要创建新对象的 tidyverse 方法。

    library(tidyverse)
    
    df %>% 
      bind_cols(
        map_dfc(.x = list("a", "b", "c"), 
                .f = ~ .y %>% 
                   rowwise() %>% 
                   transmute(!!str_c("sum_", .x) := sum(c_across(starts_with(.x)))),
                .y = .)
      )
    #>   a1 b1 c1 a2 b2 c2 sum_a sum_b sum_c
    #> 1  1  4 10  9  3 15    10     7    25
    #> 2  2  5 11 10  4 16    12     9    27
    #> 3  3  6 12 11  5 17    14    11    29
    #> 4  4  7 13 12  6 18    16    13    31
    #> 5  5  8 14 13  7 19    18    15    33
    
    解释
    数据帧通过管道传输到 bind_cols()它将原始列与新创建的列绑定(bind)。使用 purrr::map_dfc() 创建新列它采用变量前缀列表( .x )和转换函数( .f )。此外,管道数据 ( . ) 被分配为另一个参数 ( .y )。由于需要逐行操作,rowwise()c_across()在前缀的每次迭代中使用。 transmute用于使原始变量不重复。为了动态创建变量名,bang-bang 运算符 ( !! ) 和 :=在transmute内部使用。
    笔记
    使用 rowSums() 会更短而不是 rowwise()c_across()但是使用这种方法可以更轻松地实现其他功能。

    关于r - 如何使用 purrr 中的 map 和 dplyr::mutate 根据列对创建多个新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49816669/

    相关文章:

    R::tm - 创建术语关联频率表/矩阵并将值添加到树状图中

    r - 在foreach循环中找不到函数

    r - R中传单中的addMarkers?

    r - 循环 R 中的因子级别 - 如何操作两个连续级别

    html - Rvest 网页抓取带来仅包含列名称的空数据表

    r - 汇总多组列

    r - 将 `purrr::map` 与组合函数一起使用

    r - 相当于 purrr::map_df 中的 next

    r - 在 R 中使用具有年份差距的滞后函数计算变化

    r - 在dplyr的链接操作中切片向量