我想使用BiomaRt
包查询数据库。我有loci
并希望检索一些相关信息,比如description
。
我首先尝试使用lapply
,但对执行任务所需的时间感到惊讶。因此,我尝试了更基本的for-loop
并获得更快的结果。
我的代码或我对apply
的理解是预期的还是错误的?我阅读了有关*apply
vs for-loop
效果(Here, for example)的其他帖子,我知道不应该预期会有更好的表现,但我不明白为什么这里的表现实际上是下
这是一个可重复的例子。
1)加载库并选择数据库:
library("biomaRt")
athaliana <- useMart("plants_mart_14")
athaliana <- useDataset("athaliana_eg_gene",mart=athaliana)
2)查询数据库:
loci <- c("at1g01300", "at1g01800", "at1g01900", "at1g02335", "at1g02790",
"at1g03220", "at1g03230", "at1g04040", "at1g04110", "at1g05240"
)
我创建了一个在lapply
中使用的函数:
foo <- function(loci) {
getBM("description","tair_locus",loci,athaliana)
}
当我在第一个元素上使用此函数时:
> system.time(foo(cwp_loci[1]))
utilisateur système écoulé
0.020 0.004 1.599
当我使用lapply
检索所有值的数据时:
> system.time(lapply(loci, foo))
utilisateur système écoulé
0.220 0.000 16.376
然后我创建了一个新功能,添加了for-loop
:
foo2 <- function(loci) {
for (i in loci) {
getBM("description","tair_locus",loci[i],athaliana)
}
}
结果如下:
> system.time(foo2(loci))
utilisateur système écoulé
0.204 0.004 10.919
当然,这将应用于loci
的大列表,因此需要效果最佳的选项。我感谢您的帮助。
编辑按照@MartinMorgan的建议
简单地将向量loci
传递给getBM可以极大地提高查询效率。更简单更好。
> system.time(lapply(loci, foo))
utilisateur système écoulé
0.236 0.024 110.512
> system.time(foo2(loci))
utilisateur système écoulé
0.208 0.040 116.099
> system.time(foo(loci))
utilisateur système écoulé
0.028 0.000 6.193
答案 0 :(得分:4)
我觉得这与lapply vs for循环无关。有一个数据库的呼叫需要1.6秒,lapply这样做10次,即总共16秒。 for循环没有什么不同,它调用数据库10次。但是,它执行apply循环所执行的相同查询,可能导致数据库返回缓存结果而不是查询数据库。这可以通过反转调用的顺序来检查,以查看时间是否有利于lapply。感谢@JoshuaUlrich在聊天中建议数据库缓存。除了数据库缓存(或网络服务器的缓存)之外,@ MartinMorgan的建议还为getBM
所花费的时间增加了相当多的随机性。
底线,很可能差异在R之外,并且与循环,lapply或for循环的风格无关。
答案 1 :(得分:2)
apply
函数系列虽然是惯用的,但它们只是for
循环的语法糖。他们往往比较慢。正如约兰所指出的那样this has been asked之前就已经过了。
如果您想要加速R中的循环提示,请参阅this volume of R News(pdf)的第46页,称为“R帮助台 - 如何避免此循环或使其更快?”