Next, one example of how to remove the left hand side (lhs).
@@ -2218,7 +2219,7 @@ggplot(my.data, aes(x, y)) +
geom_point() +
stat_quant_band(formula = formula, color = "black", fill = "grey60") +
- stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*",
+ stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*",
after_stat(eq.label), sep = "")),
formula = formula) +
theme_classic()
ggplot(my.data, aes(x, y, color = group)) +
geom_point() +
stat_quant_line(formula = formula) +
- stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*",
+ stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*",
after_stat(eq.label), sep = "")),
formula = formula)
In some cases double quantile regression is an informative method to assess reciprocal constraints. For this a fit of x on @@ -2285,112 +2287,139 @@
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+Here we use a negative value to use an abbreviation of the word “adjusted” to three characters.
-# position of contrasts' bars (manual)
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(p.adjust.method = "bonferroni",
- adj.method.tag = -3,
- size = 2.75) +
- expand_limits(y = 0)
A character string passed as argument is used as is, here to set the -tag in Spanish.
# position of contrasts' bars (manual)
ggplot(mpg, aes(factor(cyl), hwy)) +
geom_boxplot(width = 0.33) +
- stat_multcomp(adj.method.tag = "ajustada",
- size = 2.75) +
- expand_limits(y = 0)
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+A character string passed as argument is used as is, here to set the +tag in Spanish.
+# position of contrasts' bars (manual)
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(adj.method.tag = "ajustada",
+ size = 2.75) +
+ expand_limits(y = 0)
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+A numeric vector passed to label.y
can be used to
manually set the location of each label along the y axis.
# position of contrasts' bars (manual)
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(label.y = c(7, 4, 1),
- contrasts = "Dunnet",
- size = 2.75) +
- expand_limits(y = 0)
ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(label.y =
- seq(from = 15,
- by = -3,
- length.out = 6),
- size = 2.5) +
- expand_limits(y = 0)
# position of contrasts' bars (manual)
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(label.y = c(7, 4, 1),
+ contrasts = "Dunnet",
+ size = 2.75) +
+ expand_limits(y = 0)
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(label.y =
+ seq(from = 15,
+ by = -3,
+ length.out = 6),
+ size = 2.5) +
+ expand_limits(y = 0)
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+We can pre-compute the numeric vector to achieve special positioning, in this case, next to each observation.
-means <-
- aggregate(mpg$hwy,
- by = list(mpg$cyl),
- FUN = mean,
- na.rm = TRUE)[["x"]]
-
-ggplot(mpg, aes(factor(cyl), hwy)) +
- stat_summary(fun.data = mean_se) +
- stat_multcomp(label.type = "letters",
- label.y = c(18, means), # 18 is for critical P label
- position = position_nudge(x = 0.1))
means <-
+ aggregate(mpg$hwy,
+ by = list(mpg$cyl),
+ FUN = mean,
+ na.rm = TRUE)[["x"]]
+
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ stat_summary(fun.data = mean_se) +
+ stat_multcomp(label.type = "letters",
+ label.y = c(18, means), # 18 is for critical P label
+ position = position_nudge(x = 0.1))
We can override the default use of geom_text()
and also
remove the P critical label.
# Using other geometries
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(label.type = "letters",
- adj.method.tag = FALSE,
- geom = "label")
# Using other geometries
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(label.type = "letters",
+ adj.method.tag = FALSE,
+ geom = "label")
With Dunnet contrasts, the use of bars can clutter a plot, and we can alternatively show the outcome for each level that has been compared to a control, the first level.
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(aes(x = stage(start = factor(cyl),
- after_stat = x.right.tip)),
- geom = "text",
- label.y = "bottom",
- vstep = 0,
- contrasts = "Dunnet")
ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(aes(x = stage(start = factor(cyl),
- after_stat = x.right.tip),
- label = after_stat(stars.label)),
- geom = "text",
- label.y = "bottom",
- vstep = 0,
- contrasts = "Dunnet")
ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(aes(x = stage(start = factor(cyl),
+ after_stat = x.right.tip)),
+ geom = "text",
+ label.y = "bottom",
+ vstep = 0,
+ contrasts = "Dunnet")
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(aes(x = stage(start = factor(cyl),
+ after_stat = x.right.tip),
+ label = after_stat(stars.label)),
+ geom = "text",
+ label.y = "bottom",
+ vstep = 0,
+ contrasts = "Dunnet")
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+The returned value includes numeric values in addition to character
strings mapped to the label
aesthetic. The numeric values
can be used to encode the outcomes using additional or different
aesthetics than the default.
# use colour to show significance
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(aes(colour = after_stat(p.value) < 0.01),
- size = 2.75) +
- scale_colour_manual(values = c("grey60", "black")) +
- theme_bw()
# add arrow heads to segments and use fill to show significance
-ggplot(mpg, aes(factor(cyl), hwy)) +
- geom_boxplot(width = 0.33) +
- stat_multcomp(aes(fill = after_stat(p.value) < 0.01),
- size = 2.5,
- arrow = grid::arrow(angle = 45,
- length = unit(1, "mm"),
- ends = "both")) +
- scale_fill_manual(values = c("white", "lightblue"))
# use colour to show significance
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(aes(colour = after_stat(p.value) < 0.01),
+ size = 2.75) +
+ scale_colour_manual(values = c("grey60", "black")) +
+ theme_bw()
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+# add arrow heads to segments and use fill to show significance
+ggplot(mpg, aes(factor(cyl), hwy)) +
+ geom_boxplot(width = 0.33) +
+ stat_multcomp(aes(fill = after_stat(p.value) < 0.01),
+ size = 2.5,
+ arrow = grid::arrow(angle = 45,
+ length = unit(1, "mm"),
+ ends = "both")) +
+ scale_fill_manual(values = c("white", "lightblue"))
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+"point"
.
-formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y, colour = group)) +
- geom_hline(yintercept = 0, linetype = "dashed") +
- stat_fit_residuals(formula = formula)
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y, colour = group)) +
+ geom_hline(yintercept = 0, linetype = "dashed") +
+ stat_fit_residuals(formula = formula)
We can of course also map the weights returned in the model fit
object to ggplot2 aesthetics, here we use size
.
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y, colour = group)) +
- geom_hline(yintercept = 0, linetype = "dashed") +
- stat_fit_residuals(formula = formula,
- method = "rlm",
- mapping = aes(size = sqrt(after_stat(weights))),
- alpha = 2/3)
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y, colour = group)) +
+ geom_hline(yintercept = 0, linetype = "dashed") +
+ stat_fit_residuals(formula = formula,
+ method = "rlm",
+ mapping = aes(size = sqrt(after_stat(weights))),
+ alpha = 2/3)
Weighted residuals are available, but in this case they do not differ
as we have not mapped any variable to the weight
aesthetic
in the input to the statistic.
"segment"
, each
deviation is displayed as a segment.
-formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y)) +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_deviations(formula = formula, colour = "red") +
- geom_point()
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y)) +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_deviations(formula = formula, colour = "red") +
+ geom_point()
The geometry used by default is ggplot2::geom_segment()
and additional aesthetics can be mapped or set to constant values. Here
we add arrowheads.
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y)) +
- geom_smooth(method = "lm", formula = formula) +
- geom_point() +
- stat_fit_deviations(formula = formula, colour = "red",
- arrow = arrow(length = unit(0.015, "npc"),
- ends = "both"))
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y)) +
+ geom_smooth(method = "lm", formula = formula) +
+ geom_point() +
+ stat_fit_deviations(formula = formula, colour = "red",
+ arrow = arrow(length = unit(0.015, "npc"),
+ ends = "both"))
When weights are available, either supplied by the user, or computed
as part of the fit, they are returned in data
. Having
weights available allows encoding them using colour. We here use a
robust regression fit with MASS::rlm()
.
my.data.outlier <- my.data
-my.data.outlier[6, "y"] <- my.data.outlier[6, "y"] * 5
-ggplot(my.data.outlier, aes(x, y)) +
- stat_smooth(method = MASS::rlm, formula = formula) +
- stat_fit_deviations(formula = formula, method = "rlm",
- mapping = aes(colour = after_stat(weights)),
- show.legend = TRUE) +
- scale_color_gradient(low = "red", high = "blue", limits = c(0, 1)) +
- geom_point()
my.data.outlier <- my.data
+my.data.outlier[6, "y"] <- my.data.outlier[6, "y"] * 5
+ggplot(my.data.outlier, aes(x, y)) +
+ stat_smooth(method = MASS::rlm, formula = formula) +
+ stat_fit_deviations(formula = formula, method = "rlm",
+ mapping = aes(colour = after_stat(weights)),
+ show.legend = TRUE) +
+ scale_color_gradient(low = "red", high = "blue", limits = c(0, 1)) +
+ geom_point()
# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly() correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_glance(method = "lm",
- method.args = list(formula = formula),
- label.x = "right",
- label.y = "bottom",
- aes(label = sprintf("italic(P)*\"-value = \"*%.3g",
- after_stat(p.value))),
- parse = TRUE)
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly() correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_glance(method = "lm",
+ method.args = list(formula = formula),
+ label.x = "right",
+ label.y = "bottom",
+ aes(label = sprintf("italic(P)*\"-value = \"*%.3g",
+ after_stat(p.value))),
+ parse = TRUE)
It is also possible to fit a non-linear model with
method = "nls"
, and any other model for which a
broom::glance()
method exists. Do consult the documentation
for package ‘broom’. Here we fit the Michaelis-Menten equation to
reaction rate versus concentration data.
micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
- geom_point() +
- geom_smooth(method = "nls",
- formula = micmen.formula,
- se = FALSE) +
- stat_fit_glance(method = "nls",
- method.args = list(formula = micmen.formula),
- aes(label = paste("AIC = ", signif(after_stat(AIC), digits = 3),
- ", BIC = ", signif(after_stat(BIC), digits = 3),
- sep = "")),
- label.x = "centre", label.y = "bottom")
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+ geom_point() +
+ geom_smooth(method = "nls",
+ formula = micmen.formula,
+ se = FALSE) +
+ stat_fit_glance(method = "nls",
+ method.args = list(formula = micmen.formula),
+ aes(label = paste("AIC = ", signif(after_stat(AIC), digits = 3),
+ ", BIC = ", signif(after_stat(BIC), digits = 3),
+ sep = "")),
+ label.x = "centre", label.y = "bottom")
The default output of stat_fit_tb()
is the default
output from tidy(fm)
where fm
is the fitted
model.
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_tb(method = "lm",
- method.args = list(formula = formula),
- tb.vars = c(Parameter = "term",
- Estimate = "estimate",
- "s.e." = "std.error",
- "italic(t)" = "statistic",
- "italic(P)" = "p.value"),
- label.y = "top", label.x = "left",
- parse = TRUE)
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_tb(method = "lm",
+ method.args = list(formula = formula),
+ tb.vars = c(Parameter = "term",
+ Estimate = "estimate",
+ "s.e." = "std.error",
+ "italic(t)" = "statistic",
+ "italic(P)" = "p.value"),
+ label.y = "top", label.x = "left",
+ parse = TRUE)
When tb.type = "fit.anova"
the output returned is that
from tidy(anova(fm))
where fm
is the fitted
model. Here we also show how to replace names of columns and terms, and
exclude one column, in this case, the mean squares.
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_tb(method = "lm",
- method.args = list(formula = formula),
- tb.type = "fit.anova",
- tb.vars = c(Effect = "term",
- df = "df",
- "italic(F)" = "statistic",
- "italic(P)" = "p.value"),
- tb.params = c(x = 1, "x^2" = 2, "x^3" = 3, Resid = 4),
- label.y = "top", label.x = "left",
- parse = TRUE)
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_tb(method = "lm",
+ method.args = list(formula = formula),
+ tb.type = "fit.anova",
+ tb.vars = c(Effect = "term",
+ df = "df",
+ "italic(F)" = "statistic",
+ "italic(P)" = "p.value"),
+ tb.params = c(x = 1, "x^2" = 2, "x^3" = 3, Resid = 4),
+ label.y = "top", label.x = "left",
+ parse = TRUE)
When tb.type = "fit.coefs"
the output returned is that
of tidy(fm)
after selecting the term
and
estimate
columns.
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_tb(method = "lm",
- method.args = list(formula = formula),
- tb.type = "fit.coefs", parse = TRUE,
- label.y = "center", label.x = "left")
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_tb(method = "lm",
+ method.args = list(formula = formula),
+ tb.type = "fit.coefs", parse = TRUE,
+ label.y = "center", label.x = "left")
Faceting works as expected, but grouping is ignored as mentioned
above. In this case, the colour aesthetic is not applied to the text of
the tables. Furthermore, if label.x.npc
or
label.y.npc
are passed numeric vectors of length > 1,
the corresponding values are obeyed by the different panels.
micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
- facet_wrap(~state) +
- geom_point() +
- geom_smooth(method = "nls",
- formula = micmen.formula,
- se = FALSE) +
- stat_fit_tb(method = "nls",
- method.args = list(formula = micmen.formula),
- tb.type = "fit.coefs",
- label.x = 0.9,
- label.y = c(0.75, 0.2)) +
- theme(legend.position = "none") +
- labs(x = "C", y = "V")
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+ facet_wrap(~state) +
+ geom_point() +
+ geom_smooth(method = "nls",
+ formula = micmen.formula,
+ se = FALSE) +
+ stat_fit_tb(method = "nls",
+ method.args = list(formula = micmen.formula),
+ tb.type = "fit.coefs",
+ label.x = 0.9,
+ label.y = c(0.75, 0.2)) +
+ theme(legend.position = "none") +
+ labs(x = "C", y = "V")
The data in the example below are split by ggplot into six groups
based on the levels of the feed
factor. However, as
stat_fit_tb()
ignores groupings, we can still fit a linear
model to all the data in the panel.
ggplot(chickwts, aes(factor(feed), weight)) +
- stat_summary(fun.data = "mean_se") +
- stat_fit_tb(tb.type = "fit.anova",
- label.x = "center",
- label.y = "bottom") +
- expand_limits(y = 0)
ggplot(chickwts, aes(factor(feed), weight)) +
+ stat_summary(fun.data = "mean_se") +
+ stat_fit_tb(tb.type = "fit.anova",
+ label.x = "center",
+ label.y = "bottom") +
+ expand_limits(y = 0)
We can flip the system of coordinates, if desired.
-ggplot(chickwts, aes(factor(feed), weight)) +
- stat_summary(fun.data = "mean_se") +
- stat_fit_tb(tb.type = "fit.anova", label.x = "left", size = 3) +
- scale_x_discrete(expand = expansion(mult = c(0.2, 0.5))) +
- coord_flip()
ggplot(chickwts, aes(factor(feed), weight)) +
+ stat_summary(fun.data = "mean_se") +
+ stat_fit_tb(tb.type = "fit.anova", label.x = "left", size = 3) +
+ scale_x_discrete(expand = expansion(mult = c(0.2, 0.5))) +
+ coord_flip()
It is also possible to rotate the table using angle
.
Here we also show how to replace the column headers with strings to be
parsed into R expressions.
ggplot(chickwts, aes(factor(feed), weight)) +
- stat_summary(fun.data = "mean_se") +
- stat_fit_tb(tb.type = "fit.anova",
- angle = 90, size = 3,
- label.x = "right", label.y = "center",
- hjust = 0.5, vjust = 0,
- tb.vars = c(Effect = "term",
- "df",
- "M.S." = "meansq",
- "italic(F)" = "statistic",
- "italic(P)" = "p.value"),
- parse = TRUE) +
- scale_x_discrete(expand = expansion(mult = c(0.1, 0.35))) +
- expand_limits(y = 0)
ggplot(chickwts, aes(factor(feed), weight)) +
+ stat_summary(fun.data = "mean_se") +
+ stat_fit_tb(tb.type = "fit.anova",
+ angle = 90, size = 3,
+ label.x = "right", label.y = "center",
+ hjust = 0.5, vjust = 0,
+ tb.vars = c(Effect = "term",
+ "df",
+ "M.S." = "meansq",
+ "italic(F)" = "statistic",
+ "italic(P)" = "p.value"),
+ parse = TRUE) +
+ scale_x_discrete(expand = expansion(mult = c(0.1, 0.35))) +
+ expand_limits(y = 0)
stats::nls()
. We use
the self-starting function stats::SSmicmen()
available in
R.
-micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
- geom_point() +
- geom_smooth(method = "nls",
- formula = micmen.formula,
- se = FALSE) +
- stat_fit_tidy(method = "nls",
- method.args = list(formula = micmen.formula),
- label.x = "right",
- label.y = "bottom",
- aes(label = paste("V[m]~`=`~", signif(after_stat(Vm_estimate), digits = 3),
- "%+-%", signif(after_stat(Vm_se), digits = 2),
- "~~~~K~`=`~", signif(after_stat(K_estimate), digits = 3),
- "%+-%", signif(after_stat(K_se), digits = 2),
- sep = "")),
- parse = TRUE)
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+ geom_point() +
+ geom_smooth(method = "nls",
+ formula = micmen.formula,
+ se = FALSE) +
+ stat_fit_tidy(method = "nls",
+ method.args = list(formula = micmen.formula),
+ label.x = "right",
+ label.y = "bottom",
+ aes(label = paste("V[m]~`=`~", signif(after_stat(Vm_estimate), digits = 3),
+ "%+-%", signif(after_stat(Vm_se), digits = 2),
+ "~~~~K~`=`~", signif(after_stat(K_estimate), digits = 3),
+ "%+-%", signif(after_stat(K_se), digits = 2),
+ sep = "")),
+ parse = TRUE)
Using paste we can build a string that can be parsed into an R expression, in this case for a non-linear equation.
-micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
- geom_point() +
- geom_smooth(method = "nls",
- formula = micmen.formula,
- se = FALSE) +
- stat_fit_tidy(method = "nls",
- method.args = list(formula = micmen.formula),
- size = 3,
- label.x = "center",
- label.y = "bottom",
- vstep = 0.12,
- aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
- signif(after_stat(K_estimate), digits = 2), "+C)",
- sep = "")),
- parse = TRUE) +
- labs(x = "C", y = "V")
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+ geom_point() +
+ geom_smooth(method = "nls",
+ formula = micmen.formula,
+ se = FALSE) +
+ stat_fit_tidy(method = "nls",
+ method.args = list(formula = micmen.formula),
+ size = 3,
+ label.x = "center",
+ label.y = "bottom",
+ vstep = 0.12,
+ aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
+ signif(after_stat(K_estimate), digits = 2), "+C)",
+ sep = "")),
+ parse = TRUE) +
+ labs(x = "C", y = "V")
What if we would need a more specific statistic, similar to
stat_poly_eq()
? We can use stat_fit_tidy()
as
the basis for its definition.
stat_micmen_eq <- function(vstep = 0.12,
- size = 3,
- ...) {
- stat_fit_tidy(method = "nls",
- method.args = list(formula = micmen.formula),
- aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
- signif(after_stat(K_estimate), digits = 2), "+C)",
- sep = "")),
- parse = TRUE,
- vstep = vstep,
- size = size,
- ...)
-}
stat_micmen_eq <- function(vstep = 0.12,
+ size = 3,
+ ...) {
+ stat_fit_tidy(method = "nls",
+ method.args = list(formula = micmen.formula),
+ aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
+ signif(after_stat(K_estimate), digits = 2), "+C)",
+ sep = "")),
+ parse = TRUE,
+ vstep = vstep,
+ size = size,
+ ...)
+}
The code for the figure is now simpler, and still produces the same figure (not shown).
-micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
- geom_point() +
- geom_smooth(method = "nls",
- formula = micmen.formula,
- se = FALSE) +
- stat_micmen_eq(label.x = "center",
- label.y = "bottom") +
- labs(x = "C", y = "V")
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+ geom_point() +
+ geom_smooth(method = "nls",
+ formula = micmen.formula,
+ se = FALSE) +
+ stat_micmen_eq(label.x = "center",
+ label.y = "bottom") +
+ labs(x = "C", y = "V")
quantreg::rq()
from package ‘quantreg’.my_formula <- y ~ x
-
-ggplot(mpg, aes(displ, 1 / hwy)) +
- geom_point() +
- geom_quantile(quantiles = 0.5, formula = my_formula) +
- stat_fit_tidy(method = "rq",
- method.args = list(formula = y ~ x, tau = 0.5),
- tidy.args = list(se.type = "nid"),
- mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
- after_stat(Intercept_estimate),
- after_stat(x_estimate),
- after_stat(x_p.value))),
- parse = TRUE)
my_formula <- y ~ x
+
+ggplot(mpg, aes(displ, 1 / hwy)) +
+ geom_point() +
+ geom_quantile(quantiles = 0.5, formula = my_formula) +
+ stat_fit_tidy(method = "rq",
+ method.args = list(formula = y ~ x, tau = 0.5),
+ tidy.args = list(se.type = "nid"),
+ mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
+ after_stat(Intercept_estimate),
+ after_stat(x_estimate),
+ after_stat(x_p.value))),
+ parse = TRUE)
We can define a stat_rq_eq()
if we need to add similar
equations to several plots. In this example we retain the ability of the
user to override most of the default default arguments.
stat_rq_eqn <-
- function(formula = y ~ x,
- tau = 0.5,
- method = "br",
- mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
- after_stat(Intercept_estimate),
- after_stat(x_estimate),
- after_stat(x_p.value))),
- parse = TRUE,
- ...) {
- method.args <- list(formula = formula, tau = tau, method = method)
- stat_fit_tidy(method = "rq",
- method.args = method.args,
- tidy.args = list(se.type = "nid"),
- mapping = mapping,
- parse = parse,
- ...)
- }
stat_rq_eqn <-
+ function(formula = y ~ x,
+ tau = 0.5,
+ method = "br",
+ mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
+ after_stat(Intercept_estimate),
+ after_stat(x_estimate),
+ after_stat(x_p.value))),
+ parse = TRUE,
+ ...) {
+ method.args <- list(formula = formula, tau = tau, method = method)
+ stat_fit_tidy(method = "rq",
+ method.args = method.args,
+ tidy.args = list(se.type = "nid"),
+ mapping = mapping,
+ parse = parse,
+ ...)
+ }
And the code of the figure now as simple as. Figure not shown, as is identical to the one above.
-ggplot(mpg, aes(displ, 1 / hwy)) +
- geom_point() +
- geom_quantile(quantiles = 0.5, formula = my_formula) +
- stat_rq_eqn(tau = 0.5, formula = my_formula)
ggplot(mpg, aes(displ, 1 / hwy)) +
+ geom_point() +
+ geom_quantile(quantiles = 0.5, formula = my_formula) +
+ stat_rq_eqn(tau = 0.5, formula = my_formula)
stat_fit_augment()
can handle any fitted model that is
supported by package ‘broom’ or its extensions. All these statistics
support grouping and facets.
-# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- geom_point() +
- stat_fit_augment(method = "lm",
- method.args = list(formula = formula))
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ geom_point() +
+ stat_fit_augment(method = "lm",
+ method.args = list(formula = formula))
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
- geom_point() +
- stat_fit_augment(method = "lm",
- method.args = list(formula = formula))
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+ geom_point() +
+ stat_fit_augment(method = "lm",
+ method.args = list(formula = formula))
We can override the variable returned as y
to be any of
the variables in the data frame returned by
broom::augment()
while still preserving the original
y
values.
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- stat_fit_augment(method = "lm",
- method.args = list(formula = formula),
- geom = "point",
- y.out = ".resid")
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ stat_fit_augment(method = "lm",
+ method.args = list(formula = formula),
+ geom = "point",
+ y.out = ".resid")
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
- stat_fit_augment(method = "lm",
- method.args = list(formula = formula),
- geom = "point",
- y.out = ".std.resid")
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+ stat_fit_augment(method = "lm",
+ method.args = list(formula = formula),
+ geom = "point",
+ y.out = ".std.resid")
We can use any model fitting method for which
broom::augment()
is implemented.
args <- list(formula = y ~ k * e ^ x,
- start = list(k = 1, e = 2))
-ggplot(mtcars, aes(wt, mpg)) +
- geom_point() +
- stat_fit_augment(method = "nls",
- method.args = args)
args <- list(formula = y ~ k * e ^ x,
+ start = list(k = 1, e = 2))
+ggplot(mtcars, aes(wt, mpg)) +
+ geom_point() +
+ stat_fit_augment(method = "nls",
+ method.args = args)
args <- list(formula = y ~ k * e ^ x,
- start = list(k = 1, e = 2))
-ggplot(mtcars, aes(wt, mpg)) +
- stat_fit_augment(method = "nls",
- method.args = args,
- geom = "point",
- y.out = ".resid")
args <- list(formula = y ~ k * e ^ x,
+ start = list(k = 1, e = 2))
+ggplot(mtcars, aes(wt, mpg)) +
+ stat_fit_augment(method = "nls",
+ method.args = args,
+ geom = "point",
+ y.out = ".resid")
Note: The tidiers for mixed models have moved to package ‘broom.mixed’!
-args <- list(model = y ~ SSlogis(x, Asym, xmid, scal),
- fixed = Asym + xmid + scal ~1,
- random = Asym ~1 | group,
- start = c(Asym = 200, xmid = 725, scal = 350))
-ggplot(Orange, aes(age, circumference, colour = Tree)) +
- geom_point() +
- stat_fit_augment(method = "nlme",
- method.args = args,
- augment.args = list(data = quote(data)))
args <- list(model = y ~ SSlogis(x, Asym, xmid, scal),
+ fixed = Asym + xmid + scal ~1,
+ random = Asym ~1 | group,
+ start = c(Asym = 200, xmid = 725, scal = 350))
+ggplot(Orange, aes(age, circumference, colour = Tree)) +
+ geom_point() +
+ stat_fit_augment(method = "nlme",
+ method.args = args,
+ augment.args = list(data = quote(data)))
# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly() correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_glance(geom = "debug",
- method = "lm",
- method.args = list(formula = formula),
- label.x = "right",
- label.y = "bottom",
- aes(label = sprintf("italic(P)*\"-value = \"*%.3g",
- after_stat(p.value))),
- parse = TRUE)
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly() correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_glance(geom = "debug",
+ method = "lm",
+ method.args = list(formula = formula),
+ label.x = "right",
+ label.y = "bottom",
+ aes(label = sprintf("italic(P)*\"-value = \"*%.3g",
+ after_stat(p.value))),
+ parse = TRUE)
## Warning in stat_fit_glance(geom = "debug", method = "lm", method.args =
## list(formula = formula), : Ignoring unknown parameters: `parse`
## [1] "PANEL 1; group(s) 1, 2; 'draw_function()' input 'data' (head):"
@@ -2895,21 +2924,21 @@ How to find out what variables are computed
case, function str()
is more informative than
head()
, so we can pass it as argument overriding the
default.
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
- geom_point() +
- geom_smooth(method = "lm", formula = formula) +
- stat_fit_tb(geom = "debug",
- summary.fun = str,
- method = "lm",
- method.args = list(formula = formula),
- tb.vars = c(Parameter = "term",
- Estimate = "estimate",
- "s.e." = "std.error",
- "italic(t)" = "statistic",
- "italic(P)" = "p.value"),
- label.y = "top", label.x = "left",
- parse = TRUE)
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+ geom_point() +
+ geom_smooth(method = "lm", formula = formula) +
+ stat_fit_tb(geom = "debug",
+ summary.fun = str,
+ method = "lm",
+ method.args = list(formula = formula),
+ tb.vars = c(Parameter = "term",
+ Estimate = "estimate",
+ "s.e." = "std.error",
+ "italic(t)" = "statistic",
+ "italic(P)" = "p.value"),
+ label.y = "top", label.x = "left",
+ parse = TRUE)
## Warning in stat_fit_tb(geom = "debug", summary.fun = str, method = "lm", : Ignoring unknown parameters: `table.theme`, `table.rownames`, `table.colnames`,
## `table.hjust`, `parse`, and `summary.fun`
## [1] "PANEL 1; group(s) NULL; 'draw_function()' input 'data' (head):"
@@ -2970,7 +2999,7 @@ Volcano-plot examples
Outcomes encoded as -1, 0 or 1, as seen in the tibble below need to
be converted into factors with suitable labels for levels. This can be
easily achieved with function outcome2factor()
.
-
+
## tag gene outcome logFC PValue genotype
## 1 AT1G01040 ASU1 0 -0.15284466 0.35266997 Ler
## 2 AT1G01290 ASG4 0 -0.30057068 0.05471732 Ler
@@ -2996,24 +3025,24 @@ Volcano-plot examples
arguments to parameters name
and labels
of
these scales. These x and y scales by default squish off-limits
(out-of-bounds) observations towards the limits.
-ggplot(volcano_example.df,
- aes(logFC, PValue, colour = outcome2factor(outcome))) +
- geom_point() +
- scale_x_logFC(name = "Transcript abundance%unit") +
- scale_y_Pvalue() +
- scale_colour_outcome() +
- stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
+ggplot(volcano_example.df,
+ aes(logFC, PValue, colour = outcome2factor(outcome))) +
+ geom_point() +
+ scale_x_logFC(name = "Transcript abundance%unit") +
+ scale_y_Pvalue() +
+ scale_colour_outcome() +
+ stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
![](data:image/png;base64,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)
By default outcome2factor()
creates a factor with three
levels as in the example above, but this default can be overridden as
shown below.
-ggplot(volcano_example.df,
- aes(logFC, PValue, colour = outcome2factor(outcome, n.levels = 2))) +
- geom_point() +
- scale_x_logFC(name = "Transcript abundance%unit") +
- scale_y_Pvalue() +
- scale_colour_outcome() +
- stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
+ggplot(volcano_example.df,
+ aes(logFC, PValue, colour = outcome2factor(outcome, n.levels = 2))) +
+ geom_point() +
+ scale_x_logFC(name = "Transcript abundance%unit") +
+ scale_y_Pvalue() +
+ scale_colour_outcome() +
+ stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
![](data:image/png;base64,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)
scale_colour_outcome()
and
scale_fill_outcome()
.
-
+
## tag gene outcome.x outcome.y logFC.x logFC.y genotype
## 1 AT5G11060 TIC56 0 0 -0.17685517 -0.32956762 Ler
## 2 AT3G01280 ATWRKY48 0 0 -0.06471884 0.07771315 Ler
@@ -3042,66 +3071,66 @@ Quadrant-plot examples
## 6 AT2G16070 UBQ11 0 0 -0.22328946 -0.23210780 Ler
In this plot we do not include those genes whose change in transcript abundance is uncertain under both x and y conditions.
- ggplot(subset(quadrant_example.df,
- xy_outcomes2factor(outcome.x, outcome.y) != "none"),
- aes(logFC.x, logFC.y,
- colour = outcome2factor(outcome.x),
- fill = outcome2factor(outcome.y))) +
- geom_quadrant_lines(linetype = "dotted") +
- stat_quadrant_counts(size = 3, colour = "white") +
- geom_point(shape = "circle filled") +
- scale_x_logFC(name = "Transcript abundance for x%unit") +
- scale_y_logFC(name = "Transcript abundance for y%unit") +
- scale_colour_outcome() +
- scale_fill_outcome() +
- theme_dark()
ggplot(subset(quadrant_example.df,
+ xy_outcomes2factor(outcome.x, outcome.y) != "none"),
+ aes(logFC.x, logFC.y,
+ colour = outcome2factor(outcome.x),
+ fill = outcome2factor(outcome.y))) +
+ geom_quadrant_lines(linetype = "dotted") +
+ stat_quadrant_counts(size = 3, colour = "white") +
+ geom_point(shape = "circle filled") +
+ scale_x_logFC(name = "Transcript abundance for x%unit") +
+ scale_y_logFC(name = "Transcript abundance for y%unit") +
+ scale_colour_outcome() +
+ scale_fill_outcome() +
+ theme_dark()
To plot in separate panels those observations that are significant along both x and y axes, x axis, y axis, or none, with quadrants merged takes more effort. We first define two helper functions to add counts and quadrant lines to each of the four panels.
-all_quadrant_counts <- function(...) {
- list(
- stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "xy"), ...),
- stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "x"), pool.along = "y", ...),
- stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "y"), pool.along = "x", ...),
- stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "none"), quadrants = 0L, ...)
- )
-}
all_quadrant_lines <- function(...) {
- list(
- geom_hline(data = data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
- levels = c("xy", "x", "y", "none")),
- yintercept = c(0, NA, 0, NA)),
- aes(yintercept = yintercept),
- na.rm = TRUE,
- ...),
- geom_vline(data = data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
- levels = c("xy", "x", "y", "none")),
- xintercept = c(0, 0, NA, NA)),
- aes(xintercept = xintercept),
- na.rm = TRUE,
- ...)
- )
-}
all_quadrant_counts <- function(...) {
+ list(
+ stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "xy"), ...),
+ stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "x"), pool.along = "y", ...),
+ stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "y"), pool.along = "x", ...),
+ stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "none"), quadrants = 0L, ...)
+ )
+}
all_quadrant_lines <- function(...) {
+ list(
+ geom_hline(data = data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
+ levels = c("xy", "x", "y", "none")),
+ yintercept = c(0, NA, 0, NA)),
+ aes(yintercept = yintercept),
+ na.rm = TRUE,
+ ...),
+ geom_vline(data = data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
+ levels = c("xy", "x", "y", "none")),
+ xintercept = c(0, 0, NA, NA)),
+ aes(xintercept = xintercept),
+ na.rm = TRUE,
+ ...)
+ )
+}
And use these functions to build the final plot, in this case including all genes.
-quadrant_example.df %>%
- mutate(.,
- outcome.x.fct = outcome2factor(outcome.x),
- outcome.y.fct = outcome2factor(outcome.y),
- outcome.xy.fct = xy_outcomes2factor(outcome.x, outcome.y)) %>%
- ggplot(., aes(logFC.x, logFC.y, colour = outcome.x.fct, fill = outcome.y.fct)) +
- geom_point(shape = 21) +
- all_quadrant_lines(linetype = "dotted") +
- all_quadrant_counts(size = 3, colour = "white") +
- scale_x_logFC(name = "Transcript abundance for x%unit") +
- scale_y_logFC(name = "Transcript abundance for y%unit") +
- scale_colour_outcome() +
- scale_fill_outcome() +
- facet_wrap(~outcome.xy.fct) +
- theme_dark()
quadrant_example.df %>%
+ mutate(.,
+ outcome.x.fct = outcome2factor(outcome.x),
+ outcome.y.fct = outcome2factor(outcome.y),
+ outcome.xy.fct = xy_outcomes2factor(outcome.x, outcome.y)) %>%
+ ggplot(., aes(logFC.x, logFC.y, colour = outcome.x.fct, fill = outcome.y.fct)) +
+ geom_point(shape = 21) +
+ all_quadrant_lines(linetype = "dotted") +
+ all_quadrant_counts(size = 3, colour = "white") +
+ scale_x_logFC(name = "Transcript abundance for x%unit") +
+ scale_y_logFC(name = "Transcript abundance for y%unit") +
+ scale_colour_outcome() +
+ scale_fill_outcome() +
+ facet_wrap(~outcome.xy.fct) +
+ theme_dark()