mutate and/or 汇总动态列数

mutate and/or summarise a dynamic number of columns

在上一个问题中,我想 case_when 使用动态数量的案例。解决方案是使用 parse_exprs!!!。我正在寻找与 mutate/summarise 具有动态列数的类似解决方案。

考虑以下数据集。

library(dplyr)
library(rlang)
data(mtcars)
mtcars = mtcars %>%
  mutate(g2 = ifelse(gear == 2, 1, 0),
         g3 = ifelse(gear == 3, 1, 0),
         g4 = ifelse(gear == 4, 1, 0))

假设我想对 g2g3g4 列求和。如果我知道这些是列名,那么这很简单,标准 dplyr:

answer = mtcars %>%
  summarise(sum_g2 = sum(g2),
            sum_g3 = sum(g3),
            sum_g4 = sum(g4))

但是假设我不知道有多少列,或者它们的确切名称。相反,我有一个向量,其中包含我关心的所有列名。按照我以前的方法接受的答案中的逻辑,我将使用:

columns_to_sum = c("g2","g3","g4")

formulas = paste0("sum_",columns_to_sum," = sum(",columns_to_sum,")")

answer = mtcars %>%
  summarise(!!!parse_exprs(formulas))

如果这确实有效,那么无论 columns_to_sum 中作为输入提供的列名称如何,我都应该收到相应列的总和。但是,这是行不通的。我得到一个名为 "sum_g2 = sum(g2)" 的列,而不是包含 sum(g2) 的名为 sum_g2 的列,并且此列中的每个值都是零。

鉴于我可以将公式传递给 case_when,看来我应该能够将公式传递给 summarise(同样的想法也适用于 mutate,因为它们都是使用 rlang 包)。

过去有 mutatesummarisemutate_summarise_)的字符串版本,您可以将公式作为字符串传递给它们。但是这些已经被淘汰了,因为 rlang 方法现在是预期的方法。我在 Whosebug 上查看的相关问题没有使用 rlang 引用方法,因此不足以满足我的目的。

如何使用动态列数进行汇总(使用 rlang 方法)?

您的尝试给出了正确的答案,但没有按预期给出列名。

这是一种使用 map 来获得正确名称的方法:

library(dplyr)
library(rlang)
library(purrr)

map_dfc(columns_to_sum, ~mtcars %>% 
                         summarise(!!paste0('sum_', .x) := sum(!!sym(.x))))

#  sum_g2 sum_g3 sum_g4
#1      0     15     12

您也可以使用这种简单的基础 R 方法,无需任何 NSE-stuff :

setNames(data.frame(t(colSums(mtcars[columns_to_sum]))), 
         paste0('sum_', columns_to_sum))

dplyr 方式相同:

mtcars %>%
  summarise(across(all_of(columns_to_sum), sum)) %>%
  set_names(paste0('sum_', columns_to_sum))

dplyr 1.0.0 以来的一个选项可能是:

mtcars %>%
 summarise(across(all_of(columns_to_sum), sum, .names = "sum_{col}"))

  sum_g2 sum_g3 sum_g4
1      0     15     12