R语言合并两个数据集去重时如何优先保留指定数据集的观测
问题解答
1. 该结果不是偶然现象
这个差异完全符合dplyr的官方定义行为:distinct() 及其衍生的distinct_at()函数在开启.keep_all = TRUE参数时,对于你指定的去重判定字段(此处为ID),仅保留首次出现的对应行,后续所有相同ID的重复行都会被直接丢弃。
你测试的两种拼接顺序结果完全匹配这个逻辑:
- 先拼接A再拼接B时,A的ID行在前,重复ID会保留A的字段取值
- 先拼接B再拼接A时,B的ID行在前,重复ID会保留B的字段取值
这个逻辑是稳定可复现的,不存在随机概率问题。
2. 不依赖拼接顺序的稳定实现方法
distinct_at()本身没有内置的优先级参数,不过你可以通过增加显式的优先级标识、配合排序的方式,不管拼接顺序如何都能稳定实现B数据集优先的需求,避免依赖隐式的拼接顺序,代码可读性也更高:
library(dplyr) bind_data <- rbind(a, b) %>% # 新增优先级列:B数据集优先级更高,数值越小优先级越高 mutate(priority = ifelse(Helper == "dataset_b", 1, 2)) %>% # 按ID分组,组内优先级高的排在前面 arrange(ID, priority) %>% # 按ID去重,自动保留优先级高的行 distinct(ID, .keep_all = TRUE) %>% # 剔除辅助用的优先级列 select(-priority)
补充说明:dplyr 1.0.0版本之后,*_at系列函数已经被软废弃,更推荐用distinct(across(ID), .keep_all = TRUE)的写法替代distinct_at(vars(ID), .keep_all = TRUE)。
如果你的场景固定是两个数据集合并、优先保留B的取值,也可以用更直接的更新函数,不需要拼接再去重:
final_data <- full_join(select(a, ID), b, by = "ID") %>% rows_patch(a, by = "ID")
内容的提问来源于stack exchange,提问作者RL_Pug
相关产品推荐
相关产品推荐

