R中tidyr包crossing()函数如何保留唯一组合而非排列
R中使用crossing()保留无序唯一组合的实现方法
tidyr::crossing()默认生成传入向量的笛卡尔积,属于有序排列结果,要去掉仅顺序不同的重复组合,可按以下两种方式调整代码:
方法1:两列场景最简写法(推荐)
直接将原有过滤条件从n1 != n2替换为大小判断,利用字符串/数值的固定排序规则,仅保留第一个值排序小于第二个值的行,一步完成自配对排除和顺序去重:
library(tidyr) library(dplyr) names_obj <- c("n1", "n2","n3", "n4","n5","n6","n7","n8","n9","n10","n11","n12") crossing(n1 = names_obj, n2 = names_obj) %>% filter(n1 < n2)
逻辑说明:对于任意两个不同元素,排序大小关系是固定的,比如"n1" < "n10"恒成立,因此只会保留顺序符合排序规则的唯一一条记录,反向重复的配对会被直接过滤。最终返回结果行数为组合数计算结果choose(12,2) = 66,无重复无序组合。
方法2:多列场景通用写法
如果后续需要扩展到3个及以上元素的无序组合,可以通过行级排序生成唯一组合标识后去重,不需要手动写多组大小判断:
crossing(n1 = names_obj, n2 = names_obj) %>% filter(n1 != n2) %>% rowwise() %>% # 对当前行的所有元素排序后拼接为唯一ID,同组合不同顺序的ID完全一致 mutate(combo_mark = paste(sort(c(n1, n2)), collapse = "|")) %>% ungroup() %>% # 按组合ID去重,每组保留第一条记录 distinct(combo_mark, .keep_all = TRUE) %>% select(-combo_mark)
两种方法返回的结果完全一致,可根据实际场景选择。
内容的提问来源于stack exchange,提问作者Jeff Henderson
相关产品推荐
相关产品推荐

