如何在R语言中生成仅跨不同名称的唯一name-value组合配对数据框
如何在R语言中生成仅跨不同名称的唯一name-value组合配对数据框
嗨,我来帮你搞定这个需求!你想要的是只在不同name之间生成所有name-value组合的配对,也就是同一name下的组合绝不配对,对吧?看你给出的示例,应该是要单向的配对(比如只保留a和b、a和c、b和c的组合,而不反过来),下面我给你两种实现方法:
方法一:用tidyverse工具包(简洁直观)
首先先重现你的原始数据:
data <- data.frame( name = c('a', 'a', 'b', rep('c', 3)), value = c('d1', 'd12', 'd123', 'b1', 'c12', 'd1234') )
然后加载tidyverse包(如果没装的话先跑install.packages("tidyverse")安装),接着按以下步骤操作:
library(tidyverse) # 第一步:按name分组,把每个name对应的value存成列表 name_values <- data %>% group_by(name) %>% summarise(values = list(value)) # 第二步:生成所有不同name的单向配对(排除相同name,且避免a-b和b-a重复) name_pairs <- crossing(name1 = name_values$name, name2 = name_values$name) %>% filter(name1 != name2, name1 < name2) # 第三步:把配对和对应的value列表连接,展开成所有组合 data2 <- name_pairs %>% left_join(name_values, by = c("name1" = "name")) %>% rename(value1_list = values) %>% left_join(name_values, by = c("name2" = "name")) %>% rename(value2_list = values) %>% unnest(c(value1_list, value2_list)) %>% rename(value1 = value1_list, value2 = value2_list) %>% select(name1, name2, value1, value2)
运行后得到的结果和你想要的data2完全一致:
> data2 # A tibble: 11 × 4 name1 name2 value1 value2 <chr> <chr> <chr> <chr> 1 a b d1 d123 2 a b d12 d123 3 a c d1 b1 4 a c d1 c12 5 a c d1 d1234 6 a c d12 b1 7 a c d12 c12 8 a c d12 d1234 9 b c d123 b1 10 b c d123 c12 11 b c d123 d1234
方法二:用基础R(无需额外装包)
如果你不想装新的工具包,用基础R也能实现:
# 先获取所有唯一的name unique_names <- unique(data$name) # 生成所有不同name的单向配对(用combn函数直接取两两组合) name_pairs <- t(combn(unique_names, 2)) # 初始化空数据框用来存结果 data2 <- data.frame() # 循环每个name配对,生成对应的value组合 for (i in 1:nrow(name_pairs)) { n1 <- name_pairs[i, 1] n2 <- name_pairs[i, 2] # 提取当前两个name对应的value v1 <- data$value[data$name == n1] v2 <- data$value[data$name == n2] # 生成该配对的所有value组合 temp <- expand.grid(name1 = n1, name2 = n2, value1 = v1, value2 = v2) # 合并到结果数据框 data2 <- rbind(data2, temp) } # 重置行名,让结果更整洁 rownames(data2) <- NULL
运行这段代码后,同样能得到和示例一致的结果。
核心思路其实很简单:先确定需要配对的不同name组,然后对每组name,把它们各自的value做全笛卡尔积组合,最后把所有组的结果合并起来就好啦!
备注:内容来源于stack exchange,提问作者EmilA
相关产品推荐
相关产品推荐

