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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With