在R的dplyr中实现按组条件累积求和
按组实现条件累积求和需求
需求说明:为数据框df按组添加一列条件累积求和列exp_output,规则如下:
- 当
margin列的值为负数时,正常累加该值 - 当
margin列的值为正数时,用当前累积值减去该正数(等价于累加该正数的相反数)
原数据框
df <- data.frame( group = c('g1', 'g1', 'g1', 'g1', 'g1', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2'), margin = c(-1.72, -1.13, -0.64, 1.75, 1.75, -7.22, -1.99, -1.13, -0.15, 1.31, 1.37, 1.98, 5.84) )
期望输出
df <- data.frame( group = c('g1', 'g1', 'g1', 'g1', 'g1', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2', 'g2'), margin = c(-1.72, -1.13, -0.64, 1.75, 1.75, -7.22, -1.99, -1.13, -0.15, 1.31, 1.37, 1.98, 5.84), exp_output = c(-1.72, -2.86, -3.50, -5.25, -7.00, -7.22, -9.22, -10.36, -10.51, -11.82, -13.20, -15.19, -21.03) )
解决方案
核心思路是先根据margin的正负调整数值符号:正数取相反数,负数保持不变,再对调整后的数值按组做累积求和,即可实现需求中的条件累加逻辑。
简洁实现代码
library(dplyr) df <- df %>% group_by(group) %>% mutate(exp_output = cumsum(ifelse(margin > 0, -margin, margin))) %>% ungroup() # 可选:取消分组,避免后续操作受分组状态影响
分步解释(便于理解)
如果需要更清晰的步骤,可以拆分出中间调整列:
df <- df %>% group_by(group) %>% mutate( # 调整数值符号:正数转负,负数保留 adjusted_margin = case_when( margin > 0 ~ -margin, TRUE ~ margin ), # 对调整后的值做累积求和 exp_output = cumsum(adjusted_margin) ) %>% select(-adjusted_margin) # 移除中间辅助列 ungroup()
验证结果:运行上述代码后,exp_output列将完全匹配期望输出。比如g1组第四行,原margin=1.75被转为-1.75,累加到前一行的-3.50后得到-5.25,完全符合需求逻辑。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

