exprApply.Rd
Apply function FUN
to each occurence of a call to what()
(or
a symbol what
) in an unevaluated expression. It can be used for advanced
manipulation of expressions.
Intended primarily for internal use.
exprApply(expr, what, FUN, ..., symbols = FALSE)
an unevaluated expression.
character string giving the name of a function. Each call to
what
inside expr
will be passed to FUN
. what
can be also a character representation of an operator or parenthesis
(including curly and square brackets) as
these are primitive functions in R.
Set what
to NA
to match all names.
a function to be applied.
logical value controlling whether FUN
should be applied
to symbols as well as calls.
optional arguments to FUN
.
A (modified) expression.
FUN
is found by a call to match.fun and can be either
a function or a symbol (e.g., a backquoted name) or a character string
specifying a function to be searched for from the environment of the call to
exprApply
.
If expr
has a source reference information
("srcref"
attribute), modifications done by exprApply
will not be
visible when printed unless srcref
is removed. However, exprApply
does remove source reference from any function
expression inside
expr
.
Expression-related functions: substitute, expression, quote and bquote.
Similar function walkCode
exists in package codetools.
Functions useful inside FUN
: as.name, as.call,
call, match.call etc.
### simple usage:
# print all Y(...) terms in a formula (note that symbol "Y" is omitted):
# Note: if `print` is defined as S4 "standardGeneric", we need to use
# 'print.default' rather than 'print', or put the call to 'print' inside a
# function, i.e. as `function(x) print(x)`:
exprApply(~ X(1) + Y(2 + Y(4)) + N(Y + Y(3)), "Y", print.default)
#> Y(4)
#> Y(2 + Y(4))
#> Y(3)
#> ~X(1) + Y(2 + Y(4)) + N(Y + Y(3))
#> <environment: 0x55cba9740ea8>
# replace X() with log(X, base = n)
exprApply(expression(A() + B() + C()), c("A", "B", "C"), function(expr, base) {
expr[[2]] <- expr[[1]]
expr[[1]] <- as.name("log")
expr$base <- base
expr
}, base = 10)
#> expression(log(A, base = 10) + log(B, base = 10) + log(C, base = 10))
###
# TASK: fit lm with two poly terms, varying the degree from 1 to 3 in each.
# lm(y ~ poly(X1, degree = a) + poly(X2, degree = b), data = Cement)
# for a = {1,2,3} and b = {1,2,3}
# First we create a wrapper function for lm. Within it, use "exprApply" to add
# "degree" argument to all occurences of "poly()" having "X1" or "X2" as the
# first argument. Values for "degree" are taken from arguments "d1" and "d2"
lmpolywrap <- function(formula, d1 = NA, d2 = NA, ...) {
cl <- origCall <- match.call()
cl[[1]] <- as.name("lm")
cl$formula <- exprApply(formula, "poly", function(e, degree, x) {
i <- which(e[[2]] == x)[1]
if(!is.na(i) && !is.na(degree[i])) e$degree <- degree[i]
e
}, degree = c(d1, d2), x = c("X1", "X2"))
cl$d1 <- cl$d2 <- NULL
fit <- eval(cl, parent.frame())
fit$call <- origCall # replace the stored call
fit
}
# global model:
fm <- lmpolywrap(y ~ poly(X1) + poly(X2), data = Cement)
# Use "dredge" with argument "varying" to generate calls of all combinations of
# degrees for poly(X1) and poly(X2). Use "fixed = TRUE" to keep all global model
# terms in all models.
# Since "dredge" expects that global model has all the coefficients the
# submodels can have, which is not the case here, we first generate model calls,
# evaluate them and feed to "model.sel"
modCalls <- dredge(fm,
varying = list(d1 = 1:3, d2 = 1:3),
fixed = TRUE,
evaluate = FALSE
)
#> Fixed terms are "poly(X1)", "poly(X2)" and "(Intercept)"
model.sel(models <- lapply(modCalls, eval))
#> Error in lmpolywrap(formula = y ~ 1 + poly(X1) + poly(X2), data = Cement, d1 = 1L, d2 = 1L): could not find function "lmpolywrap"
# Note: to fit *all* submodels replace "fixed = TRUE" with:
# "subset = (d1==1 || {poly(X1)}) && (d2==1 || {poly(X2)})"
# This is to avoid fitting 3 identical models when the matching "poly()" term is
# absent.