使用dplyr的summarise实现分组聚合与条件取值需求
分组聚合与指定条件值提取问题解决
原始数据
| subs_id | amount | flag |
|---|---|---|
| 1 | 15 | target |
| 1 | 10 | taker |
| 2 | 30 | target |
| 3 | 20 | taker |
| 3 | 10 | target |
需求
- 按
subs_id分组计算amount的总和,命名为ttl_amount; - 新增一列:若该
subs_id存在flag="taker"的记录,显示对应amount值,否则显示0。
预期结果
| subs_id | ttl_amount | amount |
|---|---|---|
| 1 | 25 | 10 |
| 2 | 30 | 0 |
| 3 | 30 | 20 |
错误代码与报错
尝试的代码:
df%>% group_by(subs_id)%>% summarise(ttl_amount=sum(amt), amount=case_when(flag=="taker"~amt[which(flag=="taker")[1]],TRUE~0))
报错信息:
! 'names' attribute [1] must be the same length as the vector [0]
问题分析
- 列名错误:代码中误用
amt,但原始数据的列名是amount,导致无法正确取值; - 索引逻辑问题:当分组内无
flag="taker"记录时,which(flag=="taker")[1]返回空值,用空值索引向量会触发长度不匹配错误; - 聚合逻辑错误:
summarise要求每个表达式返回单值,但原代码的case_when是逐行处理,不符合聚合规则。
解决方案(优先使用summarise)
修正后的代码:
df %>% group_by(subs_id) %>% summarise( ttl_amount = sum(amount), amount = if(any(flag == "taker")) amount[flag == "taker"] else 0 )
代码说明
sum(amount):正确引用列名,计算分组内amount的总和;if(any(flag == "taker")) ... else 0:先判断分组内是否存在taker记录,存在则提取对应amount值(每组仅一条taker记录,直接索引即可),否则返回0;- 完全基于
summarise实现,满足后续追加其他聚合操作的需求。
运行后即可得到预期结果表格。
内容的提问来源于stack exchange,提问作者GitZine
相关产品推荐
相关产品推荐

