[Rd] suggestion: "." in [lsv]apply()

Henrik Bengtsson henr|k@bengt@@on @end|ng |rom gm@||@com
Thu Apr 16 18:50:06 CEST 2020


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