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

如何用dplyr的mutate和case_when实现嵌套条件分组标记?

问题描述

我有一个每个ID对应多条观测数据的数据框,每个ID完成了多项测试,每项测试根据表现被分为三分位排名(top、mid、bottom),排名会随时间点变化。

示例数据框

df <- tibble(
  ID = c(1,1,1,2,2,2,3,3,3,4,4,4),
  time = c(1,2,3,1,2,3,1,2,3,1,2,3),
  test1_rank = c("top", "top", "top", "top", "mid", "bottom", "bottom", "bottom", "bottom", "top", "bottom", "bottom"),
  test2_rank = c("bottom", "bottom", "bottom", "top", "mid", "bottom", "top", "top", "top", "top", "bottom", "bottom")
)

数据预览:

IDtimetest1_ranktest2_rank
11topbottom
12topbottom
13topbottom
21toptop
22midmid
23bottombottom
31bottomtop
32bottomtop
33bottomtop
41toptop
42bottombottom
43bottombottom

分类规则

  • 若三个时间点排名一致,标记为"stable(top)"或"stable(bottom)"(根据排名是top还是bottom);
  • 若排名从time1的top变为time2的mid再变为time3的bottom,标记为"gradual";
  • 若排名从time1的top直接变为time2和time3的bottom,标记为"rapid";
  • 其他组合标记为"Other"。

期望结果

df2 <- tibble(
  ID = c(1,1,1,2,2,2,3,3,3,4,4,4),
  time = c(1,2,3,1,2,3,1,2,3,1,2,3),
  test1_rank = c("top", "top", "top", "top", "mid", "bottom", "bottom", "bottom", "bottom", "top", "bottom", "bottom"),
  test2_rank = c("bottom", "bottom", "bottom", "top", "mid", "bottom", "top", "top", "top", "top", "bottom", "bottom"),
  test1_rankgroup = c("stable(top)", "stable(top)", "stable(top)", "gradual", "gradual", "gradual", "stable(bottom)", "stable(bottom)", "stable(bottom)", "rapid", "rapid", "rapid"), 
  test2_rankgroup = c("stable(bottom)", "stable(bottom)", "stable(bottom)", "gradual", "gradual", "gradual", "stable(top)", "stable(top)", "stable(top)", "rapid", "rapid", "rapid")
)

数据预览:

IDtimetest1_ranktest2_ranktest1_rankgrouptest2_rankgroup
11topbottomstable(top)stable(bottom)
12topbottomstable(top)stable(bottom)
13topbottomstable(top)stable(bottom)
21toptopgradualgradual
22midmidgradualgradual
23bottombottomgradualgradual
31bottomtopstable(bottom)stable(top)
32bottomtopstable(bottom)stable(top)
33bottomtopstable(bottom)stable(top)
41toptoprapidrapid
42bottombottomrapidrapid
43bottombottomrapidrapid

请问在dplyr中使用mutate和case_when实现该需求的最简方法是什么?


解决方案

可以通过dplyr的分组+批量处理+条件判断组合实现,核心是按ID分组后,提取每个测试列的时间序列排名,再匹配规则分类:

library(dplyr)

df_result <- df %>%
  group_by(ID) %>%
  mutate(
    across(ends_with("_rank"), ~{
      # 按时间顺序提取当前测试列的三个排名
      ranks <- .[time == 1:3]
      case_when(
        # 稳定top/bottom情况
        all(ranks == "top") ~ "stable(top)",
        all(ranks == "bottom") ~ "stable(bottom)",
        # 渐变序列:top -> mid -> bottom
        identical(ranks, c("top", "mid", "bottom")) ~ "gradual",
        # 突变序列:top -> bottom -> bottom
        identical(ranks, c("top", "bottom", "bottom")) ~ "rapid",
        # 其他所有情况
        TRUE ~ "Other"
      )
    }, .names = "{.col}_group")
  ) %>%
  ungroup()

代码说明

  1. 分组处理:group_by(ID)保证每个ID的三个时间点数据被统一判断;
  2. 批量匹配测试列:across(ends_with("_rank"), ...)自动遍历所有以_rank结尾的测试列,避免重复编写规则;
  3. 提取时间序列:.[time == 1:3]按时间顺序取出当前测试列的三个排名值;
  4. 规则匹配:按优先级依次判断稳定、渐变、突变情况,最后用TRUE ~ "Other"覆盖剩余组合;
  5. 自动命名新列:.names = "{.col}_group"将原测试列名(如test1_rank)转换为对应的分组列名(test1_rank_group);
  6. 取消分组:ungroup()恢复数据框的非分组状态,方便后续操作。

运行后得到的结果与期望的df2完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:25:04