Title: Machinery for Processing Random Effect Formulas
Version: 0.4.0
Description: Takes formulas including random-effects components (formatted as in 'lme4', 'glmmTMB', etc.) and processes them. Includes various helper functions.
URL: https://github.com/bbolker/reformulas
License: GPL-3
Encoding: UTF-8
Imports: stats, methods, Matrix, Rdpack
RdMacros: Rdpack
Suggests: lme4, tinytest
RoxygenNote: 7.3.2
NeedsCompilation: no
Packaged: 2024-11-02 16:40:00 UTC; bolker
Author: Ben Bolker ORCID iD [aut, cre]
Maintainer: Ben Bolker <bolker@mcmaster.ca>
Repository: CRAN
Date/Publication: 2024-11-03 05:30:11 UTC

Detect whether there are any 'specials' in a formula term

Description

Detect whether there are any 'specials' in a formula term

Usage

anySpecial(term, specials = findReTrmClasses(), fast = FALSE)

Arguments

term

formula term

specials

values to detect

fast

(logical) use quick (syntactic) test for presence of specials?

Value

logical value

Examples

## should only detect s as the head of a function, s(...)
anySpecial(~diag(1))
anySpecial(~diag)
anySpecial(~diag[[1]])
anySpecial(~diag[1])
anySpecial(~s)
anySpecial(~s(hello+goodbye,whatever))

expand double-bar RE notation by splitting

Description

Modeled after lme4:::expandSlash, by Doug Bates. However, all formula operators that apply to factors (*, /, +) are applicable: the results are expanded into a list of independent (additive) random effect terms

Usage

expandDoubleVert(term)

RHSForm(formula) <- value

sumTerms(termList)

reOnly(f, response = FALSE, bracket = TRUE, doublevert_split = TRUE)

makeOp(x, y, op = NULL)

addForm0(f1, f2)

addForm(...)

expandAllGrpVar(bb)

findbars_x(
  term,
  debug = FALSE,
  specials = character(0),
  default.special = "us",
  target = "|",
  expand_doublevert_method = c("diag_special", "split")
)

findbars(term)

inForm(form, value)

extractForm(term, value)

dropHead(term, value)

drop.special(x, value = quote(offset), preserve = NULL)

replaceForm(term, target, repl)

Arguments

term

expression/formula

formula

a formula object

value

term to remove from formula

termList

a list of formula terms

f

a formula

response

include response variable?

bracket

bracket-protect terms?

doublevert_split

(logical) TRUE for lme4 back-compatibility; FALSE to make double vertical bars into diag() eterms

x

formula

y

a formula term (or an operator)

op

an operator

f1

formula #1

f2

formula #2

...

arguments to pass through to addForm0

bb

a list of naked grouping variables, i.e. 1 | f

debug

(logical) debug?

specials

list of special terms

default.special

character: special to use for parenthesized terms - i.e. random effects terms with unspecified structure

expand_doublevert_method

method for handling || operator: split into separate terms or replace by diag? Inherited from previous call where it was specified.

  1. atom (not a call or an expression): NULL

  2. special, i.e. foo(...) where "foo" is in specials: return term

  3. parenthesized term: if the head of the head is | (i.e. it is of the form (xx|gg), then convert it to the default special type; we won't allow pathological cases like ((xx|gg)) ... can we detect them?

preserve

(integer) retain the specified occurrence of "value"

Value

a list of expressions

Examples

f <- y ~ 1 + x
RHSForm(f) <- quote(2+x^2)
print(f)
reOnly(~ 1 + x + y + (1|f) + (1|g))
addForm0(y~x,~1)
addForm0(~x,~y)
ff <- findbars_x(y~1+(x|f/g))
expandAllGrpVar(ff)
expandAllGrpVar(quote(1|(f/g)/h))
expandAllGrpVar(quote(1|f/g/h))
expandAllGrpVar(quote(1|f*g))
expandAllGrpVar(quote(1|f+g))
expandAllGrpVar(quote(a+b|f+g+h*i))
expandAllGrpVar(quote(s(log(d), k = 4)))
expandAllGrpVar(quote(s(log(d+1))))
splitForm(quote(us(x,n=2)))
findbars_x(~ 1 + (x + y || g), expand_doublevert_method = "diag_special")
findbars_x(~ 1 + (x + y || g), expand_doublevert_method = "split")
findbars_x(~ 1 + (1 | f) + (1 | g))
findbars_x(~ 1 + (1 | f) + (1 | g))
findbars_x(~ 1 + (1|h) + (x + y || g), expand_doublevert_method = "split")
findbars_x(~ 1 + (1|Subject))
findbars_x(~ (1||Subject))
findbars_x(~ (1|Subject))
findbars_x(~ (1|Subject), default.special = NULL)
findbars_x(~ 1 + x)
findbars_x(~ s(x, bs = "tp"))
findbars_x(y ~ a + log(b) + s(x, bs = "tp") + s(y, bs = "gp"),
   target = "s", default.special = NULL)
inForm(z~.,quote(.))
inForm(z~y,quote(.))
inForm(z~a+b+c,quote(c))
inForm(z~a+b+(d+e),quote(c))
f <- ~ a + offset(x)
f2 <- z ~ a
inForm(f,quote(offset))
inForm(f2,quote(offset))
extractForm(~a+offset(b),quote(offset))
extractForm(~c,quote(offset))
extractForm(~a+offset(b)+offset(c),quote(offset))
extractForm(~offset(x),quote(offset))
dropHead(~a+offset(b),quote(offset))
dropHead(~a+poly(x+z,3)+offset(b),quote(offset))
drop.special(x~a + b+ offset(z))
replaceForm(quote(a(b+x*c(y,z))),quote(y),quote(R))
ss <- ~(1 | cask:batch) + (1 | batch)
replaceForm(ss,quote(cask:batch),quote(batch:cask))
replaceForm(ss, quote(`:`), quote(`%:%`))

Expand terms with '||' notation into separate '|' terms

Description

From the right hand side of a formula for a mixed-effects model, expand terms with the double vertical bar operator into separate, independent random effect terms.

Usage

expandDoubleVerts(term)

Arguments

term

a mixed-model formula

Value

the modified term

See Also

formula, model.frame, model.matrix.

Other utilities: mkReTrms(), nobars(), subbars()


apply

Description

apply

Usage

expandGrpVar(f)

Arguments

f

a language object (an atom of a formula) expandGrpVar(quote(x*y)) expandGrpVar(quote(x/y))


list of specials – taken from enum.R

Description

list of specials – taken from enum.R

Usage

findReTrmClasses()

Is f1 nested within f2?

Description

Does every level of f1 occur in conjunction with exactly one level of f2? The function is based on converting a triplet sparse matrix to a compressed column-oriented form in which the nesting can be quickly evaluated.

Usage

isNested(f1, f2)

Arguments

f1

factor 1

f2

factor 2

Value

TRUE if factor 1 is nested within factor 2

Examples

if (requireNamespace("lme4")) {
   data("Pastes", package = "lme4")
   with(Pastes, isNested(cask, batch))   ## => FALSE
   with(Pastes, isNested(sample, batch))  ## => TRUE
}

Create list of structures needed for models with random effects

Description

From the result of findbars applied to a model formula and and the evaluation frame, create the model matrix, etc. associated with random-effects terms. See the description of the returned value for a detailed list.

Usage

mkReTrms(
  bars,
  fr,
  drop.unused.levels = TRUE,
  reorder.terms = TRUE,
  reorder.vars = FALSE,
  calc.lambdat = TRUE
)

Arguments

bars

a list of parsed random-effects terms

fr

a model frame in which to evaluate these terms

drop.unused.levels

(logical) drop unused factor levels?

reorder.terms

arrange random effects terms in decreasing order of number of groups (factor levels)?

reorder.vars

arrange columns of individual random effects terms in alphabetical order?

calc.lambdat

(logical) compute Lambdat and Lind components? (At present these components are needed for lme4 machinery but not for glmmTMB, and may be large in some cases; see Bates et al. 2015

Value

a list with components

Zt

transpose of the sparse model matrix for the random effects

Ztlist

list of components of the transpose of the random-effects model matrix, separated by random-effects term

Lambdat

transpose of the sparse relative covariance factor

Lind

an integer vector of indices determining the mapping of the elements of the theta to the "x" slot of Lambdat

theta

initial values of the covariance parameters

lower

lower bounds on the covariance parameters

flist

list of grouping factors used in the random-effects terms

cnms

a list of column names of the random effects according to the grouping factors

Gp

a vector indexing the association of elements of the conditional mode vector with random-effect terms; if nb is the vector of numbers of conditional modes per term (i.e. number of groups times number of effects per group), Gp is c(0,cumsum(nb)) (and conversely nb is diff(Gp))

nl

names of the terms (in the same order as Zt, i.e. reflecting the reorder.terms argument)

References

Bates D, Mächler M, Bolker B, Walker S (2015). “Fitting Linear Mixed-Effects Models Using lme4.” Journal of Statistical Software, 67(1), 1–48. doi:10.18637/jss.v067.i01.)

See Also

Other utilities: expandDoubleVerts(), nobars(), subbars()


Drop 'specials' from a formula

Description

Drop 'specials' from a formula

Usage

no_specials(term, specials = c("|", "||", "s"))

Arguments

term

a term or formula or list thereof

specials

function types to drop

Value

a call or language object (or list) with specials removed

Examples

no_specials(findbars_x(~ 1 + s(x) + (f|g) + diag(x|y)))
no_specials(~us(f|g))

Omit terms separated by vertical bars in a formula

Description

Remove the random-effects terms from a mixed-effects formula, thereby producing the fixed-effects formula.

Usage

nobars(term)

nobars_(term)

Arguments

term

the right-hand side of a mixed-model formula

Value

the fixed-effects part of the formula

Note

This function is called recursively on individual terms in the model, which is why the argument is called term and not a name like form, indicating a formula.

See Also

formula, model.frame, model.matrix.

Other utilities: expandDoubleVerts(), mkReTrms(), subbars()

Examples

nobars(Reaction ~ Days + (Days|Subject)) ## => Reaction ~ Days

extract right-hand side of a formula

Description

extract right-hand side of a formula

Usage

RHSForm(form, as.form = FALSE)

Arguments

form

a formula object

as.form

(logical) return a formula (TRUE) or as a call/symbolic object (FALSE) ?

Value

a language object

Examples

RHSForm(y ~ x + (1|g))

Split formula containing special random effect terms

Description

Parse a formula into fixed formula and random effect terms, treating 'special' terms (of the form foo(x|g[,m])) appropriately

Usage

splitForm(
  formula,
  defaultTerm = "us",
  allowFixedOnly = TRUE,
  allowNoSpecials = TRUE,
  debug = FALSE,
  specials = findReTrmClasses()
)

noSpecials(term, delete = TRUE, debug = FALSE, specials = findReTrmClasses())

Arguments

formula

a formula containing special random effect terms

defaultTerm

default type for non-special RE terms

allowFixedOnly

(logical) are formulas with no RE terms OK?

allowNoSpecials

(logical) are formulas with only standard RE terms OK?

debug

debugging mode (print stuff)?

term

language object

Details

Taken from Steve Walker's lme4ord, ultimately from the flexLambda branch of lme4 https://github.com/stevencarlislewalker/lme4ord/blob/master/R/formulaParsing.R. Mostly for internal use.

Value

a list containing elements fixedFormula; reTrmFormulas list of x | g formulas for each term; reTrmAddArgs list of function+additional arguments, i.e. list() (non-special), foo() (no additional arguments), foo(addArgs) (additional arguments); reTrmClasses (vector of special functions/classes, as character)

Author(s)

Steve Walker

Examples

splitForm(~x+y)                     ## no specials or RE
splitForm(~x+y+(f|g))               ## no specials
splitForm(~x+y+diag(f|g))           ## one special
splitForm(~x+y+(diag(f|g)))         ## 'hidden' special
splitForm(~x+y+(f|g)+cs(1|g))       ## combination
splitForm(~x+y+(1|f/g))             ## 'slash'; term
splitForm(~x+y+(1|f/g/h))             ## 'slash'; term
splitForm(~x+y+(1|(f/g)/h))             ## 'slash'; term
splitForm(~x+y+(f|g)+cs(1|g)+cs(a|b,stuff))  ## complex special
splitForm(~(((x+y))))               ## lots of parentheses
splitForm(~1+rr(f|g,n=2))
splitForm(~1+s(x, bs = "tp"))

noSpecials(y~1+us(1|f))
noSpecials(y~1+us(1|f),delete=FALSE)
noSpecials(y~us(1|f))
noSpecials(y~us(1|f), delete=FALSE)
noSpecials(y~us(1|f), debug=TRUE)
noSpecials(y~us+1)  ## should *not* delete unless head of a function
noSpecials(~us(1|f)+1)   ## should work on a one-sided formula!
noSpecials(~s(stuff) + a + b, specials = "s")
noSpecials(cbind(b1, 20-b1) ~ s(x, bs = "tp"))

Substitute safe chars (+) for specials (for use in model.frame) (Generalized from lme4's subbars function.)

Description

Substitute safe chars (+) for specials (for use in model.frame) (Generalized from lme4's subbars function.)

Usage

sub_specials(
  term,
  specials = c("|", "||", "s"),
  keep_args = c(2L, 2L, NA_integer_)
)

Arguments

term

formula or term in a formula

specials

names of specials to process

keep_args

number of arguments to retain (matching specials)

Value

a term or formula with specials replaced by + (and extra arguments dropped)

Examples

sub_specials( ~ s(a, k=4))
sub_specials( ~ (1|x) + (a + b || y) + s(a, k=4))
sub_specials(Reaction ~ s(Days) + (1 + Subject))
sub_specials(~ s(cos((y^2*3)/2), bs = "tp"))

"Substitute bars"

Description

Substitute the '+' function for the '|' and '||' function in a mixed-model formula. This provides a formula suitable for the current model.frame function.

Usage

subbars(term)

Arguments

term

a mixed-model formula

Value

the formula with all | and || operators replaced by +

Note

This function is called recursively on individual terms in the model, which is why the argument is called term and not a name like form, indicating a formula.

See Also

formula, model.frame, model.matrix.

Other utilities: expandDoubleVerts(), mkReTrms(), nobars()

Examples

subbars(Reaction ~ Days + (Days|Subject)) ## => Reaction ~ Days + (Days + Subject)