anova_neat {neatStats} | R Documentation |
Comparison of Multiple Means: ANOVA
Description
Analysis of variance
(ANOVA) F-test
results with appropriate Welch
's and
epsilon corrections where applicable (unless specified otherwise), including
partial eta squared effect sizes with confidence intervals (CIs),
generalized eta squared, and
inclusion Bayes factor based
on matched models
(BFs).
Usage
anova_neat(
data_per_subject,
values,
within_ids = NULL,
between_vars = NULL,
ci = 0.9,
norm_tests = "none",
norm_plots = FALSE,
var_tests = FALSE,
bf_added = FALSE,
bf_sample = 10000,
test_title = "--- neat ANOVA ---",
welch = TRUE,
e_correction = NULL,
type = 2,
white.adjust = FALSE,
hush = FALSE,
plot_means = FALSE,
...
)
Arguments
data_per_subject |
Data frame. Should contain all values (measurements/observations) in a single row per each subject. |
values |
Vector of strings; column name(s) in the |
within_ids |
|
between_vars |
|
ci |
Numeric; confidence level for returned CIs. (Default: |
norm_tests |
Normality tests for the pooled ANOVA residuals
( |
norm_plots |
If |
var_tests |
Logical, |
bf_added |
Logical. If |
bf_sample |
Number of samples used to estimate Bayes factor ( |
test_title |
String, |
welch |
If |
e_correction |
|
type |
Sum of squares type specified as a number: |
white.adjust |
If not |
hush |
Logical. If |
plot_means |
Logical ( |
... |
Any additional arguments will be passed on to
|
Details
The Bayes factor (BF) is always calculated with the default rscaleFixed
of 0.5
("medium"
) and rscaleRandom
of 1
("nuisance"
). BF supporting null hypothesis is denoted as BF01, while
that supporting alternative hypothesis is denoted as BF10. When the BF is
smaller than 1 (i.e., supports null hypothesis), the reciprocal is calculated
(hence, BF10 = BF, but BF01 = 1/BF). When the BF is greater than or equal to
10000, scientific (exponential) form is reported for readability. (The
original full BF number is available in the returned named vector as
bf
.)
Mauchly's sphericity test is returned for repeated measures with more than two
levels. If Mauchly's test is significant, epsilon correction may be applied
(see the e_correction
parameter).
Variance equality tests (if var_tests
is TRUE
): Brown-Forsythe
and Fligner-Killeen tests are performed for each within-subject factor level
(or, in case of several factors, each combination) via
var_tests
. Note that variance testing is generally not
recommended (see e.g., Zimmerman, 2004). In case of a one-way between-subject
ANOVA, Welch-corrected results are reported by default, which corrects for
unequal variances. In case of multiple between-subject factors, the
white.adjust
parameter can be set to TRUE
(or "hc3"
) to
apply "hc3"
correction for unequal variances. In case of a mixed ANOVA
(both between-subject and within-subject factors), if the tests are
significant and the data is unbalanced (unequal group sample sizes), you
should either consider the results respectively or choose a different test.
In case of multiple values (column names) that match identical levels for all factors, the given columns will be merged into a single column taking the mean value of all these columns. (This is to simplify "dropping" a within-subject factor and retesting the remaining factors.) Explicit warning messages are shown in each such case.
Value
Prints ANOVA statistics (including, for each model, F-test with
partial eta squared and its CI, generalized eta squared, and BF, as
specified via the corresponding parameters) in APA style. Furthermore, when
assigned, returns all calculated information details for each effect (as
stat_list
), normality and variance tests (if any), etc.
Note
The F-tests are calculated via ez::ezANOVA
,
including Mauchly's sphericity test. (But Welch's ANOVA is
calculated in case of one-way between-subject designs via
stats::oneway.test
, unless the welch
parameter is set to FALSE
.)
Confidence intervals are calculated, using the F value, via
MBESS::conf.limits.ncf
, converting
noncentrality parameters to partial eta squared as ncp/(ncp+
df_nom+df_denom+1)
(Smithson, 2003).
Generalized eta squared is to facilitate potential subsequent meta-analytical comparisons (see Lakens, 2013).
The inclusion Bayes factor based on matched models is calculated via
bayestestR::bayesfactor_inclusion
,
(with match_models = TRUE
, and using an
BayesFactor::anovaBF
object for
models
input).
References
Girden, E. (1992). ANOVA: Repeated measures. Newbury Park, CA: Sage.
Kelley, K. (2007). Methods for the behavioral, educational, and social sciences: An R package. Behavior Research Methods, 39(4), 979-984. doi:10.3758/BF03192993
Lakens, D. (2013). Calculating and reporting effect sizes to facilitate cumulative science: A practical primer for t-tests and ANOVAs. Frontiers in Psychology, 4. https://doi.org/10.3389/fpsyg.2013.00863
Lakens, D. (2014). Calculating confidence intervals for Cohen's d and eta-squared using SPSS, R, and Stata [Blog post]. Retrieved from http://daniellakens.blogspot.com/2014/06/calculating-confidence-intervals-for.html
Mathot. S. (2017). Bayes like a Baws: Interpreting Bayesian Repeated Measures in JASP [Blog post]. Retrieved from https://www.cogsci.nl/blog/interpreting-bayesian-repeated-measures-in-jasp
McDonald, J. H. 2015. Handbook of Biological Statistics (3rd ed.). Sparky House Publishing, Baltimore, Maryland. Retrieved from http://www.biostathandbook.com
Moder, K. (2010). Alternatives to F-test in one way ANOVA in case of heterogeneity of variances (a simulation study). Psychological Test and Assessment Modeling, 52(4), 343-353.
Navarro, D. (2019). Learning Statistics with R: A Tutorial for Psychology Students and Other Beginners (Version 0.6.1). Retrieved from https://learningstatisticswithr.com/
Smithson, M. (2003). Confidence intervals. Thousand Oaks, Calif: Sage Publications.
Steiger, J. H. (2004). Beyond the F test: effect size confidence intervals and tests of close fit in the analysis of variance and contrast analysis. Psychological Methods, 9(2), 164-182. doi:10.1037/1082-989X.9.2.164
Zimmerman, D. W. (2004). A note on preliminary tests of equality of variances. British Journal of Mathematical and Statistical Psychology, 57(1), 173–181. https://doi.org/10.1348/000711004849222
See Also
Examples
# assign random data in a data frame for illustration
# (note that the 'subject' is only for illustration; since each row contains the
# data of a single subject, no additional subject id is needed)
dat_1 = data.frame(
subject = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
grouping1 = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2),
grouping2 = c(1, 2, 1, 2, 2, 1, 1, 1, 2, 1),
value_1_a = c(36.2, 45.2, 41, 24.6, 30.5, 28.2, 40.9, 45.1, 31, 16.9),
value_2_a = c(-14.1, 58.5, -25.5, 42.2, -13, 4.4, 55.5, -28.5, 25.6, -37.1),
value_1_b = c(83, 71, 111, 70, 92, 75, 110, 111, 110, 85),
value_2_b = c(8.024, -14.162, 3.1, -2.1, -1.5, 0.91, 11.53, 18.37, 0.3, -0.59),
value_1_c = c(27.4,-17.6,-32.7, 0.4, 37.2, 1.7, 18.2, 8.9, 1.9, 0.4),
value_2_c = c(7.7, -0.8, 2.2, 14.1, 22.1, -47.7, -4.8, 8.6, 6.2, 18.2)
)
head(dat_1) # see what we have
# For example, numbers '1' and '2' in the variable names of the values can
# denote sessions in an experiment, such as '_1' for first session, and '_2 for
# second session'. The letters '_a', '_b', '_c' could denote three different
# types of techniques used within each session, to be compared to each other.
# See further below for a more verbose but more meaningful example data.
# get the between-subject effect of 'grouping1'
anova_neat(dat_1, values = 'value_1_a', between_vars = 'grouping1')
# main effects of 'grouping1', 'grouping2', and their interactions
anova_neat(dat_1,
values = 'value_1_a',
between_vars = c('grouping1', 'grouping2'))
# repeated measures:
# get the within-subject effect for 'value_1_a' vs. 'value_1_b'
anova_neat(dat_1, values = c('value_1_a', 'value_1_b'))
# same, but give the factor a custom variable name, and omit BF for speed
anova_neat(
dat_1,
values = c('value_1_a', 'value_1_b'),
within_ids = 'a_vs_b',
bf_added = FALSE
)
# or
anova_neat(
dat_1,
values = c('value_1_a', 'value_1_b'),
within_ids = 'letters',
bf_added = FALSE
)
# within-subject effect for 'value_1_a' vs. 'value_1_b' vs. 'value_1_c'
anova_neat(
dat_1,
values = c('value_1_a', 'value_1_b', 'value_1_c'),
bf_added = FALSE
)
# within-subject main effect for 'value_1_a' vs. 'value_1_b' vs. 'value_1_c',
# between-subject main effect 'grouping1', and the interaction of these two main
# effects
anova_neat(
dat_1,
values = c('value_1_a', 'value_1_b', 'value_1_c'),
between_vars = 'grouping1',
bf_added = FALSE
)
# within-subject 'number' main effect for variables with number '1' vs. number
# '2' ('value_1_a' and 'value_1_b' vs. 'value_2_a' and 'value_2_b'), 'letter'
# main effect for variables with final letterr 'a' vs. final letter 'b'
# ('value_1_a' and 'value_2_a' vs. 'value_1_b' and 'value_2_b'), and the
# 'letter' x 'number' interaction
anova_neat(
dat_1,
values = c('value_1_a', 'value_2_a', 'value_1_b', 'value_2_b'),
within_ids = list(
letters = c('_a', '_b'),
numbers = c('_1', '_2')
),
bf_added = FALSE
)
# same as above, but now including between-subject main effect 'grouping2' and
# its interactions
anova_neat(
dat_1,
values = c('value_1_a', 'value_2_a', 'value_1_b', 'value_2_b'),
within_ids = list(
letters = c('_a', '_b'),
numbers = c('_1', '_2')
),
between_vars = 'grouping2',
bf_added = FALSE
)
# same as above, but now creating a plot of means
# y_title passed add an example title (label) for the Y axis
anova_neat(
dat_1,
values = c('value_1_a', 'value_2_a', 'value_1_b', 'value_2_b'),
within_ids = list(
letters = c('_a', '_b'),
numbers = c('_1', '_2')
),
between_vars = 'grouping2',
bf_added = FALSE,
plot_means = TRUE,
y_title = 'Example Y Title'
)
# same as above, but collapsing means over the removed "numbers" factor
anova_neat(
dat_1,
values = c('value_1_a', 'value_2_a', 'value_1_b', 'value_2_b'),
within_ids = list(
letters = c('_a', '_b')
),
between_vars = 'grouping2',
bf_added = FALSE,
plot_means = TRUE,
y_title = 'Example Y Title'
)
# In real datasets, these could of course be more meaningful. For example, let's
# say participants rated the attractiveness of pictures with low or high levels
# of frightening and low or high levels of disgusting qualities. So there are
# four types of ratings:
# 'low disgusting, low frightening' pictures
# 'low disgusting, high frightening' pictures
# 'high disgusting, low frightening' pictures
# 'high disgusting, high frightening' pictures
# this could be meaningfully assigned e.g. as below
pic_ratings = data.frame(
subject = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
rating_fright_low_disgust_low = c(36.2,45.2,41,24.6,30.5,28.2,40.9,45.1,31,16.9),
rating_fright_high_disgust_low = c(-14.1,58.5,-25.5,42.2,-13,4.4,55.5,-28.5,25.6,-37.1),
rating_fright_low_disgust_high = c(83,71,111,70,92,75,110,111,110,85),
rating_fright_high_disgust_high = c(8.024,-14.162,3.1,-2.1,-1.5,0.91,11.53,18.37,0.3,-0.59)
)
head(pic_ratings) # see what we have
# the same logic applies as for the examples above, but now the
# within-subject differences can be more meaningfully specified, e.g.
# 'disgust_low' vs. 'disgust_high' for levels of disgustingness, while
# 'fright_low' vs. 'fright_high' for levels of frighteningness
anova_neat(
pic_ratings,
values = c(
'rating_fright_low_disgust_low',
'rating_fright_high_disgust_low',
'rating_fright_low_disgust_high',
'rating_fright_high_disgust_high'
),
within_ids = list(
disgustingness = c('disgust_low', 'disgust_high'),
frighteningness = c('fright_low', 'fright_high')
),
bf_added = FALSE
)
# the results are the same as for the analogous test for the 'dat_1' data, only
# with different names
# now let's say the ratings were done in two separate groups
pic_ratings = data.frame(
subject = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
group_id = c(1, 2, 1, 2, 2, 1, 1, 1, 2, 1),
rating_fright_low_disgust_low = c(36.2,45.2,41,24.6,30.5,28.2,40.9,45.1,31,16.9),
rating_fright_high_disgust_low = c(-14.1,58.5,-25.5,42.2,-13,4.4,55.5,-28.5,25.6,-37.1),
rating_fright_low_disgust_high = c(83,71,111,70,92,75,110,111,110,85),
rating_fright_high_disgust_high = c(8.024,-14.162,3.1,-2.1,-1.5,0.91,11.53,18.37,0.3,-0.59)
)
# now test the effect and interactions of 'group_id'
anova_neat(
pic_ratings,
values = c(
'rating_fright_low_disgust_low',
'rating_fright_high_disgust_low',
'rating_fright_low_disgust_high',
'rating_fright_high_disgust_high'
),
within_ids = list(
disgustingness = c('disgust_low', 'disgust_high'),
frighteningness = c('fright_low', 'fright_high')
),
between_vars = 'group_id',
bf_added = FALSE
)
# again, same results as with 'dat_1' (using 'grouping2' as group_id)