Create a multimodel object
multimodel.Rd
A multimodel combines several model
s with identical response in one object.
There are two ways to create a multimodel:
multimodel(x, ...)
takes an object of class “model” or a fitted model as its inputx
and generates a number of variations of this model, with one or several parameters varying according to the specification in “...”.c.model(...)
andc.multimodel(...)
take a number ofmodel
s ormultimodel
s as their “...” arguments and combine them in an object of class “multimodel”.
Usage
multimodel(x, ...)
# S3 method for model
multimodel(
x,
...,
prefix = label(x),
expand = TRUE,
max_n_model = getOption("expand_max_model"),
param = TRUE,
simplify = TRUE
)
# S3 method for default
multimodel(
x,
...,
prefix = "model",
expand = TRUE,
param = TRUE,
simplify = TRUE
)
# S3 method for multimodel
multimodel(x, ...)
# S3 method for multimodel
print(
x,
what = c("class", "formula", "data", "weights", "call", "cv_info"),
abbreviate = TRUE,
n = getOption("print_max_model"),
param = TRUE,
width = getOption("width"),
...
)
# S3 method for model
c(..., param = TRUE, simplify = TRUE)
# S3 method for multimodel
c(..., param = TRUE, simplify = TRUE)
Arguments
- x
An object of class “model” or a fitted model.
- ...
In
multimodel()
: named parameters to be expanded; inc.
(multi
)model
: one or several arguments of class “model” or “multimodel”.- prefix
Prefix to use for the model
label
.- expand
Logical: Expand the “...” arguments (default) or join them element-wise? If
expand=TRUE
, the vectors in “...” will be expanded, the number of models will equal the product of the lengths of the “...” arguments; otherwise, all “...” arguments must have equal lengths, and the number of models will be equal to their common length.- max_n_model
Maximal number of models that will be included. If the number of specified models is greater than
max_n_model
, a subset will be selected at random.- param
Logical: Keep or print parameter table?
- simplify
Logical: Simplify a
multimodel
comprising only one model to amodel
?- what
Which elements of the multimodel should be printed? See
print.model
.- abbreviate
Logical. If
TRUE
(the default), long formulas and calls are printed in abbreviated mode, such that they usually fit on 4 or fewer output lines; otherwise they are printed entirely, no matter how long they are.- n
Integer: Model details are printed for first
n
models.- width
Integer: Width of printed output.
Value
multimodel()
and c.
(multi
)model()
both return an object of class “multimodel”, this is
a list
with the following elements:
models: A list of the
model
objects.param: The table of the parameter values resulting from
multimodel()
. Only included if there are any varying parameters and ifparam = TRUE
Details
multimodel()
is a (S3-)generic function.
The core method is multimodel.model()
, other methods are essentially wrappers to the core method and are described in the section “Methods” below.
The vectors in “...” are expanded or joined, according to the argument expand
.
Extraction of values for the single calls is done with “[[
” rather than “[
”.
multimodel()
executes update.model()
repeatedly, such that the helper functions absent()
,
unchanged()
and null()
can be used in a call to multimodel()
exactly as within update.model()
.
If formula
is one of the arguments in the “...” and some formula has a dot, it will be used to update the original model formula.
Enclose a formula in I()
in order to replace the original formula instead.
See the example below and update.model
.
The output of multimodel(...)
by default includes a parameter table as its element param
, containing the values
of the parameters specified in the “...”.
This is a data.frame
having an additional class “param_table”.
c.
(multi
)model
: A call to c(...)
can include both “model” and “multimodel” objects
(but no fitted models) in its “...”.
Using models()
instead of these c
-methods is more flexible in that it also accepts fitted models.
“model”s specified as named arguments in the call will have their argument name taken as their label
.
Argument names for multimodels are ignored -- the label
s already present in the multimodel will be used instead.
Duplicate labels in the output will be adjusted using make.unique()
.
Methods
multimodel.model()
is described in the “Details” section.The default method expects a fitted model as its
x
and executesx %>% model %>% multimodel(...)
.multimodel.multimodel()
returns its inputx
unchanged.
See also
label
, extract_model
, subset
, sort_models
,
update.model
, expand_formula
.
models()
is a more general version of c.
(multi
)model
also accepting fitted models.
Examples
m1 <- model(lm(Sepal.Length ~ 1 , iris), label = "intercept")
m2 <- model(lm(Sepal.Length ~ . , iris), label = "linear")
m3 <- model(lm(Sepal.Length ~ .^2 , iris), label = "order2") # without Species on rhs
# Combine models with c(...)
mm1 <- c(m1, m2, m3)
mm1
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘intercept’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘linear’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ ., data = data)
#>
#> ‘order2’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
# Specify elements to print:
print(mm1, what = c("class", "data"))
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘intercept’:
#> model class: lm
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#>
#> ‘linear’:
#> model class: lm
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#>
#> ‘order2’:
#> model class: lm
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
print(mm1, what = TRUE)
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘intercept’:
#> label: intercept
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> response_type: continuous
#> response: Sepal.Length
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#> predict_function: function (object, ...)
#> fit: Object of class ‘lm’
#>
#> ‘linear’:
#> label: linear
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length +
#> Petal.Width + Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> response_type: continuous
#> response: Sepal.Length
#> call: lm(formula = Sepal.Length ~ ., data = data)
#> predict_function: function (object, ...)
#> fit: Object of class ‘lm’
#>
#> ‘order2’:
#> label: order2
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length +
#> Petal.Width + Species + Sepal.Width:Petal.Length +
#> Sepal.Width:Petal.Width + Sepal.Width:Species +
#> ... [formula cut off - 10 terms on rhs]
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> response_type: continuous
#> response: Sepal.Length
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
#> predict_function: function (object, ...)
#> fit: Object of class ‘lm’
# Expand a model with multimodel(): random forests with different max.depth:
if (require(ranger)){
mod_ranger <- model(ranger(Sepal.Length ~ ., iris), label = "ranger")
multimodel(mod_ranger, max.depth = 1:10)
}
#> --- A “multimodel” object containing 10 models ---
#>
#> ‘ranger1’:
#> model class: ranger
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: ranger(formula = Sepal.Length ~ ., data = data,
#> max.depth = 1L)
#>
#> ‘ranger2’:
#> model class: ranger
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: ranger(formula = Sepal.Length ~ ., data = data,
#> max.depth = 2L)
#>
#> ‘ranger3’:
#> model class: ranger
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: ranger(formula = Sepal.Length ~ ., data = data,
#> max.depth = 3L)
#>
#> and 7 models more, labelled:
#> ‘ranger4’, ‘ranger5’, ‘ranger6’, ‘ranger7’, ‘ranger8’,
#> ‘ranger9’, ‘ranger10’
#>
#>
#> Parameter table:
#> max.depth
#> ranger1 1
#> ranger2 2
#> ranger3 3
#> ... 7 rows omitted (nrow=10)
#' # Expand a model with multimodel(...)
# Joining models with three formulas may not give the expected result:
mm2 <- multimodel(m1, formula = list(Sepal.Length ~ 1, Sepal.Length ~ ., Sepal.Length ~ .^2))
mm2
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘intercept1’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘intercept2’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘intercept3’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> Parameter table:
#> formula
#> intercept1 Sepal.Length ~ 1
#> intercept2 Sepal.Length ~ .
#> intercept3 Sepal.Length ~ .^2
# The reason is that the formulas in the call above are used to *update* the existing one.
# To *replace* the formula, use `I()` as in the call below:
mm3 <- multimodel(m1, formula = list(Sepal.Length ~ 1, I(Sepal.Length ~ .), I(Sepal.Length ~ .^2)))
mm3
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘intercept1’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘intercept2’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ ., data = data)
#>
#> ‘intercept3’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
#>
#> Parameter table:
#> formula
#> intercept1 Sepal.Length ~ 1
#> intercept2 Sepal.Length ~ .
#> intercept3 Sepal.Length ~ .^2
# Also note the difference in the printed outputs of mm1 and mm2:
# The parameter table only contains parameters that were passed as '...' in multimodel().
# Three ways to attribute labels to models:
# 1) Use named arguments in c.model():
c(constant = m1, linear = m2, order2 = m3)
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘constant’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘linear’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ ., data = data)
#>
#> ‘order2’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
# 2) replacement function label<-
mm1_lbls <- mm1
label(mm1_lbls) <- c("m1", "m2", "m3")
mm1_lbls
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘m1’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘m2’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ ., data = data)
#>
#> ‘m3’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
# 3) set_labels()
set_label(mm1, c("m1", "m2", "m3"))
#> --- A “multimodel” object containing 3 models ---
#>
#> ‘m1’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘m2’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ ., data = data)
#>
#> ‘m3’:
#> model class: lm
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ .^2, data = data)
# Combine mm1 and mm3:
print(c(mm1, mm3), what = "formula", n = 6)
#> --- A “multimodel” object containing 6 models ---
#>
#> ‘intercept’:
#> formula: Sepal.Length ~ 1
#>
#> ‘linear’:
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#>
#> ‘order2’:
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#>
#> ‘intercept1’:
#> formula: Sepal.Length ~ 1
#>
#> ‘intercept2’:
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species
#>
#> ‘intercept3’:
#> formula: Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width +
#> Species + Sepal.Width:Petal.Length + Sepal.Width:Petal.Width +
#> Sepal.Width:Species + Petal.Length:Petal.Width +
#> Petal.Length:Species + Petal.Width:Species
#>
#> Parameter table:
#> formula
#> intercept <unknown>
#> linear <unknown>
#> order2 <unknown>
#> intercept1 Sepal.Length ~ 1
#> intercept2 Sepal.Length ~ .
#> intercept3 Sepal.Length ~ .^2
# Unweighted and weighted model:
w <- runif(150)
mm3 <- multimodel(m1, weights = list(absent(), w))
label(mm3) <- c("unweighted", "weighted")
mm3
#> --- A “multimodel” object containing 2 models ---
#>
#> ‘unweighted’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> call: lm(formula = Sepal.Length ~ 1, data = data)
#>
#> ‘weighted’:
#> model class: lm
#> formula: Sepal.Length ~ 1
#> data: data.frame [150 x 5],
#> input as: ‘data = iris’
#> weights: numeric [150], input as: ‘weights = w’
#> call: lm(formula = Sepal.Length ~ 1, data = data, weights = weights)
#>
#> Parameter table:
#> weights
#> unweighted <absent>
#> weighted <num>[150]