You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dplyr编写条件更新分组计数器函数的问题求助

按ID分组的计数器更新问题

数据集

my_data = structure(list(id = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B"), result = c("AAA", "BBB", "CCC", "AAA", "CCC", "DDD", "BBB", 
"BBB", "DDD")), class = "data.frame", row.names = c(NA, -9L))

需求规则

针对每个唯一ID,按以下逻辑更新计数器变量:

  • 当result为AAA时,计数器重置为0
  • 当result为BBB时,计数器 = 当前计数器 + 1
  • 当result为CCC时,计数器 = 当前计数器 + 2
  • 当result为DDD时,计数器 = 当前计数器 - 1

尝试的错误代码

library(dplyr)

my_data %>%
  group_by(id) %>%
  mutate(counter = ifelse(result == "AAA", 0, 
         ifelse(result == "BBB", 1, 
     ifelse(result == "CCC", 2, 
         ifelse(result == "DDD", -1, 
     ifelse(result == 1, cumsum(result), 0))))))

错误输出结果

# A tibble: 9 x 3
# Groups:   id [2]
  id    result counter
  <chr> <chr>    <dbl>
1 A     AAA          0
2 A     BBB          1
3 A     CCC          2
4 A     AAA          0
5 A     CCC          2
6 B     DDD         -1
7 B     BBB          1
8 B     BBB          1
9 B     DDD         -1

预期输出

id result counter
1  A    AAA       0
2  A    BBB       1
3  A    CCC       3
4  A    AAA       0
5  A    CCC       2
6  B    DDD      -1
7  B    BBB       0
8  B    BBB       1
9  B    DDD       0

问题分析

你的代码只返回了单次操作的增量值,没有实现基于前一次计数器结果的累积计算,且尝试对字符型的result直接使用cumsum是无效的。要实现带重置的累积逻辑,需要先映射增量值,再按重置点分割分组后累加。

正确解法

方法1:dplyr分组累积

library(dplyr)

my_data %>%
  group_by(id) %>%
  # 映射每个result对应的增量值
  mutate(incr = case_match(
    result,
    "AAA" ~ 0,
    "BBB" ~ 1,
    "CCC" ~ 2,
    "DDD" ~ -1
  ),
  # 生成重置分组:每次出现AAA就开启新分组
  reset_group = cumsum(result == "AAA")) %>%
  # 按id和重置分组,计算累积和
  group_by(id, reset_group, .add = TRUE) %>%
  mutate(counter = cumsum(incr)) %>%
  # 清理中间列
  select(-incr, -reset_group) %>%
  ungroup()

方法2:purrr逐行计算

如果需要更灵活的逐行逻辑,用accumulate手动处理每一步的计数器更新:

library(dplyr)
library(purrr)

my_data %>%
  group_by(id) %>%
  mutate(counter = accumulate(result, .init = 0, function(prev, curr) {
    case_match(
      curr,
      "AAA" ~ 0,
      "BBB" ~ prev + 1,
      "CCC" ~ prev + 2,
      "DDD" ~ prev - 1
    )
  }) %>% tail(-1)) %>% # 移除初始的0值
  ungroup()

以上两种方法均能得到符合预期的输出结果。

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:45:31