如何按组过滤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
相关产品推荐
相关产品推荐

