Reputation: 850
My question builds on a another, similar question: passing several arguments to FUN of lapply (and others *apply)
I have a custom function creating a data.frame
. The goal is to retrieve a list of data.frames
for each new input variable (I want to sort of loop over several input variables to create new data.frames
).
I manage to do want I want if only one input variable is changing:
fn <- function(a, b){
data.frame(res = c(a, b, a + b),
text = c("a", "b", "total"))
}
fn(1, 2)
#> res text
#> 1 1 a
#> 2 2 b
#> 3 3 total
lapply(1:3, FUN = fn, b = 1)
#> [[1]]
#> res text
#> 1 1 a
#> 2 1 b
#> 3 2 total
#>
#> [[2]]
#> res text
#> 1 2 a
#> 2 1 b
#> 3 3 total
#>
#> [[3]]
#> res text
#> 1 3 a
#> 2 1 b
#> 3 4 total
However, as soon as I also change the second input variable (b) I receive an error message.
lapply(1:3, FUN = fn, b = 1:3)
Error in data.frame(res = c(a, b, a + b), text = c("a", "b", "total")): arguments imply differing number of rows: 7, 3
A suggested approach in the question above (see link) is to use mapply
. This works, but
returns a matrix
which I interpret as a list of lists (please correct me if I am wrong).
x <- mapply(fn, b = 1:3, a = 1:3)
x
#> [,1] [,2] [,3]
#> res Integer,3 Integer,3 Integer,3
#> text factor,3 factor,3 factor,3
To get my desired list of data.frames
I could again use apply
:
apply(x, 2, data.frame)
#> [[1]]
#> res text
#> 1 1 a
#> 2 1 b
#> 3 2 total
#>
#> [[2]]
#> res text
#> 1 2 a
#> 2 2 b
#> 3 4 total
#>
#> [[3]]
#> res text
#> 1 3 a
#> 2 3 b
#> 3 6 total
Created on 2019-05-22 by the reprex package (v0.2.1)
Question: is there a way to avoid mapply
followed by apply
to set more than one input variable in a custom made function?
Upvotes: 0
Views: 446
Reputation: 6441
You can do:
library(purrr)
map2(1:3, 1:3, fn)
[[1]]
res text
1 1 a
2 1 b
3 2 total
[[2]]
res text
1 2 a
2 2 b
3 4 total
[[3]]
res text
1 3 a
2 3 b
3 6 total
If you wanto to stick to mapply you can do:
x <- mapply(fn, b = 1:3, a = 1:3, SIMPLIFY = F)
or
x <- Map(fn, b = 1:3, a = 1:3)
which is a wrapper for mapply with SIMPLIFY = F
.
Upvotes: 2