I have a function f of some vector x
The function in R is written as :
f <- function(x){#insert some function of x here}
I would like to return (-f), which denotes the negative of the function. In the case the function itself is known beforehand, this is a simple exercise.
However, in this case, I don't know what this function is
Could someone please help me with the R code to carry this out? (The output needs to be a function in the vector x.)
An example would be - f(x) = x + 1, then -f(x) = -x - 1
Thank you!
The following function getNegFn() takes a function fn and returns a function which returns the negative return value of fn:
getNegFn <- function(fn){
fnOut <- function(){
- do.call(what=fn, args=as.list(match.call())[-1])
}
formals(fnOut) <- formals(fn)
fnOut
}
An example:
fn <- function(x) x + 1
nFn <- getNegFn(fn=fn)
fn(1)
[1] 2
nFn(1)
[1] -2
Also works if the input function has ... arguments:
fn2 <- function(x, ...) x + sum(unlist(list(...)))
nFn2 <- getNegFn(fn=fn2)
fn2(x=1, y=2)
[1] 3
nFn2(x=1, y=2)
[1] -3
Look into do.call(). You can give it a string of a function's name as an arguement, and that function will then be called with the arguments you provide (in a list()), so, for example, you can do:
funcname<-"mean"
dat<-1:5
do.call(funcname, list(dat))*(-1)
Would run as if you called mean(dat)*(-1), which will give you:
[1] -3
Related
I have a function that looks like
my_function <- function(object)
{
# code goes here
}
I'd like the function (among other things) to print the name of the argument (as passed to the function). So if my function call is:
xxx <- my_function(my_object)
then I'd like to know how to get the function to print out the string "my_object".
Can anyone help please?
A more R-ish solution would be to use substitute (get substitute for obj) in combination with deparse (cast symbol to string):
my_function <- function(obj) {deparse(substitute(obj))}
General R metaprogramming rule: prefer substitute!
my_function(my_object)
## [1] "my_object"
I would suggest next approach which is closer to what you want. For sure you could modify it to obtain other outputs:
#Function
my_function <- function(x)
{
as.character(eval(parse(text=enquo(x)))[2])
}
#Apply
my_function(x = my_object)
Output:
[1] "my_object"
An improvement thanks to #MrFlick is next:
#Function
my_function <- function(x)
{
rlang::as_label(rlang::enquo(x))
}
#Apply
my_function(x = my_object)
Which produces same output with a more elegant style in the function:
[1] "my_object"
To display the entire call use match.call like this:
f <- function(x) { print(match.call()); x }
f(pi)
## f(x = pi)
## [1] 3.141593
IF it is desired to display the call just for debugging without modifying the function itself then use trace:
g <- function(x) x # test function
trace(g)
g(pi)
## trace: g(pi)
## [1] 3.141593
I'm trying to create a function that subtracts 2 from each element of a vector, and whenever I pass a vector as a parameter to the function, it's outputting an error:
Error in sub(x) : argument "x" is missing, with no default.
so I have a vector that's called x1,
and my function call looks like that: sub(x1)
any help will be appreciated.
sub <- function(x)
{
for(i in 1:length(x))
{
x[i] = x[i]-2
}
return(x)
}
In R a lot of function and operators (just a special form of functions) are vectorised. Vectorisation means that a function/operator works automatically on all elements of an vector (or vector like object).
Therefore, our problem can be solved with much less code. In addition using vectorised functions (especially basic stuff like +, -, ...) is much much much faster than looping over elements.
# define function that does subtraction
sub <- function(x){
x - 2
}
# define vector with numbers ranging from 1 to 20
my_vector <- 1:20
# call function with my_vector as argument
sub(my_vector)
In regard to your error:
Error in sub(x) : argument "x" is missing, with no default.
It is telling you that you called a function sub() without providing an appropriate value for its argument x. Since you did not provide it, and there is no default, and it cannot find it otherwise R does not know what to do and signals (throws) an error.
I can reproduce your error like so:
# call sub without argument
sub()
## Error in sub() : argument "x" is missing, with no default
I can prevent it by providing a value for argument x, like so:
# call sub with value for x
sub(1)
sub(x = 1)
... Or I can provide defaults like this:
# define function with default values
sub <- function(x = NULL){
x - 2
}
# call new 'robust' sub() function without arguments
sub()
## numeric(0)
... Or I can provide defaults like this:
# define function with default values
sub <- function(x){
if ( missing(x) ){
x <- NULL
}
x - 2
}
# call new 'robust' sub() function without arguments
sub()
## numeric(0)
Resources:
https://www.youtube.com/watch?v=M4fMccWy5lU
https://www.stat.berkeley.edu/~statcur/Workshop2/Presentations/functions.pdf
http://adv-r.had.co.nz/Functions.html
?`function`
https://cran.r-project.org/doc/manuals/r-patched/R-intro.html#Writing-your-own-functions
I suppose you forgot to run your function definition:
sub2 <- function(x)
{
for(i in 1:length(x))
{
x[i] = x[i]-2
}
return(x)
}
sub2(1:4) ## works fine
sub(1:4) ## Error calling the function sub(pattern, replacement, x, ...)
Error in sub(1:4) : argument "x" is missing, with no default
or
> x1 <- 1:4
> sub(x1) ## Error
Error in sub(x1) : argument "x" is missing, with no default
If you would have choosen another name for your function (not a name of an existing R-function) the message is clear (to run in a new R-session):
# sub2 <- function(x)
# {
# for(i in 1:length(x))
# {
# x[i] = x[i]-2
# }
# return(x)
# }
sub2(1:4)
# > sub2(1:4)
# Error in sub2(1:4) : could not find function "sub2"
I commented out the function definition to simulate not running of the function definition
I want to avoid using parse() in a function definition that contains a polynomial().
My polynomial is this:
library(polynom)
polynomial(c(1, 2))
# 1 + 2*x
I want to create a function which uses this polynomial expression as in:
my.function <- function(x) magic(polynomial(c(1, 2)))
where for magic(), I have tried various combinations of expression(), formula(), eval(), as.character(), etc... but nothing seems to work.
My only working solution is using eval(parse()):
eval(parse(text = paste0('poly_function <- function(x) ', polynomial(c(1, 2)))))
poly_function(x = 10)
# 21
Is there a better way to do want I want? Can I avoid the eval(parse())?
Like you, I though that the polynomial function was returning an R expression, but we were both wrong. Reading the help Index for package:polynom would have helped us both:
str(pol)
#Class 'polynomial' num [1:2] 1 2
help(pac=polynom)
So user20650 is correct and:
> poly_function <- as.function(pol)
> poly_function(10)
[1] 21
So this was how the authors (Venables, Hornick, Maechler) do it:
> getAnywhere(as.function.polynomial)
A single object matching ‘as.function.polynomial’ was found
It was found in the following places
registered S3 method for as.function from namespace polynom
namespace:polynom
with value
function (x, ...)
{
a <- rev(coef(x))
w <- as.name("w")
v <- as.name("x")
ex <- call("{", call("<-", w, 0))
for (i in seq_along(a)) {
ex[[i + 2]] <- call("<-", w, call("+", a[1], call("*",
v, w)))
a <- a[-1]
}
ex[[length(ex) + 1]] <- w
f <- function(x) NULL
body(f) <- ex
f
}
<environment: namespace:polynom>
Since you mention in your comments that getAnywhere was new then it also might be the case that you could gain by reviewing the "run up" to using it. If you type a function name at the console prompt, you get the code, in this case:
> as.function
function (x, ...)
UseMethod("as.function")
<bytecode: 0x7f978bff5fc8>
<environment: namespace:base>
Which is rather unhelpful until you follow it up with:
> methods(as.function)
[1] as.function.default as.function.polynomial*
see '?methods' for accessing help and source code
The asterisk at the end of the polynomial version tells you that the code is not "exported", i.e. available at the console just by typing. So you need to pry it out of a loaded namespace with getAnywhere.
It seems like you could easily write your own function too
poly_function = function(x, p){
sum(sapply(1:length(p), function(i) p[i]*x^(i-1)))
}
# As 42- mentioned in comment to this answer,
# it appears that p can be either a vector or a polynomial
pol = polynomial(c(1, 2))
poly_function(x = 10, p = pol)
#[1] 21
#OR
poly_function(x = 10, p = c(1,2))
#[1] 21
I came across this example in Advanced R by Hadley. My question is after defining the function, j(1) outputs the inner function definition as supposed to what j(1)() is outputting? Intuitively, I think j(1) should output [1] 1 2
Could anyone explain what's going on actually? What's the difference between j(1) and j(1)() ?
> j <- function(x) {
+ y <- 2
+ function() {
+ c(x,y)
+ }
+ }
> k <- j(1)
> k()
[1] 1 2
> j(1)
function() {
c(x,y)
}
<environment: 0x7fa184353bf8>
> j()
function() {
c(x,y)
}
<environment: 0x7fa18b5ad0d0>
> j(1)()
[1] 1 2
tl;dr In R, the return value of a function can also be a function. That's the case here. j(1) returns a function, whereas j(1)() returns a numeric vector.
The difference between j(1) and j(1)() is that j(1) outputs a function because that's the last value in the definition of j. Functions return their last expression (or the value found in a relevant return() call), which in this case is also a function. j(1)() is calling the last value of j, which is the function returned from it. It does not take an argument, so the empty parentheses () is the argument list for j(1)
It might become a bit more clear if we have a closer look at j and some of its properties.
j <- function(x) {
y <- 2
function() {
c(x, y)
}
}
The difference between the calls becomes quite apparent when we look at their classes.
class(j(1))
# [1] "function"
class(j(1)())
# [1] "numeric"
When you defined j, 2 is hard-coded into its return function as the second value of the vector returned from that function. We can see the precise return value of a call to j(1) with
library(pryr)
unenclose(j(1))
# function ()
# {
# c(1, 2)
# }
So a call to j(1)() (or k()) will deliver the vector c(1, 2). Similarly, if we call j(5), the return value of j(5)() is c(5, 2)
unenclose(j(5))
# function ()
# {
# c(5, 2)
# }
Hope that helps.
Credit to #Khashaa for mentioning the unenclose() function (comment deleted).
Say I have the following function:
foo <- function(x, y = min(m)) {
m <- 1:10
x + y
}
When I run foo(1), the returned value is 2, as expected. However, I cannot run foo(1, y = max(m)) and receive 11, since lazy evaluation only works for default arguments. How can I supply an argument but have it evaluate lazily?
The simple answer is that you can't and shouldn't try to. That breaks scope and could wreak havoc if it were allowed. There are a few options that you can think about the problem differently.
first pass y as a function
foo<-function(x,y=min){
m<-1:10
x+y(m)
}
if a simple function does not work you can move m to an argument with a default.
foo<-function(x,y=min(m),m=1:10){
x+y(m)
}
Since this is a toy example I would assume that this would be too trivial. If you insist on breaking scope then you can pass it as an expression that is evaluated explicitly.
foo<-function(x,y=expression(min(m))){
m<-1:10
x+eval(y)
}
Then there is the option of returning a function from another function. And that might work for you as well, depending on your purpose.
bar<-function(f)function(x,y=f(m)){
m<-1:10
x+y
}
foo.min<-bar(min)
foo.min(1) #2
foo.max<-bar(max)
foo.max(1) #10
But now we are starting to get into the ridiculous.
My solution was to just change the default argument:
R> formals(foo)$y <- call("max", as.name("m"))
R> foo(1)
[1] 11
You can use a substitute, eval combintation.
foo <- function(x, y = min(m)) {
y <- substitute(y)
m <- 1:10
x + eval(y)
}
foo(1)
## [1] 2
foo(1, y = max(m))
## [1] 11