如何优雅实现tidyr中单列跨分组的所有值组合?
优雅生成多分组值的全交叉组合
你的原始解法虽然能得到预期结果,但随着分组数量增加,手动多次unnest确实会变得很繁琐。这里有两个更简洁且扩展性强的方案,无论你有2个还是N个分组,都能轻松处理:
方法1:用group_split + cross_join
先将每个分组拆分为独立的数据集,再利用dplyr::cross_join直接生成所有分组值的全交叉组合:
library(tidyverse) # 定义原始数据 X <- bind_rows( data_frame(Group = "Group1", Value = LETTERS[1:3]), data_frame(Group = "Group2", Value = letters[4:5]) ) # 拆分每个分组为单独的数据集,并以分组名命名 group_datasets <- X %>% group_split(Group, .keep = FALSE) %>% set_names(unique(X$Group)) # 生成所有分组的全交叉组合 cross_join(!!!group_datasets)
输出结果和你预期的完全一致:
# A tibble: 6 × 2 Group1 Group2 <chr> <chr> 1 A d 2 A e 3 B d 4 B e 5 C d 6 C e
这个方法的优势在于:不管后续新增多少分组,代码都不需要修改——group_split会自动拆分所有分组,cross_join会自动处理所有输入数据集的全组合。
方法2:用pivot_wider + expand_grid
先将分组值转换为列表列并宽表化,再用tidyr::expand_grid展开所有列表的全组合:
X %>% group_by(Group) %>% summarise(Value = list(Value)) %>% # 每个分组的值存为列表 pivot_wider(names_from = Group, values_from = Value) %>% # 转宽表 expand_grid(!!!.) # 展开所有列表列的全组合
同样会得到完全一致的输出,这个方法逻辑更贴近你原始的思路,但用expand_grid替代了多次手动unnest,扩展性拉满。
内容的提问来源于stack exchange,提问作者Artem Sokolov
相关产品推荐
相关产品推荐

