如何使用多个内部函数和结果使循环更优雅,更短

时间:2018-03-20 19:25:02

标签: r for-loop sapply

以下是我要遵循的步骤:

  1. 按比例范围(例如80-85,85-90)
  2. 子集两个矩阵
  3. 为每个数据子集运行两个单独的距离测量函数
  4. 使用每个数据子集生成的距离矩阵运行一个壁炉架
  5. 生成每个测试结果的列表,每个测试结果都有一个唯一的名称
  6. 生成所有mantel-r结果的数据框及其结果 相应的p值
  7. 我已经编写了完成此过程的代码,但我觉得有一种更优雅,更好的方法。我有什么工作,但我想提高我的R技能,所以任何建议/想法都会受到欢迎。我不是R的新手,但我远不是我想去的地方。

    此外,我的代码会在下面的代码中生成不必要的对象(即SS,HB,sp.dis,epa.dis和nam)。它们并不是什么大不了的事,但如果代码不会产生这种副作用,那就太好了。一个可重现的例子(模仿我的数据格式化)和我正在使用的包如下:

    library(tidyverse)
    library(betapart)
    library(vegan)
    
    set.seed(2)
    spe2<-data.frame(replicate(10,sample(0:100,100,replace=T)))
    spe2$Ag<-round(runif(100, min=0.4, max=1),2)
    epa2<-data.frame(replicate(3,sample(1:20,100,replace=T)))
    epa2$Ag<-spe2$Ag
    
    Mantel.List<-list()
    List.names <- list()
    for(i in seq(from=0.85, to=0.95,by=0.05 )){
      SS<-spe2 %>% 
        filter(Ag >= i & Ag < i+0.05)
      HB<-epa2 %>% 
        filter(Ag >= i & Ag < i+0.05)
      sp.dis<-beta.pair(decostand(SS[,1:ncol(SS)-1],'pa'))
      epa.dis<-vegdist(HB[,1:ncol(HB)-1],
                       method = 'euclidean')
      mnt<-mantel(sp.dis$beta.sor,epa.dis)
      Mantel.List[[length(Mantel.List)+1]] <- mnt
       nam<-paste('M.tt',i*100,sep='')
       List.names[[length(List.names)+1]] <- nam
       }
    names(Mantel.List)<-List.names
    Mantel.Results<-cbind(sapply(Mantel.List, function(x) x$statistic),sapply(Mantel.List, function(x) x$signif))
    colnames(Mantel.Results)<-c('Mantel-r', 'p-value')
    Mantel.Results
    

    谢谢!

1 个答案:

答案 0 :(得分:0)

我做了两件事,试图让这段代码更好一些。首先,我删除了所有不必要的对象,并且我通过使用data.table包来完成此操作,这通常是处理data.frames的最有效方法,因为它在子集化时不会复制自身。

其次,我没有使用for循环,而是使用了apply函数。请注意<a>内的分配器<<-,它将替换函数外部的对象。

这是我的建议:

doit()

这可能有点难以阅读,但它确实更有效率。