Search code examples
rfor-loopcbind

Multiple Variable Values to Function and Cbind Results


This is a continuation of this question here: For-Loop By Columns with existing For-loop by Rows

I have a dataset in which I am using 3 variables: adstock_rate, diminishing_rate, and lag_number . These are currently set to only 1 number each.

Currently I am using the following numbers:

adstock_rate<-0.5
lag_number<-1
diminishing_rate<-0.6

The final output is a dataset with new columns attached to the existing dataset using the function below.

foo1 <- function(dot, lag_val = 1) {
     tmp <- dot
     for(i in (1 + lag_val): length(tmp)) {
           tmp[i] <- tmp[i] + adstock_rate * diminishing_rate * tmp[i - lag_val]
     }
     return(tmp)
   }


advertising_dataset %>%
       group_by(Region) %>%
       mutate_all(funs(adstocked = foo1(., lag_val = lag_number)))

Here is what I am trying to do:

I want to apply this function to different values to these variables. Below are the combinations of these variables:

adstock_rate = c(0.50, 0.60, 0.70)
lag_number = c(0,1)
diminishing_rate = c(0.50, 0.60)

combos<-expand.grid(adstock_rate,lag_number,diminishing_rate)
colnames(combos)[1]<-"AdStock_Rate"
colnames(combos)[2]<-"Lag_Number"
colnames(combos)[3]<-"Diminish_Rate"


head(combos)

   AdStock_Rate Lag_Number Diminish_Rate
1           0.5          0           0.5
2           0.6          0           0.5
3           0.7          0           0.5
4           0.5          1           0.5
5           0.6          1           0.5
6           0.7          1           0.5
7           0.5          0           0.6
8           0.6          0           0.6
9           0.7          0           0.6
10          0.5          1           0.6

I think you would have to make a for-loop or use the apply function to go down the list of rows in the combos dataset.

Here is my attempt:

for(j in combos){
foo1 <- function(dot, lag_val = 1) {
     tmp <- dot
     for(i in (1 + lag_val): length(tmp)) {
           tmp[i] <- tmp[i] + combos[j,1] * combos[j,3] * tmp[i - lag_val]
     }
     return(tmp)
   }


advertising_dataset %>%
       group_by(Region) %>%
       mutate_all(funs(adstocked = foo1(., lag_val = combos[j,2])))

##cbind to previous output
}

I also need the column names to have the number values such as adstock_0.5_1_0.6 where 0.5 = adstock rate, 1 = lag number, and diminishing = 0.6.

Hope this makes sense.

Please let me know if you need me to provide any more info.

Thanks!


Solution

  • As we are looping through the rows of 'combos', create a list that have the same length as the number of rows of the 'combos' for storing the output from the for loop

    lst <- vector("list", nrow(combos)) # initialize a list to store output
    

    Add some more parameters in the 'foo1' for more flexibility

    foo1 <- function(dot, lag_val = 1, combos, ind) {
         tmp <- dot
         for(i in (1 + lag_val): length(tmp)) {
               tmp[i] <- tmp[i] + combos[ind,1] * combos[ind,3] * tmp[i - lag_val]
         }
         return(tmp)
       }
    

    and then loop through the rows of 'combos'

    for(j in seq_len(nrow(combos))){
    
    # assign the group by recursive output to each `list` element        
    
    
    lst[[j]] <- advertising_dataset %>%
                 group_by(Region) %>%
                 mutate_all(funs(adstocked =
                   foo1(., lag_val = combos[j,2], combos, ind = j)))
    
    }
    lst
    

    It is not clear whether we need the list names to be 'adstock_Rate_Number_Drate' or not. If that is that case,

    names(lst) <- paste0("adstock_", do.call(paste, c(combos, sep="_")))
    

    Convert the list of data.frame to a single data.frame having an 'id' column to indicate the combination

    out <- bind_rows(lst, .id = 'id')
    head(out, 3)
    # A tibble: 3 x 6
    # Groups:   Region [1]
    #  id        Region advertising advertising2 advertising_adst… advertising2_ads…
    #  <chr>      <dbl>       <dbl>        <dbl>             <dbl>             <dbl>
    #1 adstock_…    500        118.         43.9              147.              54.9
    #2 adstock_…    500        120.        231.               150.             289. 
    #3 adstock_…    500        126.         76.8              157.              96.0