Computation of model frames, model matrices, and model responses for
extended formulas of class Formula
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14  ## S3 method for class 'Formula'
model.frame(formula, data = NULL, ...,
lhs = NULL, rhs = NULL, dot = "separate")
## S3 method for class 'Formula'
model.matrix(object, data = environment(object), ...,
lhs = NULL, rhs = 1, dot = "separate")
## S3 method for class 'Formula'
terms(x, ...,
lhs = NULL, rhs = NULL, dot = "separate")
model.part(object, ...)
## S3 method for class 'Formula'
model.part(object, data, lhs = 0, rhs = 0,
drop = FALSE, terms = FALSE, dot = NULL, ...)

formula, object, x 
an object of class 
data 
a data.frame, list or environment containing the variables in

lhs, rhs 
indexes specifying which elements of the left and
righthand side, respectively, should be employed. 
dot 
character specifying how to process formula parts with a dot
( 
drop 
logical. Should the 
terms 
logical. Should the 
... 
further arguments passed to the respective

All three model computations leverage the corresponding standard methods. Additionally, they allow specification of the part(s) of the left and righthand side (LHS and RHS) that should be included in the computation.
The idea underlying all three model computations is to extract a suitable
formula
from the more general Formula
and then calling
the standard model.frame
, model.matrix
,
and terms
methods.
More specifically, if the Formula
has multiple parts on the RHS,
they are collapsed, essentially replacing 
by +
. If there
is only a single response on the LHS, then it is kept on the LHS.
Otherwise all parts of the formula are collapsed on the RHS (because formula
objects can not have multiple responses). Hence, for multiresponse Formula
objects, the (nongeneric) model.response
does
not give the correct results. To avoid confusion a new generic model.part
with suitable formula
method is provided which can always
be used instead of model.response
. Note, however, that it has a different
syntax: It requires the Formula
object in addition to the readily
processed model.frame
supplied in data
(and optionally the lhs
). Also, it returns either a data.frame
with
multiple columns or a single column (dropping the data.frame
property)
depending on whether multiple responses are employed or not.
If the the formula contains one or more dots (.
), some care has to be
taken to process these correctly, especially if the LHS contains transformartions
(such as log
, sqrt
, cbind
, Surv
, etc.). Calling the
terms
method with the original data (untransformed, if any) resolves
all dots (by default separately for each part, otherwise sequentially) and also
includes the original and updated formula as part of the terms. When calling
model.part
either the original untransformed data should be provided
along with a dot
specification or the transformed model.frame
from the same formula without another dot
specification (in which
case the dot
is inferred from the terms
of the model.frame
).
Zeileis A, Croissant Y (2010). Extended Model Formulas in R: Multiple Parts and Multiple Responses. Journal of Statistical Software, 34(1), 1–13. http://www.jstatsoft.org/v34/i01/.
Formula
, model.frame
,
model.matrix
, terms
,
model.response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94  ## artificial example data
set.seed(1090)
dat < as.data.frame(matrix(round(runif(21), digits = 2), ncol = 7))
colnames(dat) < c("y1", "y2", "y3", "x1", "x2", "x3", "x4")
for(i in c(2, 6:7)) dat[[i]] < factor(dat[[i]] > 0.5, labels = c("a", "b"))
dat$y2[1] < NA
dat
######################################
## single response and twopart RHS ##
######################################
## single response with twopart RHS
F1 < Formula(log(y1) ~ x1 + x2  I(x1^2))
length(F1)
## set up model frame
mf1 < model.frame(F1, data = dat)
mf1
## extract single response
model.part(F1, data = mf1, lhs = 1, drop = TRUE)
model.response(mf1)
## model.response() works as usual
## extract model matrices
model.matrix(F1, data = mf1, rhs = 1)
model.matrix(F1, data = mf1, rhs = 2)
#########################################
## multiple responses and multiple RHS ##
#########################################
## set up Formula
F2 < Formula(y1 + y2  log(y3) ~ x1 + I(x2^2)  0 + log(x1)  x3 / x4)
length(F2)
## set up full model frame
mf2 < model.frame(F2, data = dat)
mf2
## extract responses
model.part(F2, data = mf2, lhs = 1)
model.part(F2, data = mf2, lhs = 2)
## model.response(mf2) does not give correct results!
## extract model matrices
model.matrix(F2, data = mf2, rhs = 1)
model.matrix(F2, data = mf2, rhs = 2)
model.matrix(F2, data = mf2, rhs = 3)
#######################
## Formulas with '.' ##
#######################
## set up Formula with a single '.'
F3 < Formula(y1  y2 ~ .)
mf3 < model.frame(F3, data = dat)
## without y1 or y2
model.matrix(F3, data = mf3)
## without y1 but with y2
model.matrix(F3, data = mf3, lhs = 1)
## without y2 but with y1
model.matrix(F3, data = mf3, lhs = 2)
## set up Formula with multiple '.'
F3 < Formula(y1  y2  log(y3) ~ .  x3  x4  .)
## process both '.' separately (default)
mf3 < model.frame(F3, data = dat, dot = "separate")
## only x1x2
model.part(F3, data = mf3, rhs = 1)
## all x1x4
model.part(F3, data = mf3, rhs = 2)
## process the '.' sequentially, i.e., the second RHS conditional on the first
mf3 < model.frame(F3, data = dat, dot = "sequential")
## only x1x2
model.part(F3, data = mf3, rhs = 1)
## only x3x4
model.part(F3, data = mf3, rhs = 2)
##############################
## Process multiple offsets ##
##############################
## set up Formula
F4 < Formula(y1 ~ x3 + offset(x1)  x4 + offset(log(x2)))
mf4 < model.frame(F4, data = dat)
## model.part can be applied as above and includes offset!
model.part(F4, data = mf4, rhs = 1)
## additionally, the corresponding corresponding terms can be included
model.part(F4, data = mf4, rhs = 1, terms = TRUE)
## hence model.offset() can be applied to extract offsets
model.offset(model.part(F4, data = mf4, rhs = 1, terms = TRUE))
model.offset(model.part(F4, data = mf4, rhs = 2, terms = TRUE))

Questions? Problems? Suggestions? Tweet to @rdrrHQ or email at ian@mutexlabs.com.
All documentation is copyright its authors; we didn't write any of that.