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

如何在R语言中按ID删除X1=1出现后的所有行?

问题解答:按ID分组删除X1=1出现后的所有行

原始数据与目标要求

原始数据框:

df <- data.frame(ID = c(1, 1, 1, 2, 2, 2, 3, 3, 3), X1 = c(0, 1, 0, 0, 1, 0, 0, 0, 1))

想要得到的目标数据框:

df1 <- data.frame(ID = c(1, 1, 2, 2, 3, 3, 3), X1 = c(0, 1, 0, 1, 0, 0, 1))

需求:按ID分组,每个组仅保留X1=1第一次出现的位置及之前的所有行,删除第一次出现X1=1之后的所有行。

你的尝试代码问题

你编写的这段代码:

df1 <- df %>%
    group_by(ID) %>%
    mutate(flag = cumsum(X1 == 1)) %>%
    filter(flag <= 1)

无法满足需求。原因是cumsum(X1 == 1)会累计统计X1=1的出现次数,比如ID=1的组中第三行X1=0对应的flag值为1(前面已出现过一次X1=1),filter(flag <=1)会保留这一行,但按照需求该行应该被删除,最终结果和目标df1不符。

正确的实现方式

这里提供两种可靠的实现方法:

方法一:定位第一个X1=1的位置截取行

library(dplyr)

df1 <- df %>%
  group_by(ID) %>%
  # 找到第一个X1=1的行号,若无则保留所有行
  slice(1:ifelse(any(X1 == 1), which.max(X1 == 1), n())) %>%
  ungroup()

which.max(X1 == 1)会返回组内第一个X1=1的行索引,any(X1 == 1)判断组内是否存在X1=1,不存在则保留全部行。

方法二:用cumany和lag实现简洁过滤

library(dplyr)

df1 <- df %>%
  group_by(ID) %>%
  # 过滤掉第一次出现X1=1之后的所有行
  filter(!cumany(lag(X1 == 1, default = FALSE))) %>%
  ungroup()

原理:lag(X1 == 1)获取当前行的前一行是否为X1=1,cumany会将逻辑值累计传递——只要前一行出现过X1=1,后续所有行的cumany结果都会为TRUE,取反后即可过滤掉这些行,正好保留到第一次出现X1=1的位置。

两种方法都能得到与目标df1完全一致的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:31:04