1

EDIT: I have a few functions with multiple arguments I'd like to apply over a list of lists. One of the arguments is also a list of lists. Both functions have multiple parameters. two of which I have to indicate recursively across the lists of lists. say I have the two following lists of lists.

mylist <- list(list(10,12,13,14,15), list(5,6,7,8,9))
m <- list(list(2,2,2,3,4), list(3,3,4,4,5))

and the functions

func1 <- function(x, att1 = m, const = 10){
 e <- x^m + const
 return(e)
}

func2 <- function(x, att2 = m, const = 10){
 d <- sqrt(x)/m + const
 return(d)
}

I don't know how to address the right argument, att1 or att2, when I want to call each function. I tried the function below using eval(substitute(att1 = a))

nested_function <- function(df_list, FUN = func1, changing_param = a, ...){

 nested_output <- lapply(seq(df_list), function(i){
   lapply(seq(df_list[[i]]), function(j){
     FUN(df[[i]][[j]], eval(substitute(changing_param))[[i]][[j]],...)
   })
 })

 return(nested_output)
}

result <- nested_function(df_list, FUN = func1, changing_param = 'att1 = a')

and got the following error:

 Error in df[[i]] : object of type 'closure' is not subsettable 
6.
FUN(df[[i]][[j]], eval(substitute(changing_param))[[i]][[j]], 
...) 
5.
FUN(X[[i]], ...) 
4.
lapply(seq(df_list[[i]]), function(j) {
    FUN(df[[i]][[j]], eval(substitute(changing_param))[[i]][[j]], 
        ...)
}) 
3.
FUN(X[[i]], ...) 
2.
lapply(seq(df_list), function(i) {
    lapply(seq(df_list[[i]]), function(j) {
        FUN(df[[i]][[j]], eval(substitute(changing_param))[[i]][[j]], 
            ...) ... 
1.
nested_function(mylist, changing_param = m) 

My problem is how to make the FUN() call recognize a as att1 in func1 and att2 in func2, since I have to designate them for each function (I can't just put the argument there).

any suggestions?

CAOC
  • 323
  • 5
  • 18
  • 1
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. Can't you just pass the value as an unnamed positional parameter? – MrFlick Oct 02 '19 at 19:30
  • I modified my question to add some reproducible example of what I need. – CAOC Oct 02 '19 at 21:10

1 Answers1

1

If you need to dynamically build parameter names, you often have to end up using do.call (at least with base R). I'm sure quite how all your variables were supposed to work in your example, so here's an adapted version that runs.

df_list   <- list(list(10,12,13,14,15), list(5,6,7,8,9))
param_list <- list(list(2,2,2,3,4), list(3,3,4,4,5))

func1 <- function(x, att1 = m, const = 10){
  e <- x^att1 + const
  return(e)
}

func2 <- function(x, att2 = m, const = 10){
  d <- sqrt(x)/att2 + const
  return(d)
}

nested_function <- function(df_list, param_list, FUN = func1, changing_param = "a", ...){
  nested_output <- lapply(seq(df_list), function(i){
    lapply(seq(df_list[[i]]), function(j){
      params <- list(df_list[[i]][[j]], param_list[[i]][[j]], ...)
      names(params)[2] <- changing_param
      do.call(FUN, params)
    })
  })

  return(nested_output)
}

nested_function(df_list, param_list, func1, changing_param = 'att1', const=1)
nested_function(df_list, param_list, func2, changing_param = 'att2', const=2)

Here we pass in the name of the parameter we want as a string. Then when we build the parameter we are going to pass to the function, we rename the parameter we are passing in with the name supplied, then just call the function.

MrFlick
  • 195,160
  • 17
  • 277
  • 295