passing several arguments to FUN of lapply (and others *apply)
If you look up the help page, one of the arguments to lapply
is the mysterious ...
. When we look at the Arguments section of the help page, we find the following line:
...: optional arguments to ‘FUN’.
So all you have to do is include your other argument in the lapply
call as an argument, like so:
lapply(input, myfun, arg1=6)
and lapply
, recognizing that arg1
is not an argument it knows what to do with, will automatically pass it on to myfun
. All the other apply
functions can do the same thing.
An addendum: You can use ...
when you're writing your own functions, too. For example, say you write a function that calls plot
at some point, and you want to be able to change the plot parameters from your function call. You could include each parameter as an argument in your function, but that's annoying. Instead you can use ...
(as an argument to both your function and the call to plot within it), and have any argument that your function doesn't recognize be automatically passed on to plot
.
passing more than one argument to FUN of lapply
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
.
Passing multiple arguments to lapply from a dataframe
With apply
in the second argument you need to pass the MARGIN
which is to specify if you want to apply the function row-wise (1) or column-wise (2). Also you would need to use an anonymous function here since your function accepts two separate arguments.
apply(combined, 1, function(x) my_func(x[1], x[2]))
Applying a function with two arguments using Lapply
Change your function to
testFunc<-function(x,y){
return(c(length(x), nrow(y)))
}
By default, a R function returns the last evaluated value
using sapply with a function that has multiple arguments
Use an anonymous function for clarity -
sapply(prep1, function(x) BTm(cbind(win1,win2), player1, player2, data= x))
The same should work with lapply
as well.
R apply function with multiple parameters
Just pass var2 as an extra argument to one of the apply functions.
mylist <- list(a=1,b=2,c=3)
myfxn <- function(var1,var2){
var1*var2
}
var2 <- 2
sapply(mylist,myfxn,var2=var2)
This passes the same var2
to every call of myfxn
. If instead you want each call of myfxn
to get the 1st/2nd/3rd/etc. element of both mylist
and var2
, then you're in mapply
's domain.
R lapply with several dynamic arguments
Your result from mapply() is because the function tries to convert the output to a matrix with the simplify argument by default. You can get your desired output with the following:
prices <- mapply(lots$ticker, FUN = tq_get,
from = lots$buy_date,
get = "stock.prices",
to = today(), SIMPLIFY = FALSE)
Passing a function as an argument to FUN in lapply
Ooh, you're close. You just need the expression to be a function.
fit <- function(x, expr = function(i) splines::bs(i, df = 5)) {
nvars <- ncol(x)
x <- scale(x, center = TRUE, scale = FALSE)
design <- design_mat(x = x, expr = expr, nvars = nvars)
# then fit some model on design
}
send multiple arguments using apply function
Assuming you want to pass the row, and a single argument that is the same for each row:
manydo3 <- function(x, r1) NULL
apply(eq, 1, manydo3, r1=18)
If you want different values for the second argument for each row, then you want to split your matrix into rows and pass both the rows and your other argument with mapply
:
mapply(manydo3, split(eq, row(eq)), R)
where length(R) == nrow(eq)
(i.e. R contains r1, r2, etc).
Using lapply with changing arguments
Apply over list names rather than list elements. E.g.:
somelist <- list('USA'=rnorm(10), 'Europe'=rnorm(10), 'Switzerland'=rnorm(10))
anotherlist <- list('USA'=5, 'Europe'=10, 'Switzerland'=4)
lapply(names(somelist), function(i) somelist[[i]] / anotherlist[[i]])
EDIT:
You also ask if there is a way "except for a loop" to do this "efficiently". You should note that the apply will not necessarily be more efficient. Efficiency will probably be determined by how quick your inner function is. If you want to operate on each elements of a list, you will need a loop, whether it is hidden in an apply() call or not. Check this question: Is R's apply family more than syntactic sugar?
The example I gave above can be re-written as a for loop, and you can make some naive benchmarks:
fun1 <- function(){
lapply(names(somelist), function(i) somelist[[i]] / anotherlist[[i]])
}
fun2 <- function(){
for (i in names(somelist)){
somelist[[i]] <- somelist[[i]] / anotherlist[[i]]
}
return(somelist)
}
library(rbenchmark)
benchmark(fun1(), fun2(),
columns=c("test", "replications",
"elapsed", "relative"),
order="relative", replications=10000)
The output of the benchmark on my machine was this:
test replications elapsed relative
1 fun1() 10000 0.145 1.000000
2 fun2() 10000 0.148 1.020690
Although this is not a real work application and the functions are not realistic tasks, you can see that the difference in computation time is quite negligible.
Related Topics
Checking If Date Is Between Two Dates in R
Ggplot2 Bar Plot, No Space Between Bottom of Geom and X Axis Keep Space Above
Case-Insensitive Search of a List in R
Stop an R Program Without Error
Call by Reference in R (Using Function to Modify an Object)
How to Spread or Cast Multiple Values in R
Adding Regression Line Per Group with Ggplot2
R Assigning Ggplot Objects to List in Loop
Adding X and Y Axis Labels in Ggplot2
Identifying Dependencies of R Functions and Scripts
Exactly Storing Large Integers
Convert Data Frame with Date Column to Timeseries
How to Determine If You Have an Internet Connection in R
How to Add a Factor Column to Dataframe Based on a Conditional Statement from Another Column
Rename Multiple Columns Given Character Vectors of Column Names and Replacement
Add Text to Horizontal Barplot in R, Y-Axis at Different Scale