R数据框中保留最大ID组并去重(保留最低rank)的实现方法
处理R数据框的两个去重需求
原始数据
定义如下R数据框:
mydf <- data.frame(ids=c('D3022TexB4//D3022TexB7','D3022TexC10//D3026TexC1','D3021TexA6//D3022TexC8','D3022TexB4//D3022TexB7','D3021TexA6//D3022TexC8//D3026TexC2','D3022TexB4//D3022TexB7','D3019TexA5//D3022TexB4//D3026TexC1//D3026TexC3','D3021TexA7//D3021TexA10','D3022TexB8//D3026TexC4','D3022TexB6//D3022TexB9','D3022TexA2//D3026TexC5','D3022TexB4//D3022TexB7','D3022TexC10//D3026TexC1//D3026TexC3'), rank=c(1,1,2,2,3,3,4,4,4,4,4,4,4), group=c(1,2,1,2,1,2,1,2,3,4,5,6,7))
数据框展示如下:
> mydf ids rank group 1 D3022TexB4//D3022TexB7 1 1 2 D3022TexC10//D3026TexC1 1 2 3 D3021TexA6//D3022TexC8 2 1 4 D3022TexB4//D3022TexB7 2 2 5 D3021TexA6//D3022TexC8//D3026TexC2 3 1 6 D3022TexB4//D3022TexB7 3 2 7 D3019TexA5//D3022TexB4//D3026TexC1//D3026TexC3 4 1 8 D3021TexA7//D3021TexA10 4 2 9 D3022TexB8//D3026TexC4 4 3 10 D3022TexB6//D3022TexB9 4 4 11 D3022TexA2//D3026TexC5 4 5 12 D3022TexB4//D3022TexB7 4 6 13 D3022TexC10//D3026TexC1//D3026TexC3 4 7
处理目标
需完成两个数据处理步骤:
- 去除重复的
ids条目,保留rank值最小的记录(例如保留rank为1而非3的条目),目前可通过mydf <- mydf[!duplicated(mydf$ids),]实现此步骤,但还需完成第二步; - 删除所有元素被更大ID组包含的较小组(元素顺序可能不同),仅保留更大的组。
补充说明
以简化示例为例:若存在ID组A/B/C/D、A/B、A/E、A/Z、A/B/C、A/B/E、A/B/C/F,需保留A/B/C/D、A/Z、A/B/E、A/B/C/F,删除所有元素被更大组包含的A/B、A/E、A/B/C。
预期输出
最终处理后的预期数据框如下:
> mydf_final ids rank group 1 D3022TexB4//D3022TexB7 1 1 5 D3021TexA6//D3022TexC8//D3026TexC2 3 1 7 D3019TexA5//D3022TexB4//D3026TexC1//D3026TexC3 4 1 8 D3021TexA7//D3021TexA10 4 2 9 D3022TexB8//D3026TexC4 4 3 10 D3022TexB6//D3022TexB9 4 4 11 D3022TexA2//D3026TexC5 4 5 13 D3022TexC10//D3026TexC1//D3026TexC3 4 7
解决方案
通过以下步骤实现需求:
步骤1:去重并保留最小rank的记录
先按rank升序排序,确保重复ids中rank小的条目排在前面,再用duplicated去除重复项:
# 按rank升序排序 mydf_sorted <- mydf[order(mydf$rank),] # 去除重复ids,保留第一个出现的(即rank最小的条目) mydf_dedup <- mydf_sorted[!duplicated(mydf_sorted$ids),]
步骤2:删除被更大组包含的较小组
将ids拆分为元素集合,判断每个集合是否被其他集合包含,仅保留不被任何其他集合包含的条目:
# 若未安装dplyr和purrr,先运行install.packages(c("dplyr", "purrr")) library(dplyr) library(purrr) # 将每个ids字符串转换为排序后的元素集合 mydf_dedup <- mydf_dedup %>% mutate(id_set = map(ids, ~ strsplit(.x, "//")[[1]] %>% sort() %>% list())) # 定义函数:判断集合x是否被集合y包含(且x不等于y) is_proper_subset <- function(x, y) { all(x[[1]] %in% y[[1]]) && length(x[[1]]) < length(y[[1]]) } # 筛选出不被任何其他集合包含的行 mydf_final <- mydf_dedup %>% filter( map_lgl(row_number(), function(i) { !any(map_lgl(id_set[-i], ~ is_proper_subset(id_set[[i]], .x))) }) ) %>% select(-id_set) # 移除临时生成的id_set列 # 查看最终结果 mydf_final
运行以上代码后,即可得到预期的输出结果。
内容的提问来源于stack exchange,提问作者DaniCee
相关产品推荐
相关产品推荐

