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') 

## 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.

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
# 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')()