如何在R中按group列分组生成name元素两两配对的新数据框
解决方案:按组生成所有有序姓名配对
这里有几种能实现你需求的R语言方法,核心思路是按分组生成组内姓名的全有序笛卡尔积,再排除自身配对的情况:
方法1:使用dplyr + tidyr(适合熟悉tidyverse的用户)
先加载必要的包,然后通过分组、生成配对、过滤三步完成:
library(dplyr) library(tidyr) # 原始数据框 df <- data.frame(group = rep(letters[1:2], each=3), name = LETTERS[1:6]) # 生成目标df2 df2 <- df %>% group_by(group) %>% # 对每个组生成所有有序配对(包括自身) summarise( V1 = rep(name, each = n()), V2 = rep(name, times = n()) ) %>% # 过滤掉自身配对的行 filter(V1 != V2) %>% # 移除group列并取消分组 select(-group) %>% ungroup() # 查看结果 print(df2)
运行后得到的结果和你期望的完全一致:
V1 V2 1 A B 2 A C 3 B A 4 B C 5 C A 6 C B 7 D E 8 D F 9 E D 10 E F 11 F D 12 F E
方法2:使用data.table(适合大数据场景,效率更高)
如果你处理的是大规模数据,data.table的语法会更高效:
library(data.table) # 转换为data.table格式 setDT(df) # 生成目标df2 df2 <- df[, .(V1 = rep(name, each = .N), V2 = rep(name, times = .N)), by = group][V1 != V2][, group := NULL][] # 查看结果 print(df2)
方法3:基础R实现(无需额外安装包)
如果你不想加载第三方包,用基础R的拆分-应用-合并思路也能实现:
# 原始数据框 df <- data.frame(group = rep(letters[1:2], each=3), name = LETTERS[1:6]) # 按group拆分姓名列表 group_names <- split(df$name, df$group) # 对每个组生成有序配对并过滤自身 pair_data <- lapply(group_names, function(names) { expand.grid(V1 = names, V2 = names, stringsAsFactors = FALSE) %>% subset(V1 != V2) }) # 合并所有组的结果并重置行名 df2 <- do.call(rbind, pair_data) rownames(df2) <- NULL # 查看结果 print(df2)
以上三种方法都能得到你需要的df2,你可以根据自己的使用习惯和数据规模选择合适的方式~
内容的提问来源于stack exchange,提问作者NBK
相关产品推荐
相关产品推荐

