首页 > 解决方案 > 在列的子集上使用 mutate rowwise

问题描述

我正在尝试创建一个新列,该列将包含对 tibble 的列子集逐行执行的计算结果,并将这个新列添加到现有的 tibble 中。像这样:

df <- tibble(
ID = c("one", "two", "three"),
A1 = c(1, 1, 1),
A2 = c(2, 2, 2),
A3 = c(3, 3, 3)
)

我实际上想从基本 R 中做一个与此代码等效的 dplyr:

df$SumA <- rowSums(df[,grepl("^A", colnames(df))])

我的问题是这不起作用:

df %>% 
select(starts_with("A")) %>% 
mutate(SumA = rowSums(.))
    # some code here

...因为我去掉了“ID”列,以便让 mutate 在其他(数字)列上运行 rowSums。我试图在变异后在管道中 cbind 或 bind_cols ,但它不起作用。mutate 的任何变体都不起作用,因为它们就地工作(在 tibble 的每个单元格内,而不是跨列,即使按行排列)。

这确实有效,但并没有让我觉得这是一个优雅的解决方案:

df %>% 
mutate(SumA = rowSums(.[,grepl("^A", colnames(df))]))

是否有任何基于 tidyverse 的解决方案不需要 grepl 或方括号,而只需要更标准的 dplyr 动词和参数?

我的预期输出是这样的:

df_out <- tibble(
ID = c("one", "two", "three"),
A1 = c(1, 1, 1),
A2 = c(2, 2, 2),
A3 = c(3, 3, 3),
SumA = c(6, 6, 6)
)

最佳千焦

标签: rdplyr

解决方案


tidyverse这是在using中进行逐行计算的一种方法purrr::pmap。这最好与实际需要逐行运行的函数一起使用;简单的加法可能会以更快的方式完成。基本上,我们使用select向 提供输入列表pmap,这让我们可以使用select帮助器,例如starts_with或者matches如果您需要正则表达式。

library(tidyverse)
df <- tibble(
  ID = c("one", "two", "three"),
  A1 = c(1, 1, 1),
  A2 = c(2, 2, 2),
  A3 = c(3, 3, 3)
)

df %>%
  mutate(
    SumA = pmap_dbl(
      .l = select(., starts_with("A")),
      .f = function(...) sum(...)
    )
  )
#> # A tibble: 3 x 5
#>   ID       A1    A2    A3  SumA
#>   <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 one       1     2     3     6
#> 2 two       1     2     3     6
#> 3 three     1     2     3     6

reprex 包(v0.2.1)于 2019-01-30 创建


推荐阅读