R dplyr::c_across()行求和异常及按列名向量求和的实现咨询
问题原因说明
- 你写的
sum(c_across(c("A":"B")))和sum(across(cols_to_sum))都返回全局总和的核心原因是:sum()是全局聚合函数,默认会把传入的所有元素合并计算总和,不会自动按行运算。 c_across()本身是为行分组(rowwise())场景设计的,没有声明行分组时,会把所有行的指定列值拼接为单个向量,再传入sum()计算全局总和,因此所有行的total都是1+2+1+2=6。
正确实现方式
你想要的传入列名向量动态指定求和列的需求,有两种常用的实现方案:
方案1:rowSums() + across()(推荐,性能更高)
直接用rowSums()包裹across()返回的列子集,天然支持按行求和:
library(tidyverse) df <- tibble( "ride" = c("bicycle", "motorcycle", "car", "other"), "A" = c(1, NA, 1, NA), "B" = c(NA, 2, NA, 2) ) cols_to_sum <- c("A","B") df %>% mutate(total = rowSums(across(all_of(cols_to_sum)), na.rm = TRUE))
输出结果和你用列索引的结果完全一致:
# A tibble: 4 × 4 ride A B total <chr> <dbl> <dbl> <dbl> 1 bicycle 1 NA 1 2 motorcycle NA 2 2 3 car 1 NA 1 4 other NA 2 2
注:用
all_of()包裹列名向量是tidyverse的最佳实践,当列名不存在时会抛出明确的报错,避免静默匹配错误。
方案2:rowwise() + c_across()(适合简单行运算场景)
如果习惯用c_across写法,只要提前声明行分组即可:
df %>% rowwise() %>% mutate(total = sum(c_across(all_of(cols_to_sum)), na.rm = TRUE)) %>% ungroup() # 计算完成后建议取消行分组,避免影响后续操作
输出结果和方案1完全相同,缺点是大数据量下性能低于rowSums方案。
内容的提问来源于stack exchange,提问作者taiyodayo
相关产品推荐
相关产品推荐

