在R中筛选DataFrame中两列值互换的唯一行
解决方案:保留两列值互换视为重复的唯一行
示例数据
先构造匹配需求的示例数据(包含Col_1/Col_2值互换的重复行):
df <- data.frame( ID = c(1, 2, 3, 4, 5), Col_1 = c("A", "B", "C", "B", "D"), Col_2 = c("B", "A", "D", "A", "C") )
其中ID1&2、ID3&5属于值互换的重复行,ID4与ID1/2也属于重复行。
方法一:使用dplyr包(推荐,代码简洁)
核心思路是给每行生成排序后的组合键,让(A,B)和(B,A)生成相同的键,再基于该键去重,保留第一次出现的行(保证无重复行的原始位置不变):
library(dplyr) df_unique <- df %>% rowwise() %>% # 对每行的Col_1和Col_2排序后拼接成唯一键 mutate(combined_key = paste(sort(c(Col_1, Col_2)), collapse = "-")) %>% ungroup() %>% # 按组合键去重,保留每组重复行的第一行 distinct(combined_key, .keep_all = TRUE) %>% # 移除临时生成的组合键列 select(-combined_key)
运行后结果:
ID Col_1 Col_2 1 1 A B 2 3 C D
方法二:Base R实现(无需额外包)
如果不想加载dplyr,用base R也能实现相同逻辑:
# 生成排序后的组合键 df$combined_key <- apply(df[, c("Col_1", "Col_2")], 1, function(x) paste(sort(x), collapse = "-")) # 保留每个组合键第一次出现的行 df_unique <- df[!duplicated(df$combined_key), ] # 删除临时列 df_unique$combined_key <- NULL
可选调整:保留每组重复行的最后一行
如果需要保留每组互换值中的最后一行,只需修改去重逻辑:
- dplyr版本:把
distinct(combined_key, .keep_all = TRUE)改为distinct(combined_key, .keep_all = TRUE, .keep_last = TRUE)(需dplyr 1.1.0及以上) - Base R版本:把
!duplicated(df$combined_key)改为!duplicated(df$combined_key, fromLast = TRUE)
为什么你之前的方法会误删数据?
直接判断列值是否在另一列存在,会把非互换的行(比如(A,C)和(B,A))误判为重复;而通过排序生成组合键的方式,只会把真正的互换值(两列值完全相同仅顺序相反)视为重复,精准匹配需求。
内容的提问来源于stack exchange,提问作者Melissa M
相关产品推荐
相关产品推荐

