Search code examples
rloopsfor-loopnested-loops

How to run a simple for loop with a function within in R?


In the following dataset, I want to computer the function decostand every 72 rows. Do this 10 times. Here is what I tried.

library(vegan)
library(truncnorm)
df <- data.frame(set = rep(c(1:10), each = 72),
                 sp1 = rep(rtruncnorm(72, a=0, b=800, mean = 50, sd = 20), times = 10),
                 sp2 = rep(rtruncnorm(72, a=0, b=800, mean = 70, sd = 20), times = 10),
                 sp2 = rep(rtruncnorm(72, a=0, b=800, mean = 70, sd = 20), times = 10))

for(i in 1:unique(df$set)){
  df.hel <- decostand(df[i:i+71,2:4], method = "hellinger") 
   }

EDIT: I removed the assignment for the for loop. It still only computes only 1 row. The final output needs to be 720 rows.


Solution

  • We can split the subset of columns by 'set', loop over the list and apply the decostand function

    out <- do.call(rbind, lapply(split(df[2:4], df$set), decostand, 
       method = "hellinger"))
    row.names(out) <- NULL
    > dim(out)
    [1] 720   3
    

    Or on a for loop

    unq_se <- unique(df$set)
    df.hel <- vector('list', length(unq_se))
    names(df.hel) <- unq_se
    for(nm in unq_se) {
       tmp <- subset(df, set == nm, select = 2:4)
        df.hel[[nm]] <- decostand(tmp,  method = "hellinger") 
    }
    df.hel_dat <- do.call(rbind, df.hel)
    

    Or with dplyr

    library(dplyr) # version >= 1.1.0
    df %>%
      reframe(decostand(pick(everything()), method = "hellinger"), .by = "set") %>%
      as_tibble()
    # A tibble: 720 × 4
         set   sp1   sp2 sp2.1
       <int> <dbl> <dbl> <dbl>
     1     1 0.496 0.628 0.599
     2     1 0.492 0.592 0.638
     3     1 0.518 0.641 0.566
     4     1 0.602 0.522 0.604
     5     1 0.328 0.695 0.640
     6     1 0.372 0.504 0.779
     7     1 0.416 0.585 0.696
     8     1 0.618 0.300 0.727
     9     1 0.497 0.692 0.523
    10     1 0.552 0.578 0.601
    # … with 710 more rows