多次运行相同的功能并在工作区中使用不同的名称保存结果

时间:2014-04-16 19:34:35

标签: r for-loop dataframe workspace euclidean-distance

所以,我构建了一个名为 sort.song 的函数。

我使用此函数的目标是随机采样data.frame(DATA)的行,然后将其过滤掉(DATA.NEW)以进行分析。我想多次这样做(让我们说10次)。最后,我希望将这个函数产生的每个对象(mantel.something)保存在我的工作空间中,其名称可以与每个循环相关联(mantel.something1,mantel.somenthing2 ... mantel.something10)。

到目前为止,我有以下代码:

 sort.song<-function(DATA){
  require(ade4)
  for(i in 1:10){ # Am I using for correctly here?

   DATA.NEW <- DATA[sample(1:nrow(DATA),replace=FALSE),]
   DATA.NEW <- DATA.NEW[!duplicated(DATA.NEW$Point),]

   coord.dist<-dist(DATA.NEW[,4:5],method="euclidean")
   num.notes.dist<-dist(DATA.NEW$Num_Notes,method="euclidean")
   songdur.dist<-dist(DATA.NEW$Song_Dur,method="euclidean")
   hfreq.dist<-dist(DATA.NEW$High_Freq,method="euclidean")
   lfreq.dist<-dist(DATA.NEW$Low_Freq,method="euclidean")
   bwidth.dist<-dist(DATA.NEW$Bwidth_Song,method="euclidean")
   hfreqlnote.dist<-dist(DATA.NEW$HighFreq_LastNote,method="euclidean")

   mantel.numnotes[i]<<-mantel.rtest(coord.dist,num.notes.dist,nrepet=1000)
   mantel.songdur[i]<<-mantel.rtest(coord.dist,songdur.dist,nrepet=1000)
   mantel.hfreq[i]<<-mantel.rtest(coord.dist,hfreq.dist,nrepet=1000)
   mantel.lfreq[i]<<-mantel.rtest(coord.dist,lfreq.dist,nrepet=1000)
   mantel.bwidth[i]<<-mantel.rtest(coord.dist,bwidth.dist,nrepet=1000)
   mantel.hfreqlnote[i]<<-mantel.rtest(coord.dist,hfreqlnote.dist,nrepet=1000)
   }
}

有人可以帮助我以正确的方式做到吗?

我认为我没有为每个mantel.somenthing对象正确分配周期。

非常感谢提前!

2 个答案:

答案 0 :(得分:2)

实现您要执行的操作的最佳方式是list。您甚至可以使它采用两个索引,第一个用于迭代,第二个用于分析类型。

mantellist <- as.list(1:10)   ## initiate list with some values
for (i in 1:10){
...
mantellist[[i]] <- list(numnotes=mantel.rtest(coord.dist,num.notes.dist,nrepet=1000),
                        songdur=mantel.rtest(coord.dist,songdur.dist,nrepet=1000),
                        hfreq=mantel.rtest(coord.dist,hfreq.dist,nrepet=1000),
                        ...)
}
return(mantellist)

通过这种方式,您可以直观地为每次迭代索引特定分析:

mantellist[[2]][['hfreq']]
mantellist[[2]]$hfreq       ## alternative

莫尔编辑: 只是为了澄清...

所以,根据你的建议,代码应该是这样的:

sort.song<-function(DATA){
  require(ade4)
  mantellist <- as.list(1:10) 
  for(i in 1:10){
    DATA.NEW <- DATA[sample(1:nrow(DATA),replace=FALSE),]
    DATA.NEW <- DATA.NEW[!duplicated(DATA.NEW$Point),]

    coord.dist<-dist(DATA.NEW[,4:5],method="euclidean")
    num.notes.dist<-dist(DATA.NEW$Num_Notes,method="euclidean")
    songdur.dist<-dist(DATA.NEW$Song_Dur,method="euclidean")
    hfreq.dist<-dist(DATA.NEW$High_Freq,method="euclidean")
    lfreq.dist<-dist(DATA.NEW$Low_Freq,method="euclidean")
    bwidth.dist<-dist(DATA.NEW$Bwidth_Song,method="euclidean")
    hfreqlnote.dist<-dist(DATA.NEW$HighFreq_LastNote,method="euclidean")

    mantellist[[i]] <- list(numnotes=mantel.rtest(coord.dist,num.notes.dist,nrepet=1000),
                       songdur=mantel.rtest(coord.dist,songdur.dist,nrepet=1000),
                       hfreq=mantel.rtest(coord.dist,hfreq.dist,nrepet=1000),
                       lfreq=mantel.rtest(coord.dist,lfreq.dist,nrepet=1000),
                       bwidth=mantel.rtest(coord.dist,bwidth.dist,nrepet=1000),
                       hfreqlnote=mantel.rtest(coord.dist,hfreqlnote.dist,nrepet=1000)
                       )
  }
  return(mantellist)
}

答案 1 :(得分:1)

您可以在不使用明确的for循环的情况下实现重复此练习10次(或更多次)的目标。不要让函数运行循环,而是编写sort.song函数来运行该过程的一次迭代,然后您可以使用replicate重复该过程,但需要多次。

通常不要在全局环境中创建一堆命名对象。相反,您可以在单个对象中保存此过程的每次迭代的结果。 replicate将返回一个数组(如果可能),否则返回一个列表(在下面的示例中,列表列表)。因此,列表将包含10个元素(每次迭代一个),每个元素本身就是一个包含与mantel.rtest的每个结果对应的命名元素的列表。

sort.song<-function(DATA){
   DATA.NEW <- DATA[sample(1:nrow(DATA),replace=FALSE),]
   DATA.NEW <- DATA.NEW[!duplicated(DATA.NEW$Point),]

   coord.dist <- dist(DATA.NEW[,4:5],method="euclidean")
   num.notes.dist <- dist(DATA.NEW$Num_Notes,method="euclidean")
   songdur.dist <- dist(DATA.NEW$Song_Dur,method="euclidean")
   hfreq.dist <- dist(DATA.NEW$High_Freq,method="euclidean")
   lfreq.dist <- dist(DATA.NEW$Low_Freq,method="euclidean")
   bwidth.dist <- dist(DATA.NEW$Bwidth_Song,method="euclidean")
   hfreqlnote.dist <- dist(DATA.NEW$HighFreq_LastNote,method="euclidean")

   return(list(
      numnotes = mantel.rtest(coord.dist,num.notes.dist,nrepet=1000),
      songdur = mantel.rtest(coord.dist,songdur.dist,nrepet=1000),
      hfreq = mantel.rtest(coord.dist,hfreq.dist,nrepet=1000),
      lfreq = mantel.rtest(coord.dist,lfreq.dist,nrepet=1000),
      bwidth = mantel.rtest(coord.dist,bwidth.dist,nrepet=1000),
      hfreqlnote = mantel.rtest(coord.dist,hfreqlnote.dist,nrepet=1000)
   ))
}

require(ade4)
replicate(10, sort.song(DATA))