Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
A bit more on our replyr R package.
library("replyr")
help(let, package='replyr')
| let {replyr} | R Documentation |
Prepare expr for execution with name substitutions specified in alias.
Description
replyr::let implements a mapping from desired names (names used directly in the expr code) to names used in the data. Mnemonic: "expr code symbols are on the left, external data and function argument names are on the right."
Usage
let(alias, expr)
Arguments
alias |
mapping from free names in expr to target names to use. |
expr |
block to prepare for execution |
Details
Code adapted from gtools::strmacro by Gregory R. Warnes (License: GPL-2, this portion also available GPL-2 to respect gtools license). Please see the replyr vignette for some discussion of let and crossing function call boundaries: vignette('replyr','replyr'). Transformation is performed by substitution on the expression parse tree, so be wary of name collisions or aliasing.
Something like replyr::let is only useful to get control of a function that is parameterized (in the sense it take column names) but non-standard (in that it takes column names from non-standard evaluation argument name capture, and not as simple variables or parameters). So replyr:let is not useful for non-parameterized functions (functions that work only over values such as base::sum), and not useful for functions take parameters in straightforward way (such as base::merge‘s "by" argument). dplyr::mutate is an example where we can use a replyr::let helper. dplyr::mutate is parameterized (in the sense it can work over user supplied columns and expressions), but column names are captured through non-standard evaluation (and it rapidly becomes unwieldy to use complex formulas with the standard evaluation equivalent dplyr::mutate_).
Value
item ready to evaluate, need to apply with "()" to perform the evaluation in own environment.
See Also
replyr_mapRestrictCols
Examples
library('dplyr')
d <- data.frame(Sepal_Length=c(5.8,5.7),
Sepal_Width=c(4.0,4.4),
Species='setosa',
rank=c(1,2))
mapping = list(RankColumn='rank',GroupColumn='Species')
let(alias=mapping,
expr={
# Notice code here can be written in
# terms of known or concrete
# names "RankColumn" and "GroupColumn",
# but executes as if we
# had written mapping specified
# columns "rank" and "Species".
#
# restart ranks at zero.
d %>% mutate(RankColumn=RankColumn-1) -> dres
# confirm set of groups.
unique(d$GroupColumn) -> groups
})()
print(groups)
print(length(groups))
print(dres)
# It is also possible to pipe into let-blocks,
# but it takes some extra notation
# (notice the extra ". %>%" at the beginning
# and the extra "()" at the end).
d %>% let(alias=mapping,
expr={
. %>% mutate(RankColumn=RankColumn-1)
})()()
# Or:
f <- let(alias=mapping,
expr={
. %>% mutate(RankColumn=RankColumn-1)
})()
d %>% f
# Be wary of using any assignment to attempt
# side-effects in these "delayed pipelines",
# as the assignment tends to happen during the
# let dereference and not (as one would hope)
# during the later pipeline application. Example:
g <- let(alias=mapping,
expr={
. %>% mutate(RankColumn=RankColumn-1) -> ZZZ
})()
print(ZZZ)
# Notice ZZZ has captured a copy of the
# sub-pipeline and not waited for application of g.
# Applying g performs a calculation,
# but does not overwrite ZZZ.
g(d)
print(ZZZ)
# Notice ZZZ is not a copy of g(d),
# but instead still the pipeline fragment.
# let works by string substitution
# aligning on word boundaries,
# so it does (unfortunately)
# also re-write strings.
let(list(x='y'),'x')()
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
