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

如何按组过滤DataFrame中最后一个非NA值后的NA行?

问题:按分组保留最后一个非NA值及之前的所有行

需求描述

按Story字段分组,过滤掉每组中最后一个非NA的Climax值之后的所有NA行,仅保留最后一个非NA值及之前的所有行。

原始数据

df
   id Story Climax
1   1     A   <NA>
2   2     A      x
3   3     A   <NA>
4   4     A   <NA>
5   5     A      x
6   6     A      x  # <--- 分组A的截断点
7   7     A   <NA>
8   8     B   <NA>
9   9     B   <NA>
10 10     B      y
11 11     B   <NA>
12 12     B      y  # <--- 分组B的截断点
13 13     B   <NA>
14 14     B   <NA>
15 15     B   <NA>

期望输出

id Story Climax
1   1     A   <NA>
2   2     A      x
3   3     A   <NA>
4   4     A   <NA>
5   5     A      x
6   6     A      x
8   8     B   <NA>
9   9     B   <NA>
10 10     B      y
11 11     B   <NA>
12 12     B      y

尝试的错误代码

原代码逻辑仅能筛选第一个非NA值之前的行,不符合需求(已修正拼写错误):

library(dplyr)
df %>%
  group_by(Story) %>%
  mutate(cnt = cumsum(!is.na(Climax))) %>%
  filter(cnt == 0)

数据构造代码

df <- data.frame(
  id = 1:15,
  Story = c(rep("A",7), rep("B",8)),
  Climax = c(NA, "x", NA, NA, "x", "x", NA, NA, NA, "y", NA, "y", NA, NA, NA)
)

正确实现方法

方法1:dplyr直接定位最后一个非NA行号

核心思路:找到每组中最后一个非NAClimax的行号,保留该行及之前的所有行:

library(dplyr)

df %>%
  group_by(Story) %>%
  filter(row_number() <= max(which(!is.na(Climax)))) %>%
  ungroup()

方法2:反向累积标记(dplyr另一种实现)

从后往前遍历,标记已遇到非NA值的行,再筛选有效行:

library(dplyr)

df %>%
  group_by(Story) %>%
  mutate(keep_flag = rev(cumsum(rev(!is.na(Climax))))) %>%
  filter(keep_flag > 0) %>%
  select(-keep_flag) %>%
  ungroup()

方法3:data.table实现

如果习惯使用data.table,逻辑与方法1一致:

library(data.table)
setDT(df)

df[, .SD[1:max(which(!is.na(Climax)))], by = Story]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:53:09