How to wrap an R function that accepts a scalar so it will accept a vector? - r

I have a function in R that accepts a scalar value quite nicely, but it doesn't accept a vector.
Is there any way to place a wrapper over it, so this wrapper function can accept a vector?
The function itself has 5 parameters.
What I've tried
I've tried every combination of sapply, lapply and mapply I can think of, and R keeps on giving errors that are somewhat obscure, to say the least.

Got it.
The original function call is:
result<-MyFunc(P=34,S=100,X=100,T=1)
Method 1
To make this accept a vector input, simply add mapply in front of the function call and convert the first opening bracket ( into a comma ,:
result<-mapply(MyFunc,P=34,S=100,X=100,T=1)
Method 2
Thanks to #Roland, type ??Vectorize to find a function that can wrap a function to make it accept vectors.
MyFuncOnVector <- Vectorize(MyFunc)
result <- MyFuncOnVector(P=34,S=100,X=100,T=1)
Behind the scenes, Vectorize is calling mapply.

Related

Suppressing parentheses in a function that uses the pipe operator

Can somebody explain why I have to suppress the parentheses for the function is.factor in the command shown below? Student-data was read from a .csv file. I can see the structure of Student-data and I want to select only the factor variables. The command works fine but I cannot see why I cannot write the parentheses. I saw an example in the forum. Sorry if the question is silly or has been asked before. I could not find any similar question.
studentData%>%select_if(is.factor)
It's not the pipe, %>%, that requires you to "drop the brackets, it's select_if. From the documentation:
.predicate "A predicate function to be applied to the columns or a logical vector. The variables for which .predicate is or returns TRUE are selected. This argument is passed to rlang::as_function() and thus supports quosure-style lambda functions and strings representing function names."
You're not evaluating the function here. You're passing an R object. (Functions are objects, just as data.frames or scalars are). The evaluation happens later, in the guts of select_if. Including the brackets would tell R to evaluate the function at the time the select_if call was executed. That's not correct. It needs to be evaluated later.

How to use apply() with my function

bmi<-function(x,y){
(x)/((y/100)^2)
}
bmi(70,177) it can work
but with apply() it does't work
apply(Student,1:2,bmi(Student$weight,Student$height))
Error in match.fun(FUN) :
'bmi(Student$weight, Student$height)' is not a function, character or symbol
It's a bit unclear what the goal is. If it's just to get an answer, then the comments do answer it. If on the other hand, the goal is to understand what you are doing wrong, then read on. I'd say the first error going from left to right is passing the whole dataframe. I would have only passed the 'height' and 'weight' columns.
The next error, again going from left to right, is the use of 1:2 as the second argument to apply. You obviously want to do this "by rows" which mean you should use only 1, i.e. the first dimension of the dataframe.
And the third error is using a function call rather than the function name. Functions with arguments in parentheses don't work when an R function (meaning apply in this case) is expecting a function name or an anonymous function as illustrated in comments.
Fourth error is not assigning the value to a column in your dataframe. So this probably would have succeeded in making the desired extra column via the apply method. But, as noted in comments this is not the most efficient method.:
Student$bmi_val <- apply(Student[ ,c("weight", "height")], bmi)
# didn't want my column name to be the same as the function name
The apply function was actually designed to work with matrices and arrays, so for many purposes it is ill-suited when used with dataframes. In this case where all the arguments to the bmi function are numeric and you can control the order of argument in the first argument to match the x and y positions, it's arguably an acceptable strategy, but not most R-ish method. When working with dates or factor variables, you should definitely avoid apply.

using clusterApply with unknown number of arguments

I want to be able to generalise the behavior of clusterApply() so that I can parallelise functions with different number of arguments.
Normally, I use clusterApply() like this:
clusterApply(cl=cl,seq_len(nsim),FUN=runsim,arg1,arg2,arg3)
But what if I don't know how many arguments function runsim has? I was thinking of using do.call("runsim",listofArguments), but I don't know if I can use it inside of clusterApply.
Any suggestions?
The main issue seems to be the fact that do.call wants the function (or name thereof) as first argument while clusterApply, like all functions from the apply family, passes the iterated over object as the first argument to the function it calls. Consequently one solution could be:
clusterApply(cl=cl,seq_len(nsim),FUN=function(x) do.call(rumsim, args = list(...)))
... can now be filled with whatever different arguments there are including the possibility to hand over x (i.e., the slice of the iterated over object, in this case the simulation number).
I do not see the need to also wrap clusterApply into do.call as you know which function to call (clusterApply).

Naming columns of coefficient matrix in a VAR

I am searching for a fast and simple way to give comprehensible names to the columns of a VAR-coefficient matrix.
What I would like to use is the function VAR.names, which is used in the function VAR.est() in the VAR.etp-package. When I use the function VAR.est(), this works perfectly, but as soon as I modify VAR.est (by adding another element to the list of values which are returned), I receive an error message stating "could not find function VAR.names".
I could not find any information on the function VAR.names.
Example:
library(VAR.etp)
data(dat)
M=VAR.est(dat,p=2,type="const")
M$coef
Another possibility would be to use a loop as in the function VAR() from the vars package, but if VAR.names would actually work, this would be a lot more elegant!

R - where can vectorize happen?

So clearly one way to vectorize a function is WITHIN the function - either explicitly iterate over inputs or utilize other functions that have been vectorized. Is there a way to mark or tag a function as being/treated as vectorized so that the iteration is managed by the R platform? The analogy would be attributes in c# or annotations in Java. I tell R that this function should be treated as vectorized and it feeds that input one at a time into the function, constructing the vector output? Or am I just thinking about this whole thing incorrectly?
You can use the Vectorize function (http://stat.ethz.ch/R-manual/R-patched/library/base/html/mapply.html), to make the function take vectors.
But here it just uses the mapply function to do the vectorization. As Gavin said, you are just hiding the loop.

Resources