【问题标题】:How to use lapply or purrr::map or any other fast way instead of "for loop" with lists?如何使用 lapply 或 purrr::map 或任何其他快速方式而不是列表的“for循环”?
【发布时间】:2019-12-09 17:21:19
【问题描述】:

我正在计算一个索引,该索引需要物种 x 位点的矩阵和物种之间的共生距离矩阵(从系统发育树生成)。这段代码给出了计算它所需的对象(站点和树):

library(ape)#phylogenetic tree
library(picante)#ses.mpd calculation
library(purrr)#list of distance matrices

#Sample matrix
set.seed(0000)
site <- matrix(data = sample(c(0, 1), 15, prob = c(0.4, 0.6), replace = T), ncol = 5, nrow = 3)
colnames(site) <- c("t1", "t2", "t3", "t4", "t5")
rownames(site) <- c("samp1", "samp2", "samp3")

#Sample phylogenetic tree
tree <- rcoal(5)

#Reordering species names in the community to match the order in the tree
site <- site[, tree$tip.label]

根据上面的输出,我需要使用相同的社区矩阵计算 ses.mpd 100 次,但要更改距离矩阵(其中 100 个存储在 4gb 的列表中)。我使用for循环计算ses.mpd,但我意识到要得到输出需要一个多月!我之前用过lapply,但是这次不知道怎么用,purrr::map也不知道。我在这里看到过类似的问题:Apply a function to list of matrices 和这里:Calculate function for all row combinations of two matrices in R,但它们实际上都不像我的问题。这是我在for 循环中使用的代码(由@Parfait 更新)。我需要比循环更快的任何其他方式来获得相同的输出。有什么建议吗?非常感谢!

#Empty list for the resolved trees
many.trees <- list()

#Creates 5 resolved trees with the function ape::multi2di
for(i in 1:5){
  many.trees[[i]] <- multi2di(tree)
}

#For each resolved tree, creates a distance matrix
many.dists <- map(many.trees, cophenetic)

#ses.mpd using each of the distance matrices above
out <- list()

for(i in 1:5){
 out.2[[i]] <- ses.mpd(site, many.dists[[length(many.dists)]])# Thanks, @Parfait.
}

【问题讨论】:

  • 两个代码块调用不同的方法。你有什么需要帮助的?哪个部分需要这么长时间:multi2dicopheneticses.mpd? 4GB 矩阵自然需要很长时间。
  • @Parfait,谢谢!我编辑了问题以使其更清楚。我需要比第二个块中的第二个循环(获取 ses.mpd)更快的东西来获得相同的输出。
  • 您的嵌套循环仅将最后一次 jth 迭代保存到对应的out[[i]]
  • @Parfait,不。在此示例中,它返回一个列表(输出),该列表中有 5 个数据框。每个数据框包含 8 列。其中之一是我需要的 ses.mpd。我刚刚从一开始就运行它,它运行良好。
  • 您的代码将毫无错误地运行,但您的内部循环是多余的,因为您只保存了最后一次运行。删除内部循环并检查是否输出相同的结果:for(i in 1:5) { out[[i]] &lt;- ses.mpd(site, many.dists[[length(many.dists)]]) }

标签: r list for-loop lapply purrr


【解决方案1】:

考虑一个 apply 系列解决方案以获得更紧凑的代码,并避免初始化空列表并分配给它的簿记。

# Creates 5 resolved trees with the function ape::multi2di
many.trees <- replicate(5, multi2di(tree), simplify = FALSE)   

# For each resolved tree, creates a distance matrix
many.dists <- lapply(many.trees, cophenetic)

# ses.mpd using each of the distance matrices above
out_nested <- lapply(many.dists, function(d) ses.mpd(site, d))

要保留名称(如果包含在上述方法中),请将lapply 更改为sapply(等效于lapplysimplify=FALSE,但保留USE.NAMES=TRUE)。结果将被命名为列表。

# For each resolved tree, creates a distance matrix
many.dists <- sapply(many.trees, cophenetic, simplify = FALSE)

# ses.mpd using each of the distance matrices above
out <- sapply(many.dists, function(d) ses.mpd(site, d), simplify = FALSE)

out$first_name
out$second_name
out$third_name
out$fourth_name
out$fifth_name

【讨论】:

  • 谢谢!它至少比之前的代码快两倍。
  • 太棒了!很高兴听到并乐于提供帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
  • 2016-12-03
  • 2017-12-19
  • 2018-05-22
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多