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

按ID分组,基于sBP/dBP各自条件删除后续行

问题与解决方案

需求说明

此前我曾解决过类似的简单问题,本次需求更复杂:现有包含sBP和dBP两列的数据框,需按Id分组,根据以下规则删除后续行:

  • 若某行sBP >= 140,删除该行之后的所有行;
  • 若某行dBP >= 90先于sBP条件触发,同样删除该行之后的所有行;
  • 若两列均未满足条件,保留所有行。

示例数据

Id <- c(1,1,1,1,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4)
sBP <- c(130,130,140,131, 140, 120, 121, 121, 120, 130, 130, 130, 130, 130, 130, 130, 120, 140, 120)
dBP <- c(89,87,88,70, 89, 90, 70, 70, 70, 72, 73, 74, 76, 90, 80, 70, 90, 80, 60 )
DF1 <- data.frame(Id, sBP, dBP)

解决方案(dplyr实现)

使用dplyr的分组和累计求和功能,可以高效实现需求:

library(dplyr)

DF2 <- DF1 %>%
  group_by(Id) %>%
  mutate(
    # 标记每行是否触发任一条件
    is_trigger = sBP >= 140 | dBP >= 90,
    # 累计触发次数,第一次触发后后续值均大于1
    cum_trigger = cumsum(is_trigger)
  ) %>%
  # 保留未触发过的所有行,以及第一次触发的行
  filter(cum_trigger <= 1 & (cum_trigger == 0 | is_trigger)) %>%
  # 移除辅助列并取消分组
  select(-is_trigger, -cum_trigger) %>%
  ungroup()

print(DF2)

代码逻辑解释

  1. 分组处理:通过group_by(Id)确保每个ID独立计算;
  2. 标记触发行:is_trigger列标记当前行是否满足sBP>=140或dBP>=90;
  3. 累计触发状态:cum_trigger用累计求和,第一次触发后后续行的累计值都会大于1;
  4. 筛选目标行:filter条件保留两种情况:还未触发过的行(cum_trigger == 0),以及第一次触发的行(is_trigger为TRUE且cum_trigger <=1);
  5. 清理结果:移除辅助列并取消分组,得到最终数据框。

运行后得到的结果完全符合需求:

  • ID1:保留前3行(第三行sBP=140触发条件);
  • ID2:保留第1行(第1行sBP=140先触发);
  • ID3:保留前4行(第4行dBP=90触发条件);
  • ID4:保留前2行(第2行dBP=90先触发)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:40:53