如何用Tidyverse在R中保留每个ID对应的最高等级组数据?
基于Tidyverse保留每个ID最高等级组的最优实现方法
现有数据框df包含ID、Name、Group列,Group分为A、B、C、D四个等级(A为最高级,D为最低级),需求是为每个ID仅保留其对应的最高等级组数据。
输入示例
ID | Name | Group 101| Jon | A 101| Jon | C 103| Tom | B 103| Tom | D 103| Tom | C
期望输出
ID | Name | Group 101| Jon | A 103| Tom | B
最优实现方案
核心思路是先明确Group的等级顺序,再按ID分组后提取每组的最高等级记录。以下是两种简洁高效的Tidyverse实现方式:
方法一:排序后取首行
library(tidyverse) df_clean <- df %>% # 将Group转为有序因子,指定等级从高到低的顺序 mutate(Group = factor(Group, levels = c("A", "B", "C", "D"), ordered = TRUE)) %>% # 按ID分组,再按Group升序排序(有序因子中A优先级最高,会排在最前) group_by(ID) %>% arrange(Group) %>% # 提取每组第一条数据(即最高等级记录) slice_head(n = 1) %>% # 取消分组 ungroup() %>% # 可选:将Group转回字符类型(如果不需要因子格式) mutate(Group = as.character(Group))
方法二:直接取等级最小值
利用有序因子的数值特性,slice_min可以直接提取每组中等级最高的记录(因为A对应的因子值最小):
df_clean <- df %>% mutate(Group = factor(Group, levels = c("A", "B", "C", "D"), ordered = TRUE)) %>% group_by(ID) %>% slice_min(Group, n = 1) %>% ungroup() %>% mutate(Group = as.character(Group))
注意事项
- 必须将
Group转为有序因子,否则默认字符串排序可能在等级规则变化时出错(比如等级为Z、Y、X时) - 如果
Name与ID是一一对应的,分组时可以加上Name,但仅按ID分组也能得到正确结果(同一ID的Name应一致) - 这两种方法比
distinct结合case_when的写法更直观,逻辑清晰且易于维护
内容的提问来源于stack exchange,提问作者Abdullah Al Sobhi
相关产品推荐
相关产品推荐

