Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting closure to character in R

Tags:

r

I have data and a working summary function:

[data:]       x = runif(100)

[function 1:] sapply(list("mean", "median", "sd"),
                  function(f) array(do.call(f, list(x)),
                  dimnames=list(f)))

     mean    median        sd 
0.5198142 0.5566567 0.3048372  

The following also runs, but without giving the dimnames:

[function 2:] sapply(list(mean, median, sd), 
                  function(f) array(do.call(f, list(x))))

[1] 0.5198142 0.5566567 0.3048372

I have unsuccessfully tried various combinations of quote(), enquote(), substitute(), deparse() etc to give me the same results with function 2 (where the functions to be applied are not quoted) as I got from function 1. I would like to find something of the following form, if it exists, which yields the same results as function 1:

[function 3:] sapply(list(mean, median, sd), 
                  function(f) array(do.call(f, list(x)), 
                  dimnames=list(SOMEFUNCTION(f))))

My understanding of the problem is I need to use function that will quote mean, median and sd but after f has been partially evaluated; all my attempts at this have failed.

I started off writing the function like function 3; rewriting as function 1 was the only way I could get the desired output, however I can't help but feel that there is some way to achieve this without the quotation marks in function 1.

As this area is a little confusing to me, could you please explain why your solution works, in addition to providing the code.

Thanks.

like image 440
ds440 Avatar asked Sep 06 '25 17:09

ds440


2 Answers

Assuming your functions are closures:

set.seed(0)
x = runif(100)

sapply(list(mean, median, sd), 
                  function(f){
funcs <- ls(environment(f))
names <- funcs[which(sapply(lapply(funcs,get,environment(f)),function(y)identical(y,f)))]
array(do.call(f, list(x)),dimnames=list(names))
}
)

#     mean    median        sd 
#0.5207647 0.4878107 0.2701225 

Its not very eloquent. If you cannot name your list of functions then you could check the environment of a given function. Using identical you can compare your function against the objects in that functions environment.

Closures dont have a name component.

It all seems very contrived however and approaching the problem from a different angle can probably avoid the need to do the above.

like image 186
user1609452 Avatar answered Sep 09 '25 08:09

user1609452


you simply have to name the elements:

sapply(list(mean=mean, median=median, sd=sd), 
              function(f) array(do.call(f, list(x))))

#      mean    median        sd 
# 0.5151791 0.4883450 0.2723679 

sapply(list(orUse=mean, YourChoice=median, OfNames=sd), 
        function(f) array(do.call(f, list(x))))

 #     orUse YourChoice    OfNames 
 # 0.5151791  0.4883450  0.2723679 
like image 39
Ricardo Saporta Avatar answered Sep 09 '25 07:09

Ricardo Saporta