我必须使用 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 向其中传递两个列名列表。
然后我可以计算每个匹配列表条目的总和,格式如下:
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/