exprApply.RdApply 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.