使用dplyr的mutate实现类Excel SUMIF条件求和遇问题求排查
问题分析
你的代码有两个核心问题:
- 参数传递错误:你预期是用
a列的年份值(2022、2021、2020)作为筛选阈值(筛选b <= 年份的行),但代码里传给get_sum的year参数是b列的值,完全搞反了逻辑。 - 函数不支持向量输入:
get_sum现在只能处理单个year值,但mutate中传递的是整个列的向量,filter会按行做元素级匹配,而非为每个阈值单独遍历整个数据集求和。
修正方案
方案1:用rowwise()逐行处理
先修正参数传递,再用rowwise()让函数对每一行的a值单独计算:
library(dplyr) data <- data.frame(a = c(2022, 2021, 2020), b = c(10, 20, 10)) get_sum <- function(x, year){ sum(x$b[x$b <= year]) } data %>% rowwise() %>% mutate(cum = get_sum(x = ., year = a)) %>% ungroup()
方案2:用purrr::map_dbl向量化处理
如果不想用rowwise(),可以用map_dbl遍历a列的每个值,单独计算求和:
library(dplyr) library(purrr) data <- data.frame(a = c(2022, 2021, 2020), b = c(10, 20, 10)) data %>% mutate(cum = map_dbl(a, ~sum(b[b <= .x])))
方案3:高效矩阵运算(适合大数据)
如果数据集很大,逐行处理效率低,可以用外积生成布尔矩阵,再按行求和:
data <- data.frame(a = c(2022, 2021, 2020), b = c(10, 20, 10)) data$cum <- colSums(outer(data$b, data$a, `<=`) * data$b)
以上三种方法都能得到你预期的输出:
a b cum 1 2022 10 40 2 2021 20 30 3 2020 10 10
内容的提问来源于stack exchange,提问作者Francesc VE
相关产品推荐
相关产品推荐

