如何将R语言中按类拆分后的DataFrame过滤操作改为循环
批量处理按类别拆分后的DataFrame,筛选特定蛋白组合
问题背景
我有一个大型DataFrame,先通过子集化精简了列:
genesABDF <- select(genes, Species, Class, BfrA, BfrB, Bfd, Ftn)
接着用split()按Class拆分得到列表:
ABDFclass <- split(genesABDF, genesABDF$Class)
之后把单个类别转回DataFrame(比如Alpha变形菌):
alpha <- data.frame(ABDFclass$Alphaproteobacteria)
需求说明
需要针对以下所有类别:Alphaproteobacteria、Betaproteobacteria、Bacteroidetes、Deltaproteobacteria、Enterobacteria、Firmicutes、Gammaproteobacteria,筛选出7种蛋白出现的组合:
- A(BfrA=1,其余为0)
- BD(BfrB=1、Bfd=1,其余为0)
- Ftn(Ftn=1,其余为0)
- ABD(BfrA=1、BfrB=1、Bfd=1,Ftn=0)
- AFtn(BfrA=1、Ftn=1,其余为0)
- BDFtn(BfrB=1、Bfd=1、Ftn=1,BfrA=0)
- ABDFtn(全部为1)
手动筛选的代码可以正常运行,但想改成循环批量处理所有类别:
alphaA <- filter(alpha, BfrA==1 & BfrB==0 & Bfd==0 & Ftn==0) alphaBD <- filter(alpha, BfrA==0 & BfrB==1 & Bfd==1 & Ftn==0) alphaFtn <- filter(alpha, BfrA==0 & BfrB==0 & Bfd==0 & Ftn==1) alphaABD <- filter(alpha, BfrA==1 & BfrB==1 & Bfd==1 & Ftn==0) alphaAFtn <- filter(alpha, BfrA==1 & BfrB==0 & Bfd==0 & Ftn==1) alphaBDFtn <- filter(alpha, BfrA==0 & BfrB==1 & Bfd==1 & Ftn==1) alphaABDFtn <- filter(alpha, BfrA==1 & BfrB==1 & Bfd==1 & Ftn==1)
补充数据(前25行)
structure(list(Species = c("Mycolicibacterium smegmatis", "Streptomyces lydicus", "Agrobacterium fabrum", "Azospirillum brasilense", "Blastochloris viridis", "Brucella abortus", "Cereibacter sphaeroides", "Gluconobacter thailandicus", "Magnetospirillum gryphiswaldense", "Magnetospirillum magnetotacticum", "Reyranella sp.", "Rhizobium borbori", "Rhodospirillaceae bacterium", "Rhodospirillum rubrum", "Alistipes finegoldii", "Flavobacterium psychrophilum", "Mangrovimonas yunxiaonensis", "Maribacter polysiphoniae", "Achromobacter insuavis", "Acidovorax cattleyae", "Acidovorax valerianellae", "Alcaligenes ammonioxydans", "Alcaligenes aquatilis" ), Class = c("Actinobacteria", "Actinobacteria", "Actinobacteria", "Actinobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Alphaproteobacteria", "Bacteroidetes", "Bacteroidetes", "Bacteroidetes", "Bacteroidetes", "Betaproteobacteria", "Betaproteobacteria", "Betaproteobacteria", "Betaproteobacteria", "Betaproteobacteria" ), BfrA = c(0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1), BfrB = c(0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0), Bfd = c(0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0), Ftn = c(1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1)), row.names = c(NA, -25L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
方法1:基础R循环
先定义筛选规则,再遍历所有类别和组合:
# 定义组合规则:名称对应筛选条件 combinations <- list( A = quote(BfrA == 1 & BfrB == 0 & Bfd == 0 & Ftn == 0), BD = quote(BfrA == 0 & BfrB == 1 & Bfd == 1 & Ftn == 0), Ftn = quote(BfrA == 0 & BfrB == 0 & Bfd == 0 & Ftn == 1), ABD = quote(BfrA == 1 & BfrB == 1 & Bfd == 1 & Ftn == 0), AFtn = quote(BfrA == 1 & BfrB == 0 & Bfd == 0 & Ftn == 1), BDFtn = quote(BfrA == 0 & BfrB == 1 & Bfd == 1 & Ftn == 1), ABDFtn = quote(BfrA == 1 & BfrB == 1 & Bfd == 1 & Ftn == 1) ) # 目标类别列表 target_classes <- c("Alphaproteobacteria", "Betaproteobacteria", "Bacteroidetes", "Deltaproteobacteria", "Enterobacteria", "Firmicutes", "Gammaproteobacteria") # 嵌套循环处理所有类别和组合 result_list <- list() for (cls in target_classes) { current_df <- ABDFclass[[cls]] cls_results <- list() for (comb_name in names(combinations)) { cls_results[[comb_name]] <- filter(current_df, eval(combinations[[comb_name]])) } result_list[[cls]] <- cls_results }
结果存储在result_list中,调用result_list[["Alphaproteobacteria"]][["A"]]即可获取Alpha变形菌中符合A组合的DataFrame。
方法2:purrr包简洁实现
library(purrr) # 定义筛选函数 filter_combination <- function(df, comb_condition) { filter(df, eval(comb_condition)) } # 批量处理目标类别,生成嵌套结果列表 result_list <- ABDFclass[target_classes] %>% map(~ map(combinations, ~ filter_combination(.x, .y)))
额外优化:直接生成全局环境变量
如果需要像手动命名那样(如alphaA、betaBD)将结果存入全局环境:
for (cls in target_classes) { current_df <- ABDFclass[[cls]] for (comb_name in names(combinations)) { # 生成变量名:类别前缀+组合名 var_name <- paste0(tolower(substr(cls, 1, 5)), comb_name) assign(var_name, filter(current_df, eval(combinations[[comb_name]]))) } }
可根据需求调整前缀的生成规则。
内容的提问来源于stack exchange,提问作者glitterbox
相关产品推荐
相关产品推荐

