How to use for loop to create new data frames using i in the name of data frame in R

Viewed 402

I'm relatively new to R and have been searching this forum for an example. While I have found some similar questions and answers, I still can't seem to get my code to work.

I would like to use a for loop in R to create a series of new data frames that incorporates the temporary value for i in the name of the new data frame. I have the following code in which I would like to create two new data frames: metrics_2013, and metrics_2014. I have some calculations (mutate and filter) to apply to the new dataframes, but I'm leaving that out for simplicity.

yearlist <- as.list(c(2013, 2014))
metrics_ <- data.frame(matrix(ncol = 4, nrow = 0))
for (i in yearlist) {
  
  maxyear <- i
  minyear <- maxyear - 7
  
metrics_[as.character(i)] <- mutatedata %>% 
  group_by(symbol) %>% 
  filter(year>=minyear & year<=maxyear) %>% 
  summarize(
    avgroepercent = mean(roe,na.rm = TRUE), 
    avgrocpercent = mean(roc, na.rm = TRUE),
    epsroc = (((last(eps))/(first(eps)))^(1/(maxyear-minyear))-1)
    )
}

In this case both dataframes (for 2013 and 2014) will be equal to "data", as all I'm having trouble with at the moment is creating data frames with names based on the value of i. I believe that it may have something to do with [], vs [[]], or maybe I need to define metrics_[i] prior to the for loop??? But any assistance is much appreciated!!!

2 Answers

Doing this slightly differently will be a lot simpler and make your life easier in the long run. Instead of having several variables with auto-generated names, have a list whose elements have auto-generated names. e.g.:

data <- data.frame(a=1:2)

metrics <- list()
for (i in yearlist) {
  metrics[as.character(i)] <- data
}

(there may be a better way to do this than with a loop, but that's another topic)

You can try :

library(dplyr)
yearlist <- c(2013, 2014)

lapply(yearlist, function(x) {
  maxyear <- x
  minyear <- maxyear - 7
  
  mutatedata %>% 
    filter(year>=minyear & year<=maxyear) %>% 
    group_by(symbol) %>% 
    summarize(
      avgroepercent = mean(roe,na.rm = TRUE), 
      avgrocpercent = mean(roc, na.rm = TRUE),
      epsroc = (((last(eps))/(first(eps)))^(1/(maxyear-minyear))-1)
    )
}) -> data

where data is a list of dataframes. If you want to create separate dataframes you can use list2env.

names(data) <- paste0('metrics_', yearlist)
list2env(data, .GlobalEnv)
Related