# afex_plot

##### m-way Plot with Error Bars and Raw Data

Plots results from factorial experiments. Estimated marginal means and error bars are plotted in the foreground, raw data is plotted in the background. Error bars can be based on different standard errors (e.g., model-based, within-subjects, between-subjects). Functions described here return a ggplot2 plot object, thus allowing further customization of the plot.

`afex_plot`

is the user friendly function that does data preparation
and plotting. It also allows to only return the prepared data (```
return
= "data"
```

).

`interaction_plot`

does the plotting when a `trace`

factor is
present. `oneway_plot`

does the plotting when a `trace`

factor is
absent.

##### Usage

`afex_plot(object, ...)`# S3 method for afex_aov
afex_plot(object, x, trace, panel, mapping,
error = "model", error_ci = TRUE, error_level = 0.95,
error_arg = list(width = 0), data_plot = TRUE, data_geom,
data_alpha = 0.5, data_arg = list(color = "darkgrey"),
point_arg = list(), line_arg = list(), emmeans_arg = list(),
dodge = 0.5, return = "plot", factor_levels = list(), legend_title,
...)

# S3 method for mixed
afex_plot(object, x, trace, panel, mapping, random,
error = "model", error_ci = TRUE, error_level = 0.95,
error_arg = list(width = 0), data_plot = TRUE, data_geom,
data_alpha = 0.5, data_arg = list(color = "darkgrey"),
point_arg = list(), line_arg = list(), emmeans_arg = list(),
dodge = 0.5, return = "plot", factor_levels = list(), legend_title,
...)

# S3 method for merMod
afex_plot(object, x, trace, panel, mapping, random,
error = "model", error_ci = TRUE, error_level = 0.95,
error_arg = list(width = 0), data_plot = TRUE, data_geom,
data_alpha = 0.5, data_arg = list(color = "darkgrey"),
point_arg = list(), line_arg = list(), emmeans_arg = list(),
dodge = 0.5, return = "plot", factor_levels = list(), legend_title,
...)

interaction_plot(means, data, mapping = c("shape", "lineytpe"),
error_plot = TRUE, error_arg = list(width = 0), data_plot = TRUE,
data_geom = ggplot2::geom_point, data_alpha = 0.5,
data_arg = list(color = "darkgrey"), point_arg = list(),
line_arg = list(), dodge = 0.5, legend_title, col_x = "x",
col_y = "y", col_trace = "trace", col_panel = "panel",
col_lower = "lower", col_upper = "upper")

oneway_plot(means, data, mapping = "", error_plot = TRUE,
error_arg = list(width = 0), data_plot = TRUE,
data_geom = ggbeeswarm::geom_beeswarm, data_alpha = 0.5,
data_arg = list(color = "darkgrey"), point_arg = list(),
legend_title, col_x = "x", col_y = "y", col_panel = "panel",
col_lower = "lower", col_upper = "upper")

##### Arguments

- object
`afex_aov`

,`mixed`

, or`merMod`

object.- ...
currently ignored.

- x
A

`character`

vector or one-sided`formula`

specifying the factor names of the predictors displayed on the x-axis.`mapping`

specifies further mappings for these factors if`trace`

is missing.- trace
An optional

`character`

vector or one-sided`formula`

specifying the factor names of the predictors connected by the same line.`mapping`

specifies further mappings for these factors.- panel
An optional

`character`

vector or one-sided`formula`

specifying the factor names of the predictors shown in different panels.- mapping
A

`character`

vector specifying which aesthetic mappings should be applied to either the`trace`

factors (if`trace`

is specified) or the`x`

factors. Useful options are any combination of`"shape"`

,`"color"`

,`"linetype"`

, or also`"fill"`

(see examples). The default (i.e., missing) uses`c("shape", "linetype")`

if`trace`

is specified and`""`

otherwise (i.e., no additional aesthetic).- error
A scalar

`character`

vector specifying on which standard error the error bars should be based. Default is`"model"`

, which plots model-based standard errors. Further options are:`"none"`

(or`NULL`

),`"mean"`

,`"within"`

(or`"CMO"`

), and`"between"`

. See details.- error_ci
Logical. Should error bars plot confidence intervals (=

`TRUE`

, the default) or standard errors (=`FALSE`

)?- error_level
Numeric value between 0 and 1 determing the width of the confidence interval. Default is .95 corresponding to a 95% confidence interval.

- error_arg
A

`list`

of further arguments passed to`geom_errorbar`

, which draws the errorsbars. Default is`list(width = 0)`

which suppresses the vertical bars at the end of the error bar.- data_plot
`logical`

. Should raw data be plotted in the background? Default is`TRUE`

.- data_geom
Geom

`function`

used for plotting data in background. The default (missing) uses`geom_point`

if`trace`

is specified, otherwise`geom_beeswarm`

. See examples fo further options.- data_alpha
numeric

`alpha`

value between 0 and 1 passed to`data_geom`

. Default is`0.5`

which correspond to semitransparent data points in the background such that overlapping data points are plotted darker.- data_arg
A

`list`

of further arguments passed to`data_geom`

. Default is`list(color = "darkgrey")`

, which plots points in the background in grey.- point_arg, line_arg
A

`list`

of further arguments passed to`geom_point`

or`geom_line`

which draw the points and lines in the foreground. Default is`list()`

.`line_arg`

is only used if`trace`

is specified.- emmeans_arg
A

`list`

of further arguments passed to`emmeans`

. Of particular importance for ANOVAs is`model`

, see`afex_aov-methods`

.- dodge
Numerical amount of dodging of factor-levels on x-axis. Default is

`0.5`

.- return
A scalar

`character`

specifying what should be returned. The default`"plot"`

returns the ggplot2 plot. The other option`"data"`

returns a list with two`data.frame`

s containing the data used for plotting:`means`

contains the means and standard errors for the foreground,`data`

contains the raw data in the background.- factor_levels
A

`list`

of new factor levels that should be used in the plot. The name of each list entry needs to correspond to one of the factors in the plot.- legend_title
A scalar

`character`

vector with a new title for the legend.- random
A

`character`

vector specifying over which variables the raw data should be aggregated in case of`mixed`

objects. The default (missing) uses all random effects grouping factors which can lead to many data points.`error = "within"`

or`error = "between"`

require that`random`

is of length 1. See examples.- means, data
`data.frame`

s used for plotting of the plotting functions.- error_plot
`logical`

. Should error bars be plotted? Only used in plotting functions. To suppress plotting of error bars use`error = "none"`

in`afex_plot`

.- col_y, col_x, col_trace, col_panel
A scalar

`character`

string specifying the name of the corresponding column containing the information used for plotting. Each column needs to exist in both the`means`

and the`data`

`data.frame`

.- col_lower, col_upper
A scalar

`character`

string specifying the name of the columns containing lower and upper bounds for the error bars. These columns need to exist in`means`

.

##### Details

`afex_plot`

obtains the estimated marginal means via
`emmeans`

and aggregates the raw data to the same
level. It then calculates the desired confidence interval or standard error
(see below) and passes the prepared data to one of the two plotting
functions: `interaction_plot`

when `trace`

is specified and
`oneway_plot`

otherwise.

### Error Bars

Error bars provide a grahical representation of the variability of the estimated means and should be routinely added to results figures. However, there exist several possibilities which particular measure of variability to use. Because of this, any figure depicting error bars should be accompanied by a note detailing which measure the error bars shows. The present functions allow plotting of different types of confidence intervals (if`error_ci = TRUE`

, the default) or standard
errors (if `error_ci = FALSE`

).A further complication is that readers routinely misinterpret confidence
intervals. The most common error is to assume that non-overlapping error
bars indicate a significant difference (e.g., Belia et al., 2005). This is
rarely the case (see e.g., Cumming & Finch, 2005; Knol et al., 2011;
Schenker & Gentleman, 2005). For example, in a fully between-subjects design
in which the error bars depict 95% confidence intervals and groups are of
approximately equal size and have equal variance, even error bars that
overlap by as much as 50% still correspond to *p* < .05. Error bars
that are just touching roughly correspond to *p* = .01.

In the case of designs involving repeated-measures factors the usual confidence intervals or standard errors (i.e., model-based confidence intervals or intervals based on the standard error of the mean) cannot be used to gauge significant differences as this requires knowledge about the correlation between measures. One popular alternative in the psychological literature are intervals based on within-subjects standard errors/confidence intervals (e.g., Cousineau & O'Brien, 2014). These attempt to control for the correlation across individuals and thereby allow judging differences between repeated-measures condition. As a downside, when using within-subjects intervals no comparisons across between-subjects conditions or with respect to a fixed-value are possible anymore.

In the case of a mixed-design, no single type of error bar is possible that
allows comparison across all conditions. Likewise, for mixed models
involving multiple *crossed* random effects, no single set of error
bars (or even data aggregation) adequately represent the true varibility in
the data and adequately allows for "inference by eye". Therefore, special
care is necessary in such cases. One possiblity is to avoid error bars
altogether and plot only the raw data in the background (with ```
error =
"none"
```

). The raw data in the background still provides a visual impression
of the variability in the data and the precision of the mean estimate, but
does not as easily suggest an incorrect inferences. Another possibility is
to use the model-based standard error and note in the figure caption that
it does not permit comparisons across repeated-measures factors.

The following "rules of eye" (Cumming and Finch, 2005) hold, when permitted by design (i.e., within-subjects bars for within-subjects comparisons; other variants for between-subjects comparisons), and groups are approximately equal in size and variance. Note that for more complex designs ususally analyzed with mixed models, such as designs involving complicated dependencies across data points, these rules of thumbs may be highly misleading.

*p*< .05 when the overlap of the 95% confidence intervals (CIs) is no more than about half the average margin of error, that is, when proportion overlap is about .50 or less.*p*< .01 when the two CIs do not overlap, that is, when proportion overlap is about 0 or there is a positive gap.*p*< .05 when the gap between standard error (SE) bars is at least about the size of the average SE, that is, when the proportion gap is about 1 or greater.*p*< .01 when the proportion gap between SE bars is about 2 or more.

### Implemented Standard Errors

The following lists the implemented approaches to calculate confidence intervals (CIs) and standard errors (SEs). CIs are based on the SEs using the*t*-distribution with degrees of freedom based on the cell or group size. For ANOVA models,

`afex_plot`

attempts to warn in case the chosen approach is misleading
given the design (e.g., model-based error bars for purely
within-subjects plots). For `mixed`

models, no such warnings are
produced, but users should be aware that all options beside `"model"`

are not actually appropriate and have only heuristic value. But then again,
`"model"`

based error bars do not permit comparisons for factors
varying within one of the random-effects grouping factors (i.e., factors
for which random-slopes should be estimated).
`"model"`

Uses model-based CIs and SEs. For ANOVAs, the variant based on the

`lm`

or`mlm`

model (i.e.,`emmeans_arg = list(model = "multivariate")`

) seems generally preferrable.`"mean"`

Calculates the standard error of the mean for each cell ignoring any repeated-measures factors.

`"within"`

or`"CMO"`

Calculates within-subjects SEs using the Cosineau-Morey-O'Brien (Cousineau & O'Brien, 2014) method. This method is based on a double normalization of the data. SEs and CIs are then calculated independently for each cell (i.e., if the desired output contains between-subjects factors, SEs are calculated for each cell including the between-subjects factors).

`"between"`

First aggregates the data per participant and then calculates the SEs for each between-subjects condition. Results in one SE and

*t*-quantile for all conditions in purely within-subjects designs.`"none"`

or`NULL`

Suppresses calculation of SEs and plots no error bars.

`mixed`

models, the within-subjects/repeated-measures factors are
relative to the chosen `random`

effects grouping factor. They are
automatically detected based on the random-slopes of the random-effects
grouping factor in `random`

. All other factors are treated as
independent-samples or between-subjects factors.
##### Value

Returns a ggplot2 plot (i.e., object of class ```
c("gg",
"ggplot")
```

) unless `return = "data"`

.

##### References

Belia, S., Fidler, F., Williams, J., & Cumming, G. (2005).
Researchers Misunderstand Confidence Intervals and Standard Error Bars.
*Psychological Methods*, 10(4), 389-396.
https://doi.org/10.1037/1082-989X.10.4.389

Cousineau, D., & O'Brien, F. (2014). Error bars in within-subject designs:
a comment on Baguley (2012). *Behavior Research Methods*, 46(4),
1149-1151. https://doi.org/10.3758/s13428-013-0441-z

Cumming, G., & Finch, S. (2005). Inference by Eye: Confidence Intervals and
How to Read Pictures of Data. *American Psychologist*, 60(2), 170-180.
https://doi.org/10.1037/0003-066X.60.2.170

Knol, M. J., Pestman, W. R., & Grobbee, D. E. (2011). The (mis)use of
overlap of confidence intervals to assess effect modification.
*European Journal of Epidemiology*, 26(4), 253-254.
https://doi.org/10.1007/s10654-011-9563-8

Schenker, N., & Gentleman, J. F. (2001). On Judging the Significance of
Differences by Examining the Overlap Between Confidence Intervals.
*The American Statistician*, 55(3), 182-186.
https://doi.org/10.1198/000313001317097960

##### Examples

```
# NOT RUN {
# note: use library("ggplot") to avoid "ggplot2::" in the following
##################################################################
## 2-factor Within-Subject Design ##
##################################################################
data(md_12.1)
aw <- aov_ez("id", "rt", md_12.1, within = c("angle", "noise"))
##---------------------------------------------------------------
## Basic Interaction Plots -
##---------------------------------------------------------------
afex_plot(aw, x = "angle", trace = "noise")
# or: afex_plot(aw, x = ~angle, trace = ~noise)
afex_plot(aw, x = "noise", trace = "angle")
### For within-subject designs, using within-subject CIs is better:
afex_plot(aw, x = "angle", trace = "noise", error = "within")
(p1 <- afex_plot(aw, x = "noise", trace = "angle", error = "within"))
## use different themes for nicer graphs:
p1 + ggplot2::theme_bw()
# }
# NOT RUN {
p1 + ggplot2::theme_light()
p1 + ggplot2::theme_minimal()
p1 + jtools::theme_apa()
p1 + ggpubr::theme_pubr()
### set theme globally for R session:
ggplot2::theme_set(ggplot2::theme_bw())
### There are several ways to deal with overlapping points in the background besides alpha
# 1. using the default data geom and ggplot2::position_jitterdodge
afex_plot(aw, x = "noise", trace = "angle", error = "within", dodge = 0.3,
data_arg = list(
position =
ggplot2::position_jitterdodge(
jitter.width = 0,
jitter.height = 5,
dodge.width = 0.3 ## needs to be same as dodge
),
color = "darkgrey"))
# 2. using ggbeeswarm::geom_beeswarm
afex_plot(aw, x = "noise", trace = "angle", error = "within", dodge = 0.5,
data_geom = ggbeeswarm::geom_beeswarm,
data_arg = list(
dodge.width = 0.5, ## needs to be same as dodge
cex = 0.8,
color = "darkgrey"))
# 3. do not display points, but use a violinplot: ggplot2::geom_violin
afex_plot(aw, x = "noise", trace = "angle", error = "within",
data_geom = ggplot2::geom_violin,
data_arg = list(width = 0.5))
# 4. violinplots with color: ggplot2::geom_violin
afex_plot(aw, x = "noise", trace = "angle", error = "within",
mapping = c("linetype", "shape", "fill"),
data_geom = ggplot2::geom_violin,
data_arg = list(width = 0.5))
# 5. do not display points, but use a boxplot: ggplot2::geom_boxplot
afex_plot(aw, x = "noise", trace = "angle", error = "within",
data_geom = ggplot2::geom_boxplot,
data_arg = list(width = 0.3))
# 6. combine points with boxplot: ggpol::geom_boxjitter
afex_plot(aw, x = "noise", trace = "angle", error = "within",
data_geom = ggpol::geom_boxjitter,
data_arg = list(width = 0.3))
## hides error bars!
# 7. nicer variant of ggpol::geom_boxjitter
afex_plot(aw, x = "noise", trace = "angle", error = "within",
mapping = c("shape", "fill"),
data_geom = ggpol::geom_boxjitter,
data_arg = list(
width = 0.3,
jitter.width = 0,
jitter.height = 10,
outlier.intersect = TRUE),
point_arg = list(size = 2.5),
error_arg = list(size = 1.5, width = 0))
# 8. nicer variant of ggpol::geom_boxjitter without lines
afex_plot(aw, x = "noise", trace = "angle", error = "within", dodge = 0.7,
mapping = c("shape", "fill"),
data_geom = ggpol::geom_boxjitter,
data_arg = list(
width = 0.5,
jitter.width = 0,
jitter.height = 10,
outlier.intersect = TRUE),
point_arg = list(size = 2.5),
line_arg = list(linetype = 0),
error_arg = list(size = 1.5, width = 0))
# }
# NOT RUN {
##---------------------------------------------------------------
## Basic One-Way Plots -
##---------------------------------------------------------------
afex_plot(aw, x = "angle", error = "within") ## default
# }
# NOT RUN {
## with color we need larger points
afex_plot(aw, x = "angle", mapping = "color", error = "within",
point_arg = list(size = 2.5),
error_arg = list(size = 1.5, width = 0.05))
library("ggpol") ## currently required for combination of boxplot and points
afex_plot(aw, x = "angle", error = "within", data_geom = ggpol::geom_boxjitter)
## nicer
afex_plot(aw, x = "angle", error = "within", data_geom = ggpol::geom_boxjitter,
mapping = "fill", data_alpha = 0.7,
data_arg = list(
width = 0.6,
jitter.width = 0.07,
jitter.height = 10,
outlier.intersect = TRUE
),
point_arg = list(size = 2.5),
error_arg = list(size = 1.5, width = 0.05))
##---------------------------------------------------------------
## Other Basic Options -
##---------------------------------------------------------------
## relabel factor levels via new_levels
afex_plot(aw, x = "noise", trace = "angle",
new_levels = list(angle = c("0", "4", "8"),
noise = c("Absent", "Present")))
## Change title of legend
afex_plot(aw, x = "noise", trace = "angle",
legend_title = "Noise Condition")
## for plots with few factor levels, smaller dodge might be better:
afex_plot(aw, x = "angle", trace = "noise", dodge = 0.25)
#################################################################
## 4-factor Mixed Design ##
#################################################################
data(obk.long, package = "afex")
a1 <- aov_car(value ~ treatment * gender + Error(id/(phase*hour)),
data = obk.long, observed = "gender")
## too difficult to see anything
afex_plot(a1, ~phase*hour, ~treatment) +
ggplot2::theme_light()
## better
afex_plot(a1, ~hour, ~treatment, ~phase) +
ggplot2::theme_light()
## even better and different model-based standard errors
afex_plot(a1, ~hour, ~treatment, ~phase,
dodge = 0.65,
data_arg = list(
position =
ggplot2::position_jitterdodge(
jitter.width = 0,
jitter.height = 0.2,
dodge.width = 0.65 ## needs to be same as dodge
),
color = "darkgrey"),
emmeans_arg = list(model = "multivariate")) +
ggplot2::theme_classic()
# with color instead of linetype to separate trace factor
afex_plot(a1, ~hour, ~treatment, ~phase,
mapping = c("shape", "color"),
dodge = 0.65,
data_arg = list(
position =
ggplot2::position_jitterdodge(
jitter.width = 0,
jitter.height = 0.2,
dodge.width = 0.65 ## needs to be same as dodge
)),
emmeans_arg = list(model = "multivariate")) +
ggplot2::theme_light()
# only color to separate trace factor
afex_plot(a1, ~hour, ~treatment, ~phase,
mapping = "color",
dodge = 0.65,
data_arg = list(
position =
ggplot2::position_jitterdodge(
jitter.width = 0,
jitter.height = 0.2,
dodge.width = 0.65 ## needs to be same as dodge
)),
emmeans_arg = list(model = "multivariate")) +
ggplot2::theme_classic()
## plot involving all 4 factors:
afex_plot(a1, ~hour, ~treatment, ~gender+phase,
dodge = 0.65,
data_arg = list(
position =
ggplot2::position_jitterdodge(
jitter.width = 0,
jitter.height = 0.2,
dodge.width = 0.65 ## needs to be same as dodge
),
color = "darkgrey"),
emmeans_arg = list(model = "multivariate")) +
ggplot2::theme_bw()
##---------------------------------------------------------------
## Different Standard Errors Available -
##---------------------------------------------------------------
## purely within-design
cbind(
afex_plot(a1, ~phase, ~hour,
error = "model", return = "data")$means[,c("phase", "hour", "y", "SE")],
multivariate = afex_plot(a1, ~phase, ~hour,
emmeans_arg = list(model = "multivariate"),
error = "model", return = "data")$means$error,
mean = afex_plot(a1, ~phase, ~hour,
error = "mean", return = "data")$means$error,
within = afex_plot(a1, ~phase, ~hour,
error = "within", return = "data")$means$error,
between = afex_plot(a1, ~phase, ~hour,
error = "between", return = "data")$means$error)
## mixed design
cbind(
afex_plot(a1, ~phase, ~treatment,
error = "model", return = "data")$means[,c("phase", "treatment", "y", "SE")],
multivariate = afex_plot(a1, ~phase, ~treatment,
emmeans_arg = list(model = "multivariate"),
error = "model", return = "data")$means$error,
mean = afex_plot(a1, ~phase, ~treatment,
error = "mean", return = "data")$means$error,
within = afex_plot(a1, ~phase, ~treatment,
error = "within", return = "data")$means$error,
between = afex_plot(a1, ~phase, ~treatment,
error = "between", return = "data")$means$error)
# }
# NOT RUN {
##################################################################
## Mixed Models ##
##################################################################
data("Machines", package = "MEMSS")
m1 <- mixed(score ~ Machine + (Machine|Worker), data=Machines)
pairs(emmeans::emmeans(m1, "Machine"))
# contrast estimate SE df t.ratio p.value
# A - B -7.966667 2.420850 5 -3.291 0.0481
# A - C -13.916667 1.540100 5 -9.036 0.0007
# B - C -5.950000 2.446475 5 -2.432 0.1253
## Default (i.e., model-based) error bars suggest no difference between Machines.
## This contrasts with pairwise comparisons above.
afex_plot(m1, "Machine")
## Impression from within-subject error bars is more in line with pattern of differences.
afex_plot(m1, "Machine", error = "within")
# }
# NOT RUN {
data("fhch2010") # load
fhch <- droplevels(fhch2010[ fhch2010$correct,]) # remove errors
### following model should take less than a minute to fit:
mrt <- mixed(log_rt ~ task*stimulus*frequency + (stimulus*frequency||id)+
(task||item), fhch, method = "S", expand_re = TRUE)
## way too many points in background:
afex_plot(mrt, "stimulus", "frequency", "task")
## better to restrict plot of data to one random-effects grouping variable
afex_plot(mrt, "stimulus", "frequency", "task", random = "id")
## when plotting data from a single random effect, different error bars are possible:
afex_plot(mrt, "stimulus", "frequency", "task", random = "id", error = "within")
afex_plot(mrt, "stimulus", "frequency", "task", random = "id", error = "mean")
## compare visual impression with:
pairs(emmeans::emmeans(mrt, c("stimulus", "frequency"), by = "task"))
## same logic also possible for other random-effects grouping factor
afex_plot(mrt, "stimulus", "frequency", "task", random = "item")
## within-item error bars are misleading here. task is sole within-items factor.
afex_plot(mrt, "stimulus", "frequency", "task", random = "item", error = "within")
## CIs based on stanard error of mean look small, but not unreasonable given results.
afex_plot(mrt, "stimulus", "frequency", "task", random = "item", error = "mean")
### compare distribution of individual data for different random effects:
## requires package cowplot
p_id <- afex_plot(mrt, "stimulus", "frequency", "task", random = "id",
error = "within", dodge = 0.7,
data_geom = ggplot2::geom_violin,
mapping = c("shape", "fill"),
data_arg = list(width = 0.7)) +
ggplot2::scale_shape_manual(values = c(4, 17)) +
ggplot2::labs(title = "ID")
p_item <- afex_plot(mrt, "stimulus", "frequency", "task", random = "item",
error = "within", dodge = 0.7,
data_geom = ggplot2::geom_violin,
mapping = c("shape", "fill"),
data_arg = list(width = 0.7)) +
ggplot2::scale_shape_manual(values = c(4, 17)) +
ggplot2::labs(title = "Item")
### see: https://cran.r-project.org/package=cowplot/vignettes/shared_legends.html
p_comb <- cowplot::plot_grid(
p_id + ggplot2::theme_light() + ggplot2::theme(legend.position="none"),
p_item + ggplot2::theme_light() + ggplot2::theme(legend.position="none")
)
legend <- cowplot::get_legend(p_id + ggplot2::theme(legend.position="bottom"))
cowplot::plot_grid(p_comb, legend,
ncol = 1,
rel_heights = c(1, 0.1))
##----------------------------------------------------------------
## Support for lme4::lmer -
##----------------------------------------------------------------
Oats <- nlme::Oats
## afex_plot does currently not support implicit nesting: (1|Block/Variety)
## Instead, we need to create the factor explicitly
Oats$VarBlock <- Oats$Variety:Oats$Block
Oats.lmer <- lmer(yield ~ Variety * factor(nitro) + (1|VarBlock) + (1|Block),
data = Oats)
afex_plot(Oats.lmer, "nitro", "Variety")
afex_plot(Oats.lmer, "nitro", panel = "Variety")
# }
```

*Documentation reproduced from package afex, version 0.22-1, License: GPL (>= 2)*