0

I am trying to return three variables( walkpop, cathpop, abovepop) from a function for each iteration of a loop for every combination of other variables in the data; this function is a life history simulator. I can return and create the correct output in a dataframe for one of my variables at a time; my fully working code example returns the desired output for walkpop. However, I would like all of them at once without copying and pasting and change which variable is returned. I have seen and unsuccessfully tried to adapt the following examples unsuccessfully: Store multiple outputs from each iteration of a for loop, How to assign from a function which returns more than one value?, and Return multiple values from apply() function in R.

Working code example that does part of what I need:

library(tidyverse)

#### Create data - Populate all possible combinations of survival and transition rates ####
walksurv = c(0.9269106, 0.970851)
cathsurv = c(.8)
abovesurv = c(0.8334328, 0.9708581)
walktrans_out_A = c(0.0343630, 0.0835229)
walktrans_out_C = c(0.0048465, 0.0273910)
walktrans_in_A = c(0.0768314, 0.2521549)
walktrans_in_C = c(0.0016355, 0.0779052)
abovetrans_out_C = c(0.0142056, 0.1188569)
cathtrans_out_A = c(0)

data = expand.grid(walksurv, cathsurv,
                   abovesurv, walktrans_out_C,
                   walktrans_out_A, walktrans_in_A,
                   walktrans_in_C, abovetrans_out_C,
                   cathtrans_out_A )
colnames(data) = c("walksurv", "cathsurv",
                   "abovesurv", "walktrans_out_C",
                   "walktrans_out_A", "walktrans_in_A",
                   "walktrans_in_C", "abovetrans_out_C",
                   "cathtrans_out_A")

#### Define intial population size ####
walkpop = 10000
abovepop = 1000
cathpop = 100

#### Make life history table function ####
getMC <- function(data){
  walkpop = walkpop*data$walksurv
  cathpop = cathpop*data$cathsurv
  abovepop = abovepop*data$abovesurv
  walkpop_pre_trans = walkpop
  walkpop = walkpop - walkpop_pre_trans*data$walktrans_out_C - walkpop_pre_trans*data$walktrans_out_A
  return(walkpop)

}
#### estimate population change across 13 time steps saving each time step####    
walkpoplist = list()
for (i in 1:13) {
  walkpop = getMC(data)
  walkpoplist[[i]] = walkpop #only works if return is same as variable in return stament

}

poplistwalk = do.call(rbind, lapply(walkpoplist, function(x) as.data.frame(t(x[1:128]))))

Any help is appreciated.

Devon Oliver
  • 295
  • 1
  • 7
  • 20
  • `return(list(walkpop, cathpop, abovepop))`? – r2evans Jul 08 '20 at 03:33
  • Pretty sure I tryed that and it didn't work correctly. I believe it returns correct value for walkpop, but just a repeat of the first iteration for the other two. It may have been the way I try to kick the iterations out to a list. – Devon Oliver Jul 08 '20 at 03:38
  • You are passing same `data` in `getMC` function 13 times. Wouldn't it generate the same value for `walkpop` everytime? – Ronak Shah Jul 08 '20 at 03:42
  • It does not, it updates the population values each time; ie walkpop, cathpop, abovepop, . Because their initial values are not in data and are set outside the loop. You would be correct if their values were included in data. – Devon Oliver Jul 08 '20 at 03:50

1 Answers1

2

You could return a dataframe from getMC function. Also instead of relying on vectors in global environment (walkpop, cathpop etc) pass them into the function.

getMC <- function(data, ref_data){
   walkpop = ref_data$walkpop*data$walksurv
   cathpop = ref_data$cathpop*data$cathsurv
   abovepop = ref_data$abovepop*data$abovesurv
   walkpop_pre_trans = walkpop
   walkpop = walkpop - walkpop_pre_trans*data$walktrans_out_C - 
                       walkpop_pre_trans*data$walktrans_out_A
   return(data.frame(walkpop, cathpop, abovepop))
}


walkpop = 10000
abovepop = 1000
cathpop = 100
ref_data <- data.frame(walkpop, abovepop, cathpop)

totallist = vector('list', 2)
for (i in 1:2) {
  ref_data <- getMC(data, ref_data)
  totallist[[i]] <- ref_data
}

Checking the output.

lapply(totallist, head)
#[[1]]
#   walkpop cathpop abovepop
#1 8905.669      80 833.4328
#2 9327.844      80 833.4328
#3 8905.669      80 970.8581
#4 9327.844      80 970.8581
#5 8696.702      80 833.4328
#6 9108.971      80 833.4328

#[[2]]
#   walkpop cathpop abovepop
#1 7931.094      64 694.6102
#2 8700.868      64 694.6102
#3 7931.094      64 942.5655
#4 8700.868      64 942.5655
#5 7563.262      64 694.6102
#6 8297.335      64 694.6102
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213