Search code examples
rfor-loopdataframeworkspaceeuclidean-distance

Running the same function multiple times and saving results with different names in workspace


So, I built a function called sort.song.

My goal with this function is to randomly sample the rows of a data.frame (DATA) and then filter it out (DATA.NEW) to analyse it. I want to do it multiple times (let's say 10 times). By the end, I want that each object (mantel.something) resulted from this function to be saved in my workspace with a name that I can relate to each cycle (mantel.something1, mantel.somenthing2...mantel.something10).

I have the following code, so far:

 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)
   }
}

Could someone please help me to do it the right way?

I think I'm not assigning the cycles correctly for each mantel.somenthing object.

Many thanks in advance!


Solution

  • The best way to implement what you are trying to do is through a list. You can even make it take two indices, the first for the iterations, the second for the type of analysis.

    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)
    

    In this way you can index your specific analysis for each iteration in an intuitive way:

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

    EDIT by Mohr: Just for clarification...

    So, according to your suggestion the code should be something like this:

    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)
    }