2

I have the follwing code that takes a dataframe called dft1 and then produces a resulting dataframe called dfb1. I want to repeat the same code for multiple input dataframes such as dft1, dft2 all indexed by a number towards the end and then store the results using the same pattern i.e. dfb1, dfb2, .... I have tried many methods such as using dapply or for loops but given the nature of the code inside I wasn't able to get the intended results.


#define the function for rolling

window <- 24
rolling_lm <- 
  rollify(.f = function(R_excess, MKT_RF, SMB, HML) {
    lm(R_excess ~ MKT_RF + SMB + HML)
  }, window = window, unlist = FALSE)

#rolling over the variable 

dfb1 <-
  dft1 %>% 
  mutate(rolling_ff = 
           rolling_lm(R_excess, 
                      MKT_RF, 
                      SMB, 
                      HML)) %>% 
  mutate(tidied = map(rolling_ff, 
                      tidy, 
                      conf.int = T)) %>% 
  unnest(tidied) %>% 
  slice(-1:-23) %>% 
  select(date, term, estimate, conf.low, conf.high) %>% 
  filter(term != "(Intercept)") %>% 
  rename(beta = estimate, factor = term) %>% 
  group_by(factor)
Erwin Rhine
  • 303
  • 2
  • 11
  • https://stackoverflow.com/questions/50858296/how-to-apply-same-operation-to-multiple-data-frames-in-dplyr-r – BENY Mar 27 '19 at 01:33

1 Answers1

2

Add the command you want to apply to each dataframe in a function

apply_fun <- function(df) {
   df %>% 
    mutate(rolling_ff = 
         rolling_lm(R_excess, 
                    MKT_RF, 
                    SMB, 
                    HML)) %>% 
    mutate(tidied = map(rolling_ff, 
                    tidy, 
                    conf.int = T)) %>% 
    unnest(tidied) %>% 
    slice(-1:-23) %>% 
    select(date, term, estimate, conf.low, conf.high) %>% 
    filter(term != "(Intercept)") %>% 
    rename(beta = estimate, factor = term) %>% 
    group_by(factor)
}

Now apply the function to each dataframe and store the results in a list

n <- 10
out <- setNames(lapply(mget(paste0("dft", 1:n)), apply_fun), paste0("dfb", 1:n))

Assuming you have input dataframes like dft1, dft2...this will output a list of dataframes which you can now access doing out[['dfb1']], out[['dfb2']] and so on. Change the value of n based on number of dft dataframes you have.

If the data is already present in a list we can avoid mget by doing

setNames(lapply(result, apply_fun), paste0("dfb", 1:n))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Thank you very much for your help. I get an error when i try to run the code: Error in mget(paste0("dft"), 1:n) : second argument must be an environment Also is there a way to do same thing but when your dataframes are within a list e.g. I have a list called result {dft1, dft2, ....} I want to apply my function to the list and get the results as a list of dataframes {dfb1, dfb2,...}. – Erwin Rhine Mar 27 '19 at 13:47
  • @ErwinRhine the `mget` command is used to bring individual dataframes in a list itself, so if you already have them then it's well and good. You could do `setNames(lapply(result, apply_fun), paste0("dfb", 1:n))`. Can you try and let me know if it works? Also in the `mget` attempt I misplaced a bracket, it should have been `setNames(lapply(mget(paste0("dft", 1:n)), apply_fun), paste0("dfb", 1:n))` – Ronak Shah Mar 27 '19 at 13:54
  • 1
    Thank you very much both methods worked, I will stick to using the list since its much easier. – Erwin Rhine Mar 27 '19 at 14:08
  • @RonakShah I'm trying something similar, but the function is returning the same dataframe and not ht filtered one. Any comments? – classy_BLINK Apr 18 '22 at 07:03