The eply
package processes batches of quoted expressions. Just as apply()
acts on data frames of function arguments, eply()
acts on data frames of quoted expressions that return arguments. The package also has evals()
, which simply evaluates a character vector of quoted expressions, plus some nice utilities.
eply()
library(eply)
eply()
applies a function over a data frame of quoted expressions.
Begin with a function.
.fun = example.fun
.fun
## function (x, y)
## {
## mean(x/y)
## }
## <environment: namespace:eply>
Then, make a data frame of quoted expressions that return arguments to .fun
.
.expr = example.expr()
.expr
## x y rep
## 1 subset(mtcars, cyl == 4, mpg, T) a A
## 2 subset(mtcars, cyl == 4, wt, T) a A
## 3 subset(mtcars, cyl == 4, mpg, T) b A
## 4 subset(mtcars, cyl == 4, wt, T) b A
## 5 subset(mtcars, cyl == 4, mpg, T) a B
## 6 subset(mtcars, cyl == 4, wt, T) a B
## 7 subset(mtcars, cyl == 4, mpg, T) b B
## 8 subset(mtcars, cyl == 4, wt, T) b B
# str(.expr) # The expressions are actually just characters.
Define the variables referenced in .expr
.
a = 1
b = 2
For each row in .expr
, eply()
evaluates the expressions and feeds the results to .fun
.
eply(.fun, .expr)
## 1 2 3 4 5 6 7
## 26.663636 2.285727 13.331818 1.142864 26.663636 2.285727 13.331818
## 8
## 1.142864
evals()
evals()
evaluates a character vector of quoted expressions.
evals(c("1+1", "2+2", "3+3"))
## 1+1 2+2 3+3
## 2 4 6
evals(c("1+1", "2+2", "3+3"), .simplify = FALSE)
## $`1+1`
## [1] 2
##
## $`2+2`
## [1] 4
##
## $`3+3`
## [1] 6
a = 4
evals(c("subset(mtcars, cyl == a, mpg, TRUE)", "mtcars[1:2, 1:2]"))
## $`subset(mtcars, cyl == a, mpg, TRUE)`
## [1] 22.8 24.4 22.8 32.4 30.4 33.9 21.5 27.3 26.0 30.4 21.4
##
## $`mtcars[1:2, 1:2]`
## mpg cyl
## Mazda RX4 21 6
## Mazda RX4 Wag 21 6
Use the .with
argument to control the environment in which the expressions are evaluated. .with
can be a list, data frame, or environment. Data in the calling environment may be used as well, so take care to avoid ambiguities.
.fun = function(x) return(x)
.expr = data.frame(x = c("1+a", "1+b"))
rownames(.expr) = c("expr1", "expr2")
a = b = 0
.with = list(a = 1, b = 2)
eply(.fun, .expr, .with)
## expr1 expr2
## 2 3
evals(.expr$x, .with)
## 1+a 1+b
## 2 3
The .with
argument is especially important if you wish to pass eply()
or evals()
to an iteration function like lapply()
.
.expr2 = split(.expr, f = .expr$x) # list of rows of .expr
lapply(.expr2, eply, .fun = .fun, .with = .with)
## $`1+a`
## expr1
## 2
##
## $`1+b`
## expr2
## 3
lapply(c("1+X", "2+Y"), evals, .with = list(X = 1, Y = 2))
## [[1]]
## 1+X
## 2
##
## [[2]]
## 2+Y
## 4
Eply does not implement any special parallel computing functionality. However, the parallel
package may be used on non-Windows machines to distribute subsets of .expr
across parallel processes. The output of parallel::mclapply()
is a list, so take care to simplify if necessary (say, to a data frame).
library(parallel)
.fun = example.fun
expr.dataframe = example.expr()
expr.list = split(expr.dataframe, f = expr.dataframe$rep) # split expr.dataframe by rep
.with = example.with()
mclapply(X = expr.list, FUN = eply, .fun = .fun, .with = .with, mc.cores = 2)
The parallel execution of evals()
with mclapply()
is similar. For an alternative, consider the plyr
package to parallelize eply()
over chunks of .expr
. See the
“Parallel processing” section of the linked guide.
If you want some quoted expressions to evaluate to character strings, enclosed them with literal escaped quotes.
.expr = data.frame(
string = quotes(c("a", "b")),
variable = c("c", "d"))
.expr
## string variable
## 1 "a" c
## 2 "b" d
.fun = function(string, variable) paste(string, variable)
.with = list(c = "C", d = "D")
eply(.fun, .expr, .with)
## 1 2
## "a C" "b D"
You can use single or double quotes.
quotes(c("x", "y"))
## [1] "\"x\"" "\"y\""
quotes(c("x", "y"), single = FALSE)
## [1] "\"x\"" "\"y\""
quotes(c("x", "y"), single = TRUE)
## [1] "'x'" "'y'"
Undo with unquote()
.
.expr$string = unquote(.expr$string)
.expr
## string variable
## 1 a c
## 2 b d
x = quotes(quotes(c("x", "y"), single = TRUE))
x
## [1] "\"'x'\"" "\"'y'\""
unquote(x, deep = TRUE)
## [1] "x" "y"
unquote(x, deep = FALSE)
## [1] "'x'" "'y'"
Turn valid expressions into strings with strings()
.
data.frame(
arg1 = strings(a + b, sqrt(x) - 2),
arg2 = 1:2)
## arg1 arg2
## 1 a + b 1
## 2 sqrt(x) - 2 2
help_eply()
## The eply package has a tutorial at https://CRAN.R-project.org/package=eply/vignettes/eply.html.For troubleshooting, please visit https://github.com/wlandau/eply/blob/master/TROUBLESHOOTING.md.To submit bug reports, questions, feature requests, please seehttps://github.com/wlandau/eply/issues.