如何用lapply替代for循环从数据框提取基因计数至空数据框?
问题:批量提取基因计数数据——用apply系列替代for循环的优化方案
背景
需要处理包含数千个基因的数据框,目标是根据指定的基因ID向量快速提取对应计数并返回数据框,计划用apply系列函数替代for循环以提升处理速度。
原始数据表
rawCounts <- data.frame( ensembl_gene_id_version = c('ENSG00000000003.15', 'ENSG00000000005.6', 'ENSG00000000419.14'), HS1 = c(1133, 0, 1392), HS2 = c(900, 0, 1155), HS3 = c(1251, 0, 2011), HS4 = c(785, 0, 1022), stringsAsFactors = FALSE )
原函数与问题现象
原函数定义
extract_counts <- function(df, esdbid){ counts <- data.frame() plyr::ldply(esdbid, function(i) {counts <- df[grep(pattern = i, x = df),] %>% rbind()}) return(counts) }
问题
- 调用
extract_counts(df = rawCounts, esdbid = c('ENSG00000000003.15'))时无任何返回值; - 控制台单独运行单ID代码能返回正确结果,但多ID(如
c('ENSG00000000003.15', 'ENSG00000000005.6', 'ENSG00000000419.14'))时,会重复返回第一个基因ID对应的计数。
问题原因
- 返回值错误:函数内部
ldply的结果未赋值给counts变量,最终返回的是初始定义的空数据框; - 匹配逻辑错误:
grep的x参数传入了整个数据框,而非目标列ensembl_gene_id_version,导致匹配逻辑混乱,多ID时重复匹配到同一行。
解决方案
方案1:base R的lapply + do.call(替代for循环)
extract_counts <- function(df, esdbid){ # 逐个提取基因ID对应的行 result_list <- lapply(esdbid, function(i) { df[df$ensembl_gene_id_version == i, ] }) # 将结果列表合并为数据框 do.call(rbind, result_list) }
测试调用:
extract_counts(rawCounts, c('ENSG00000000003.15', 'ENSG00000000005.6'))
方案2:dplyr批量过滤(更高效,无需循环)
对于大数据框,直接用%in%批量匹配是更高效的方式,无需迭代:
library(dplyr) extract_counts <- function(df, esdbid){ df %>% filter(ensembl_gene_id_version %in% esdbid) }
方案3:修正原plyr::ldply写法
若坚持使用plyr包,需修正匹配列并直接返回ldply结果:
extract_counts <- function(df, esdbid){ plyr::ldply(esdbid, function(i) { df[grep(pattern = i, x = df$ensembl_gene_id_version), ] }) }
内容的提问来源于stack exchange,提问作者Ctat41
相关产品推荐
相关产品推荐

