R语言dplyr按source列自定义优先级去重保留目标行方法
dplyr按自定义列优先级去重实现方案
默认distinct()函数会按数据原始行顺序保留重复组的第一行,无法自定义保留规则,要实现按source列预设优先级保留行的需求,核心思路是先将source转换为按优先级排序的有序因子,排序/分组筛选后再去重即可。
实现代码
library(dplyr) # 示例数据集 mydata = data.frame ( species =c ('myli','myli','myli','myli','myli','stili','stili','stili'), count = c (10,10,15,15,12,10,10,10), year =c(2020,2020,2021,2021,2019,2017,2017,2018), source =c('zd','steam','ted','steam','zd','steam','ted','steam') ) # 按需求设定source优先级,顺序为从高到低:zd > ted > steam source_priority <- c("zd", "ted", "steam") # 方法1:排序后调用distinct去重 result <- mydata %>% # 将source转为有序因子,水平顺序匹配优先级 mutate(source = factor(source, levels = source_priority, ordered = TRUE)) %>% # 先按重复判定列分组,组内按source优先级升序排(优先级越高越靠前) arrange(species, count, year, source) %>% # 去重时保留每组第一行,即优先级最高的行 distinct(species, count, year, .keep_all = TRUE) %>% # 可选步骤:将source转回字符类型,适配后续常规操作 mutate(source = as.character(source))
运行结果
执行代码后输出的result完全匹配预期结果:
species count year source 1 myli 10 2020 zd 2 myli 12 2019 zd 3 myli 15 2021 ted 4 stili 10 2017 ted 5 stili 10 2018 steam
可选替代写法
也可以用分组切片的方式实现,逻辑等价,不需要提前排序:
result <- mydata %>% mutate(source = factor(source, levels = source_priority, ordered = TRUE)) %>% # 按判定重复的三个列分组 group_by(species, count, year) %>% # 取组内source优先级最高的1行(有序因子值越小优先级越高) slice_min(order_by = source, n = 1, with_ties = FALSE) %>% ungroup() %>% mutate(source = as.character(source))
注意事项
- 如果后续需要调整数据源优先级,仅需修改
source_priority向量内的元素顺序即可,其余代码无需改动。 - 如果重复组内存在多个相同最高优先级的行,
slice_min写法中设置with_ties = FALSE会仅保留第一行,和distinct行为保持一致。
内容的提问来源于stack exchange,提问作者Amanda Goldberg
相关产品推荐
相关产品推荐

