[Rd] suggestion: "." in [lsv]apply()
Sokol Serguei
@oko| @end|ng |rom |n@@-tou|ou@e@|r
Thu Apr 16 20:02:17 CEST 2020
Thanks Henrik,
Probably, it will be the solution I'll retain.
Best,
Serguei.
Le 16/04/2020 à 18:50, Henrik Bengtsson a écrit :
> I'm sure this exists elsewhere, but, as a trade-off, could you achieve
> what you want with a separate helper function F(expr) that constructs
> the function you want to pass to [lsv]apply()? Something that would
> allow you to write:
>
> sapply(split(mtcars, mtcars$cyl), F(summary(lm(mpg ~ wt,.))$r.squared))
>
> Such an F() function would apply elsewhere too.
>
> /Henrik
>
> On Thu, Apr 16, 2020 at 9:30 AM Michael Mahoney
> <mike.mahoney.218 using gmail.com> wrote:
>> This syntax is already implemented in the {purrr} package, more or
>> less -- you need to add a tilde before your function call for it to
>> work exactly as written:
>>
>> purrr::map_dbl(split(mtcars, mtcars$cyl), ~ summary(lm(wt ~ mpg, .))$r.squared)
>>
>> is equivalent to
>>
>> sapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
>> d))$r.squared)
>>
>> Seems like using this package is probably an easier solution for this
>> wish than adding a reserved variable and adding additional syntax to
>> the apply family as a whole.
>>
>> Thanks,
>>
>> -Mike
>>
>>> From: Sokol Serguei <sokol using insa-toulouse.fr>
>>> Date: Thu, Apr 16, 2020 at 12:03 PM
>>> Subject: Re: [Rd] suggestion: "." in [lsv]apply()
>>> To: William Dunlap <wdunlap using tibco.com>
>>> Cc: r-devel <r-devel using r-project.org>
>>>
>>>
>>> Thanks Bill,
>>>
>>> Clearly, my first proposition for wsapply() is quick and dirty one.
>>> However, if "." becomes a reserved variable with this new syntax,
>>> wsapply() can be fixed (at least for your example and alike) as:
>>>
>>> wsapply=function(l, fun, ...) {
>>> .=substitute(fun)
>>> if (is.name(.) || is.call(.) && .[[1]]==as.name("function")) {
>>> sapply(l, fun, ...)
>>> } else {
>>> sapply(l, function(d) eval(., list(.=d)), ...)
>>> }
>>> }
>>>
>>> Will it do the job?
>>>
>>> Best,
>>> Serguei.
>>>
>>> Le 16/04/2020 à 17:07, William Dunlap a écrit :
>>>> Passing in a function passes not only an argument list but also an
>>>> environment from which to get free variables. Since your function
>>>> doesn't pay attention to the environment you get things like the
>>>> following.
>>>>
>>>>> wsapply(list(1,2:3), paste(., ":", deparse(s)))
>>>> [[1]]
>>>> [1] "1 : paste(., \":\", deparse(s))"
>>>>
>>>> [[2]]
>>>> [1] "2 : paste(., \":\", deparse(s))" "3 : paste(., \":\", deparse(s))"
>>>>
>>>> Bill Dunlap
>>>> TIBCO Software
>>>> wdunlap tibco.com <http://tibco.com>
>>>>
>>>>
>>>> On Thu, Apr 16, 2020 at 7:25 AM Sokol Serguei <sokol using insa-toulouse.fr
>>>> <mailto:sokol using insa-toulouse.fr>> wrote:
>>>>
>>>> Hi,
>>>>
>>>> I would like to make a suggestion for a small syntactic
>>>> modification of
>>>> FUN argument in the family of functions [lsv]apply(). The idea is to
>>>> allow one-liner expressions without typing "function(item) {...}" to
>>>> surround them. The argument to the anonymous function is simply
>>>> referred
>>>> as ".". Let take an example. With this new feature, the following call
>>>>
>>>> sapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
>>>> d))$r.squared)
>>>> # 4 6 8
>>>> #0.5086326 0.4645102 0.4229655
>>>>
>>>>
>>>> could be rewritten as
>>>>
>>>> sapply(split(mtcars, mtcars$cyl), summary(lm(mpg ~ wt, .))$r.squared)
>>>>
>>>> "Not a big saving in typing" you can say but multiplied by the
>>>> number of
>>>> [lsv]apply usage and a neater look, I think, the idea merits to be
>>>> considered.
>>>> To illustrate a possible implementation, I propose a wrapper
>>>> example for
>>>> sapply():
>>>>
>>>> wsapply=function(l, fun, ...) {
>>>> s=substitute(fun)
>>>> if (is.name <http://is.name>(s) || is.call(s) &&
>>>> s[[1]]==as.name <http://as.name>("function")) {
>>>> sapply(l, fun, ...) # legacy call
>>>> } else {
>>>> sapply(l, function(d) eval(s, list(.=d)), ...)
>>>> }
>>>> }
>>>>
>>>> Now, we can do:
>>>>
>>>> wsapply(split(mtcars, mtcars$cyl), summary(lm(mpg ~ wt, .))$r.squared)
>>>>
>>>> or, traditional way:
>>>>
>>>> wsapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
>>>> d))$r.squared)
>>>>
>>>> the both work.
>>>>
>>>> How do you feel about that?
>>>>
>>>> Best,
>>>> Serguei.
>>>>
>>>> ______________________________________________
>>>> R-devel using r-project.org <mailto:R-devel using r-project.org> mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>
>>>
>>> [[alternative HTML version deleted]]
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> ______________________________________________
>> R-devel using r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list