在R中找出三列中任意两列的共有元素并汇总的方法
解决R语言中找出任意两列共有元素并汇总的问题
没问题,我来帮你搞定这个需求!先明确下你的数据情况:genus_sub里的ID列是微生物分类单元名称,其他以GutREF开头的列是不同样本的存在标记(1表示该分类在对应样本中存在,0表示不存在)。我们要找出任意两个样本列之间共有的存在分类,并完成汇总。
方法一:基础R实现
这种方法不需要额外安装包,用基础R函数就能完成:
步骤1:提取每个样本中存在的分类列表
首先把每个样本里值为1的分类(即ID)提取出来,存成列表:
# 提取所有样本列的名称(排除ID列) sample_cols <- setdiff(names(genus_sub), "ID") # 遍历每个样本列,提取存在的分类ID sample_taxa <- lapply(sample_cols, function(col) { genus_sub$ID[genus_sub[[col]] == 1] }) names(sample_taxa) <- sample_cols
步骤2:生成所有两两样本的组合
用combn函数生成所有不重复的样本对:
# 生成两两样本的组合(返回列表格式) sample_pairs <- combn(sample_cols, 2, simplify = FALSE)
步骤3:计算每对样本的共有分类并汇总
遍历每个样本对,计算交集,然后整理成汇总数据框:
# 计算每对的共有元素并生成汇总结果 summary_list <- lapply(sample_pairs, function(pair) { # 获取两个样本的共有分类 shared_taxa <- intersect(sample_taxa[[pair[1]]], sample_taxa[[pair[2]]]) # 整理成数据框行 data.frame( 样本1 = pair[1], 样本2 = pair[2], 共有分类数量 = length(shared_taxa), 共有分类名称 = paste(shared_taxa, collapse = ", ") ) }) # 合并所有行成最终汇总数据框 final_summary <- do.call(rbind, summary_list)
运行后,final_summary就是你要的汇总结果,包含每对样本的名称、共有分类的数量和具体名称。
方法二:tidyverse风格实现
如果你习惯用tidyverse系列包(比如dplyr、tidyr),可以用更简洁的管道式代码:
library(tidyverse) final_summary <- genus_sub %>% # 把宽格式转成长格式,方便处理 pivot_longer(-ID, names_to = "样本", values_to = "是否存在") %>% # 只保留存在的分类 filter(是否存在 == 1) %>% # 自连接,找到同一个分类出现在不同样本的情况 full_join(., ., by = "ID") %>% # 过滤掉重复的样本对(比如避免同时出现A-B和B-A) filter(样本.x < 样本.y) %>% # 按样本对分组汇总 group_by(样本.x, 样本.y) %>% summarise( 共有分类数量 = n(), 共有分类名称 = paste(ID, collapse = ", "), .groups = "drop" )
这个方法的结果和基础R版本完全一致,代码更直观,适合熟悉tidyverse的用户。
举个例子,你的测试数据里所有样本都存在Oscillospiraceae (B; Firm),所以每对样本的共有分类名称里都会包含这个分类。
内容的提问来源于stack exchange,提问作者Manasi Shah
相关产品推荐
相关产品推荐

