Function <code>eply()</code>

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.

# Function `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

# Function `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

# Control the evaluation environment

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

# Parallel execution

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.

# Character vector manipulation

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

# More help

    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.