I'm trying to write a function in R that accepts a formula such as the following:
y ~ 1 + sex + age + (1 | school) + (1 | school:section)
Is there an easy way to extract the various components of this formula for use in my function? For example, I would like to be able to get the left hand side, each of the variables, the random effects variables and how they are nested, etc.
Is there an easier way to do this than walking the formula parse tree?
If you want a solution which doesn't require regex, I suggest you consider terms
.
form <- y ~ 1 + sex + age + (1 | school) + (1 | school:section)
terms(form)
## y ~ 1 + sex + age + (1 | school) + (1 | school:section)
## attr(,"variables")
## list(y, sex, age, 1 | school, 1 | school:section)
## attr(,"factors")
## sex age 1 | school 1 | school:section
## y 0 0 0 0
## sex 1 0 0 0
## age 0 1 0 0
## 1 | school 0 0 1 0
## 1 | school:section 0 0 0 1
## attr(,"term.labels")
## [1] "sex" "age" "1 | school" "1 | school:section"
## attr(,"order")
## [1] 1 1 1 1
## attr(,"intercept")
## [1] 1
## attr(,"response")
## [1] 1
## attr(,".Environment")
## <environment: R_GlobalEnv>
Furthermore you can extract attributes from it using attributes
:
attributes(terms(form))$term.labels
## [1] "sex" "age" "1 | school" "1 | school:section"
To expand on @Ben Bolker's suggestion:
f1 <- formula(y ~ 1 + sex + age + (1 | school) + (1 | school:section))
The left hand side (assuming one variable on left):
all.vars(terms(f1))[1] # character
The variables:
all.vars(delete.response(terms(f1))) # character
The random effects:
lme4:::findbars(f1) # returns list of language items
There's also the formula.tools
package for this, although it doesn't have methods specifically for mixed-effects models:
library(formula.tools)
lhs(f1)
r1 <- rhs.vars(f1) # gives fixed and random effects as character
r1[grepl("\\|", r1)] # character vector of random effects
Maybe something like:
x <- as.formula("y ~ 1 + sex + age + (1 | school) + (1 | school:section)")
x[[2]]
x[[3]][2]
You could use strsplit
too as in:
strsplit(as.character(x[[3]][2]), "\\+")
> form <- y ~ 1 + sex + age + (1 | school) + (1 | school:section)
> form[1]
`~`()
> form[2]
y()
> form[3]
1 + sex + age + (1 | school) + (1 | school:section)()
So basically you should be addressing the LHS and the RHS as list elements. To split up the RHS you could use TylerRinker's answer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.