
Mixture model prediction and annotations
Source:R/stat-distrmix-eq.R, R/stat-distrmix-line.R
stat_distrmix_eq.RdFit an univariate mixture of Normals model. stat_distrmix_line() and
stat_distrmix_area() add a layer with prediction lines or areas,
respectively, while stat_distrmix_eq() adds a layer with textual
labels of parameter estimates.
Usage
stat_distrmix_eq(
mapping = NULL,
data = NULL,
geom = "text_npc",
position = "identity",
...,
orientation = NA,
method = "normalmixEM",
method.args = list(),
n.min = 10L * k,
level = 0.95,
k = 2,
free.mean = TRUE,
free.sd = TRUE,
se = FALSE,
fit.seed = NA,
fm.values = TRUE,
components = NULL,
eq.with.lhs = TRUE,
eq.digits = 2,
label.x = "left",
label.y = "top",
hstep = 0,
vstep = NULL,
output.type = NULL,
na.rm = FALSE,
parse = NULL,
show.legend = NA,
inherit.aes = TRUE
)
stat_distrmix_line(
mapping = NULL,
data = NULL,
geom = "line",
position = "identity",
...,
orientation = NA,
method = "normalmixEM",
se = NULL,
quantiles = NA,
fit.seed = NA,
fm.values = FALSE,
n = 500,
fullrange = TRUE,
level = 0.95,
method.args = list(),
k = 2,
free.mean = TRUE,
free.sd = TRUE,
components = "all",
n.min = 10L * k,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE
)
stat_distrmix_area(
mapping = NULL,
data = NULL,
geom = "area",
position = "identity",
...,
orientation = NA,
method = "normalmixEM",
se = NULL,
quantiles = NA,
fit.seed = NA,
fm.values = FALSE,
n = 500,
fullrange = TRUE,
level = 0.95,
method.args = list(),
k = 2,
free.mean = TRUE,
free.sd = TRUE,
components = "sum",
n.min = 10L * k,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE
)Arguments
- mapping
The aesthetic mapping, usually constructed with
aes(). Only needs to be set at the layer level if you are overriding the plot defaults.- data
A layer specific dataset, only needed if you want to override the plot defaults.
- geom
The geometric object to use display the data
- position
The position adjustment to use for overlapping points on this layer.
- ...
other arguments passed on to
layer. This can include aesthetics whose values you want to set, not map. Seelayerfor more details.- orientation
character Either "x" or "y" controlling the aesthetic to which the density model is fit. With the default
orientation = NAthe orientation used is based on the mapping and nearly always correct.- method
function or character If character,
"normalmixEM"or the name of a model fit function are accepted, possibly followed by the fit function's method argument separated by a colon. The function must return a model fit object of class"mixEM".- method.args
named list with additional arguments. Not
dataorweightswhich are always passed through aesthetic mappings.- n.min
integer Minimum number of distinct values in the variable for fitting to the attempted. The default depends on
k.- level
Level of confidence interval to use (0.95 by default).
- k
integer Number of mixture components to fit.
- free.mean, free.sd
logical If TRUE, allow the fitted
meanand/or fittedsdto vary among the component Normal distributions.- se
logical If
TRUEstandard errors for the parameter estimates are returned in addition to the parameter estimates.- fit.seed
RNG seed argument passed to
set.seed(). Defaults toNA, indicating thatset.seed()should not be called.- fm.values
logical Add parameter estimates and their standard errors to the returned values (`FALSE` by default.)
- components
character One of
"all","sum", or"members"select which densities are returned.- eq.with.lhs
If
characterthe string is pasted to the front of the equation label before parsing or alogical(see note).- eq.digits
integer Number of digits after the decimal point to use for parameters in labels. If
Inf, use exponential notation with three decimal places.- label.x, label.y
numericwith range 0..1 "normalized parent coordinates" (npc units) or character if usinggeom_text_npc()orgeom_label_npc(). If usinggeom_text()orgeom_label()numeric in native data units. If too short they will be recycled.- hstep, vstep
numeric in npc units, the horizontal and vertical step used between labels for different groups.
- output.type
character One of "expression", "text", "markdown", "marquee", "latex", "latex.eqn", "latex.deqn" or "numeric".
- na.rm
a logical indicating whether NA values should be stripped before the computation proceeds.
- parse
logical Passed to the geom. If
TRUE, the labels will be parsed into expressions and displayed as described inplotmath. Default isTRUEifoutput.type = "expression"andFALSEotherwise.- show.legend
logical. Should this layer be included in the legends?
NA, the default, includes if any aesthetics are mapped.FALSEnever includes, andTRUEalways includes.- inherit.aes
If
FALSE, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g.borders.- quantiles
numeric The boundaries for quantiles given by P-values in the range 0 to 1, with
NULLbeing equivalent toquantiles = c(0, 1).- n
Number of points at which to predict with the fitted model.
- fullrange
logical Should the fit prediction span the full range of the plot, or just the range of the explanatory variable?
Value
The value returned by stat_distrmix_line() and by
stat_distrmix_area() is a data frame, with n predictions
values or possibly fewer in the case when fullrange = FALSE.
Predictions for each component of the mixture plus for their sum are
returned in long form.
The value returned by stat_distrmix_eq() is a data frame, with one
row of estimates for each group of data in the plot.
Details
stat_distrmix_line() and stat_distrmix_area() are
similar to stat_density but they fit the Normal
distribution to observations. In addition to a single Normal distribution
they can fit a mixture of two or more Normal distributions, using an
approach related to clustering. Defaults related to how fitting is done are
consistent between stat_distrmix_line(), stat_distrmix_area()
and stat_distrmix_eq(). stat_distrmix_eq() can be used to add
matched textual annotations, while stat_distrmix_line() and
stat_distrmix_area() only differ in their default arguments,
including the geom.
If k >= 2 a mixture-of-Normals model is fitted with
normalmixEM(), while if k == 1 a single
Normal distribution is fitted with function fitdistr().
Only for k == 1 the SE values are exact estimates.
In stat_distrmix_line(), predictions are computed to cover >= 0.999 of
the integral in all cases, trimming to the range of the data with
fullrange = FALSE is done as the last step in the computations. This
ensures correct estimates of the cumulated density (CDF) and of
quantiles, whose locations are estimated based on the CDF.
Parameter fit.seed if not NA is used in a call to
set.seed() immediately before calling the model fit function. As the
fitting procedure makes use of the (pseudo-)random number generator (RNG),
convergence can depend on it, and in such cases setting fit.seed to
the same value in stat_distrmix_line() and in
stat_distrmix_eq() can ensure consistency, and more generally,
reproducibility.
The minimum number of observations with distinct values in the data
variable can be set through parameter n.min. The default depends on
k, the number of components in the mix. Model fits with too few
observations are unreliable, thus, using larger values of n.min than
the default is wise. The value of n, instead, sets the number of
predicted values, which affects the smoothness of the plotted curve and
the accuracy with which the location of the quantiles is predicted.
Variables computed by stat_distrmix_line()
Some of the variables can have missing values or depend on
orientation and/or method.
- component
A factor indexing the components and/or their sum
- density
predicted density values
- quant.splits
integer, numbering sequentially the regions separated by the the
quantiles
.
If fm.values = TRUE is passed then columns with diagnosis and
parameters estimates are added, with the same value in each row within a
group:
- n
numericthe number ofxvalues- .size
numericthe number ofdensityvalues- fm.class
characterthe most derived class of the fitted model object- fm.method
characterthe method, as given by theftfield of the fitted model objects
This provides a simple and robust approach to achieve effects like colouring or hiding annotations by group depending on the outcome of model fitting.
Variables computed by stat_distrmix_eq()
Some of the variables depend on the orientation:
- y
the location of text labels
- eq.label
characterstring for equations- n.label
characterstring for number of observations- method.label
characterstring for model fit method- lambda
numericthe estimate of the contribution of the component of the mixture towards the joint density- mu
numericthe estimate of the mean- sigma
numericthe estimate of the standard deviation- component
A factor indexing the components of the mixture and/or their sum
If se = TRUE is passed then columns with standard errors for the
parameter estimates are also returned:
- mu.se
numericthe estimate of the mean- sigma.se
numericthe estimate of the standard deviation
If fm.values = TRUE is passed then columns with diagnosis and
parameters estimates are added:
- n
numericthe number ofxvalues- .size
numericthe number ofdensityvalues- fm.class
characterthe most derived class of the fitted model object- fm.method
characterthe method, as given by theftfield of the fitted model objects
Output types
The formatting of character strings to be displayed in plots are marked as mathematical equations. Depending on the geom used, the mark-up needs to be encoded differently, or in some cases mark-up not applied.
"expression"The labels are encoded as character strings to be parsed into R's plotmath expressions.
"LaTeX", "TeX", "tikz", "latex"The labels are encoded as 'LaTeX' maths equations, without the "fences" for switching in math mode.
"latex.eqn"Same as
"latex"but enclosed in single$, i.e., as in-line maths."latex.deqn"Same as
"latex"but enclosed in double$$, i.e., as display maths."markdown"The labels are encoded as character strings using markdown syntax, with some embedded HTML.
"marquee"The labels are encoded as character strings using markdown syntax, with 'marquee' supported spans.
"text"The labels are plain ASCII character strings.
"numeric"No labels are generated. This value is accepted by the statistics, but not by the label formatting functions.
NULLThe value used depends on the argument passed to
geom.
If geom = "latex" (package 'xdvir') the output type used is
"latex.eqn". If geom = "richtext" (package 'ggtext') or
geom = "textbox" (package 'ggtext') the output type used is
"markdown". If geom = "marquee" (package 'marquee') the output
type used is "marquee". For all other values of geom the default
is "expression". Invalid values as argument trigger an error.
Position of labels
When data are grouped by mapping a factor to an aesthetic, e.g.,
colour, shape and/or linetype the model is fitted
separately to each group, and for each group a whole set of labels is
generated. If the argument passed to label.y is a vector of length
1, this value determines the position of the equation and/or other labels
for the first group, and the positions of the labels for the remaining
groups are generated by adding vspace based on the group number.
If the argument passed to label.y is a vector of length > 1, it is
used unchanged, possibly extended by recycling, ignoring vstep.
If the labels are rotated by 90 degrees then the automatic stepping is
best based on hstep with vstep = 0. Similarly as described
above, if label.x is a vector of length > 1, it is
used unchanged, possibly extended by recycling, ignoring hstep.
When using facets and with a grouping that does not repeat in each panel,
the automatic positioning in most cases will not be the desired one. Manual
positioning using a vector of length > 1 for label.x and/or
label.y is the currently available workaround.
Which variables are available for mapping?
Computed variables and
their names can vary depending on the method used to fit a model or
the output.type in use. They can also depend for a given
method on other arguments passed when fitting a model or extracting
estimates and other computed values. In many cases, when values are not
available, the variables are filled with NA values.
In the statistics returning formatted strings for use as annotations, a
message is issued by default in interactive R sessions, listing the short
names for available formatted labels as recognized by functions
use_label() and f_use_label(), except when
output.type = "numeric" is passed, in which case the names of all
variables accessible by after_stat() within a call to aes()
are listed. This default ("nicknames") can be changed by setting R
option "ggpmisc.stat.vars.message" to one of "names",
"colnames" or "none".
In the statistics that plot a prediction or more generally mainly return
numeric variables, a message is issued by default in interactive R
sessions, listing the names of all variables accessible by
after_stat() within a call to aes() with at least some
non-missing values. This default ("colnames") can be changed by
setting R option "ggpmisc.stat.vars.message" to "none".
To explore the whole returned data frame for a given input we suggest the
use of geom_debug().
See also
For the underlying computations see for mixes of two or more Normal
distributions normalmixEM() and for a single Normal
distribution fitdistr().
statistics from 'ggpmisc' for model fit annotations:
stat_poly_eq(), stat_quant_eq(),
stat_ma_eq() and stat_distrmix_eq(), and for
model fit predictions: stat_poly_line(),
stat_quant_line(), stat_quant_band(),
stat_ma_line() and stat_distrmix_line().
Aesthetics
stat_distrmix_eq() understands the following aesthetics. Required aesthetics are displayed in bold and defaults are displayed for optional aesthetics:
| • | x or y | |
| • | group | → after_stat(component) |
| • | hjust | → "inward" |
| • | label | → after_stat(eq.label) |
| • | npcx | → after_stat(npcx) |
| • | npcy | → after_stat(npcy) |
| • | vjust | → "inward" |
stat_distrmix_line() understands the following aesthetics. Required aesthetics are displayed in bold and defaults are displayed for optional aesthetics:
| • | x or y | |
| • | group | → after_stat(component) |
| • | weight | → NULL |
Learn more about setting these aesthetics in vignette("ggplot2-specs").
Examples
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line() +
stat_distrmix_eq()
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_area() +
stat_distrmix_eq()
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_area(aes(fill = after_stat(quant.splits != 2)),
quantiles = c(0.025, 0.975),
show.legend = FALSE)
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "sum") +
stat_distrmix_eq(use_label("eq", "n", "method"))
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "sum") +
stat_distrmix_eq(geom = "label_npc")
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "sum") +
stat_distrmix_eq(geom = "text", label.x = "center", label.y = "bottom")
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "sum") +
stat_distrmix_eq(geom = "text", hjust = "inward")
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "members") +
stat_distrmix_eq(components = "members")
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(components = "members") +
stat_distrmix_eq(components = "members", se = TRUE)
ggplot(faithful, aes(y = waiting)) +
stat_distrmix_line(components = "sum") +
stat_distrmix_eq(label.x = "right")
ggplot(faithful, aes(x = waiting)) +
geom_histogram(aes(y = after_stat(density)), bins = 20) +
stat_distrmix_line(aes(colour = after_stat(component),
fill = after_stat(component)),
geom = "area", linewidth = 1, alpha = 0.25) +
stat_distrmix_eq(aes(colour = after_stat(component)))
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(aes(colour = after_stat(component),
fill = after_stat(component)),
geom = "area", linewidth = 1, alpha = 0.25,
components = "members") +
stat_distrmix_eq(aes(colour = after_stat(component)),
components = "members")
ggplot(faithful, aes(x = waiting)) +
stat_distrmix_line(geom = "area", linewidth = 1, alpha = 0.25,
colour = "black", outline.type = "upper",
components = "sum", se = FALSE) +
stat_distrmix_eq(components = "sum")
# special case of no mixture
ggplot(subset(faithful, waiting > 66), aes(x = waiting)) +
stat_distrmix_line(k = 1) +
stat_distrmix_eq(k = 1)
#> With k = 1 one Normal distribution is fitted. Irrelevant parameters ignored!
#> With k = 1 one Normal distribution is fitted. Irrelevant parameters ignored!
ggplot(subset(faithful, waiting > 66), aes(x = waiting)) +
stat_distrmix_line(k = 1) +
stat_distrmix_eq(k = 1, se = TRUE)
#> With k = 1 one Normal distribution is fitted. Irrelevant parameters ignored!
#> With k = 1 one Normal distribution is fitted. Irrelevant parameters ignored!