Claudia
Claudia

Reputation: 83

How to save all repeated loop results in R in a dataframe

I created a loop for bootstrapping of repeated measures, picking one random measurement per sampling day. The loop is supposed to run 100 times.

This is how my input data frame looks like:

  date        spot treatment   site  N2O.units N2O.pv N2O.flux t.air
   <chr>      <int> <chr>       <chr> <chr>     <chr>     <dbl> <dbl>
 1 2019-06-21    31 min 5, bare LV    mg        **       0.0002  16.5
 2 2019-06-21    46 min 5, bare LV    mg        *        0       11.1
 3 2019-07-05    31 min 5, bare LV    mg        **       0.0001  17.2
 4 2019-07-05    36 min 5, bare LV    mg        **       0.0004  18.4
 5 2019-07-05    46 min 5, bare LV    mg        **       0.0001  17.2
 6 2019-07-19    26 min 5, bare LV    mg        ***      0       29.4
 7 2019-07-19    31 min 5, bare LV    mg        ***      0.0002  29.4
 8 2019-07-19    36 min 5, bare LV    mg        **       0.0002  19.9
 9 2019-08-02    26 min 5, bare LV    mg        **       0       26.9
10 2019-08-02    36 min 5, bare LV    mg        **       0.0001  33.9
# ... with 44 more rows

First I created a list

lst <- list()

then I ran the loop (with only five iterations here in the example)

for(i in 1:5)

 {
  LV %>%
    group_by(date) %>%
    sample_n(1) -> result
  print(result$N2O.flux)
  lst[i]<-result$N2O.flux
}

resulting in this output, which actually is perfectly fine and what I wanted

 [1]  2e-04  1e-04  2e-04  1e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00
[14]  0e+00  0e+00  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00 -1e-04  0e+00  0e+00  0e+00
 [1]  0e+00  1e-04  0e+00  0e+00  1e-04  0e+00  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00  0e+00
[14] -2e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00
 [1]  0e+00  4e-04  2e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00  0e+00
[14]  0e+00  1e-04  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00  0e+00 -1e-04  0e+00  0e+00
 [1]  2e-04  1e-04  0e+00  1e-04  1e-04  1e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00
[14] -2e-04  0e+00  0e+00  0e+00  0e+00  1e-04  0e+00  0e+00 -1e-04  0e+00  0e+00  0e+00
 [1]  0e+00  1e-04  2e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00
[14]  0e+00  1e-04  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00  0e+00 -1e-04  0e+00  0e+00

BUT, what I get is only the last value

 str(lst)
List of 5
 $ : num 0
 $ : num 0
 $ : num 2e-04
 $ : num 0
 $ : num 2e-04

which when writing a .csv with write.table(as.data.frame(lst),file="mylist2.csv", quote=F,sep=",",row.names=F) looks like that (pretty awful)

X0 X0.1 X2e.04 X0.2 X2e04.1
0 0 2.00e-04 0 2.00e-04

So, my questions are:

  1. How to save all the loop results per run in a list?
  2. How to assign numbers to the various loop runs so that the results can be printed in neat columns with a numeric value as identifier in a .csv for further processing? In my fantasy the output would look like:
1 2 3 4 5 ...etc 100
0 0 2.00e-04 0 2.00e-04 ... -1e-04
2.00e-04 0 2.00e-04 0 2.00e-04 ... -1e-04
-1e-04 0 4 0 2.00e-04 ... -1e-04
0 2.00e-04 2.00e-04 0 -1e-04 ... -1e-04
-1e-04 0 2.00e-04 0 2.00e-04 ... -1e-04

and so on (25 rows)

Upvotes: 1

Views: 1428

Answers (2)

jay.sf
jay.sf

Reputation: 73842

You probable noticed the warning

Warning message:
In lst[i] <- result$N2O.flux :
  number of items to replace is not a multiple of replacement length

By saying lst[i] <- result$N2O.flux you're attempting to add a vector, i.e. an object with multiple elements as sublist to list lst. In such situations the assigned objects got pruned to the first element, which is stated in the warning.

So either you may list() the vector, to get a single object to assign, by saying

lst[i] <- list(result$N2O.flux)

or access the sublist and add elements to it by saying

lst[[i]] <- result$N2O.flux

Alternatively you could try a different approach which gives you a matrix with dates in the rows and draws in the columns:

set.seed(42)
res <- replicate(n=5, sapply(split(LV$N2O.flux, LV$date), sample, 1))
res
#             [,1]  [,2]  [,3]  [,4]  [,5]
# 2019-06-21 2e-04 0e+00 0e+00 2e-04 0e+00
# 2019-07-05 1e-04 4e-04 1e-04 1e-04 4e-04
# 2019-07-19 0e+00 2e-04 2e-04 2e-04 2e-04
# 2019-08-02 0e+00 0e+00 1e-04 1e-04 0e+00

write.csv(res, file='test.csv')

which gives you

enter image description here


Data:

LV <- structure(list(date = c("2019-06-21", "2019-06-21", "2019-07-05", 
"2019-07-05", "2019-07-05", "2019-07-19", "2019-07-19", "2019-07-19", 
"2019-08-02", "2019-08-02"), spot = c(31L, 46L, 31L, 36L, 46L, 
26L, 31L, 36L, 26L, 36L), treatment = c("min 5, bare", "min 5, bare", 
"min 5, bare", "min 5, bare", "min 5, bare", "min 5, bare", "min 5, bare", 
"min 5, bare", "min 5, bare", "min 5, bare"), site = c("LV", 
"LV", "LV", "LV", "LV", "LV", "LV", "LV", "LV", "LV"), N2O.units = c("mg", 
"mg", "mg", "mg", "mg", "mg", "mg", "mg", "mg", "mg"), N2O.pv = c("**", 
"*", "**", "**", "**", "***", "***", "**", "**", "**"), N2O.flux = c(2e-04, 
0, 1e-04, 4e-04, 1e-04, 0, 2e-04, 2e-04, 0, 1e-04), t.air = c(16.5, 
11.1, 17.2, 18.4, 17.2, 29.4, 29.4, 19.9, 26.9, 33.9)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"))

Upvotes: 1

andtsouris
andtsouris

Reputation: 26

As you want to extract a csv it would be better to directly make a data frame with your results. An easy way to do this is :

all_iter <- data.frame()
for(i in 1:5) {
  result <- LV %>%group_by(date) %>%sample_n(1)
  print(result$N2O.flux)
  all_iter <- all_iter %>% rbind(c(i, result$N2O.flux))
}

Each row of all_iter corresponds to an iteration. The first column corresponds to the iteration number and the rest to the values for that iteration.

Then you can export all_iter using :

write.csv(all_iter, 'all_iterations_result.csv', quote=F,sep=",",row.names=F)

Upvotes: 0

Related Questions