Choubi - 1 year ago 76
R Question

# Creating functions in a for loop with lists

I am scratching my head at the following problem:

I am creating two functions inside a for loop with parameters that depend on some dataframe. Each function is then put inside a list.

Printing the parameters inside the for loop shows that eachh function is well defined. Yet, when I use those outside of the loop, only the last parameters are used for both functions. The following example should make that clearer.

``````dt <- data.frame(color = c("red", "blue"),
a = c(3,9),
b = c(1.3, 1.8))
function_list <- list()
for (col in dt\$color) {
a <- dt\$a[dt\$color == col]
b <- dt\$b[dt\$color == col]

foo <- function(x) {
a*x^b
}
print(paste(col, foo(1)))
function_list[[col]] <- foo
}
``````

[1] "red 3"

[1] "blue 9"

``````function_list[["red"]](1)
``````

[1] 9

``````function_list[["blue"]](1)
``````

[1] 9

To note, this is inspired from the following question: R nested for loop to write multiple functions and plot them

The equivalent solution with
`assign`
and
`get`
works (my answer to the previous question).

The relevant values of `a` and `b` are those when you call the function and not when you define it. The way you create the list, they are taken from the global environment. The solution is to create closures. I'd use `Map` for this, but you can do the same with a `for` loop:

``````funs <- Map(function(a, b) function(x) a*x^b, a = dt\$a, b = dt\$b)

print(funs)
#[[1]]
#function (x)
#a * x^b
#<environment: 0x000000000a9a4298>
#
#[[2]]
#function (x)
#a * x^b
#<environment: 0x000000000a9a3728>
``````

Notice the different environments.

``````environment(funs[[1]])\$a
#[1] 3
environment(funs[[2]])\$a
#[1] 9

funs[[1]](1)
#[1] 3
funs[[2]](1)
#[1] 9
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download