API Reference

Index

Types

AnovaFun.AnovaResultType
AnovaResult

Results from an ANOVA analysis.

Fields

  • data::DataFrame: Original data used for analysis (in long format)
  • dv::Symbol: Dependent variable column name
  • id::Symbol: Subject/participant identifier column name
  • table::DataFrame: ANOVA table with test statistics. Columns include: Effect, DFn, DFd, SSn, SSd, MSE, F, p, sig, and optionally ε (epsilon), η², η²ₚ, ω²
  • design::DesignInfo: Design metadata containing type (:between, :within, or :mixed), factors, and number of subjects
  • model: Fitted linear model (GLM.TableRegressionModel) for diagnostics. Use model(result) to access GLM functions like residuals(), fitted(), coef(), etc.

Accessor Functions

Use these functions to extract information from an AnovaResult:

  • factors(result): Get all factors (between and within)
  • between_factors(result): Get between-subjects factors
  • within_factors(result): Get within-subjects factors
  • n_id(result): Get number of subjects
  • n_effects(result): Get number of effects (excluding Intercept)
  • design_type(result): Get design type (:between, :within, or :mixed)
  • model(result): Get fitted model

Access data directly using fields:

  • result.data: Get original data
  • result.dv: Get dependent variable name
  • result.id: Get subject identifier name

Examples

result = anova(data, :dv, :id, within=[:time])
result.table  # Access ANOVA table
factors(result)  # Get all factors
design_type(result)  # Get design type
source
AnovaFun.AxisKwargsType

Axis customization (prefix: axis_). Known custom fields are struct fields; all other axis_* kwargs go to makie_attrs and are forwarded directly to Makie.Axis().

source
AnovaFun.DesignInfoType
DesignInfo

Stores info about the ANOVA design.

Fields

  • type::Symbol: Design type. Options: :between (between-subjects only), :within (within-subjects/repeated measures only), or :mixed (combination of both)
  • between_factors::Vector{Symbol}: Vector of between-subjects factor names
  • within_factors::Vector{Symbol}: Vector of within-subjects (repeated measures) factor names
  • n_id::Int: Number of unique subjects/participants in the design

Examples

result = anova(data, :dv, :id, between=[:group])
design_type(result)     # Returns :between
between_factors(result) # Returns [:group]
within_factors(result)  # Returns []
n_id(result)            # Returns number of subjects
source
AnovaFun.EmmeansResultType
EmmeansResult

Results from estimated marginal means computation.

Fields

  • means::DataFrame: Marginal means table with columns:
    • Effect: Name of the effect (e.g., "time", "time × condition")
    • Level: Level combination (e.g., "T1" or "T1, Condition1")
    • N: Number of subjects contributing to this mean
    • Mean: Estimated marginal mean
    • SD: Standard deviation
    • SE: Standard error of the mean
    • Lower: Lower bound of confidence interval
    • Upper: Upper bound of confidence interval
  • anova::AnovaResult: The original ANOVA result object used to compute the means
  • level::Float64: Confidence level used for intervals (e.g., 0.95 for 95% CI)
  • group::Union{Vector{Symbol}, Nothing}: Grouping factors (if specified via group parameter)

Note: The original data can be accessed via result.anova.data.

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
em.means  # Access marginal means table
em.level  # Get confidence level (e.g., 0.95)
em.anova  # Access original ANOVA result
em = emmeans(result, by=[:time, :condition], group=:condition)  # Grouped display
source
AnovaFun.FacetContextType

Facet context bundling common parameters for plot functions. Dramatically reduces parameter lists from 8+ params down to 3-4.

source
AnovaFun.FigureKwargsType

Figure customization (prefix: figure_). Known custom fields are struct fields; all other figure_* kwargs go to makie_attrs.

source
AnovaFun.LegendKwargsType

Legend customization (prefix: legend_). Known custom fields are struct fields; all other legend_* kwargs go to makie_attrs. The top-level legend=false kwarg maps to show=false.

source
AnovaFun.PairwiseResultType
PairwiseResult

Results from pairwise comparisons computation.

Fields

  • table::DataFrame: Pairwise comparisons table with columns:
    • Effect: Name of the effect being compared
    • Contrast: Description of the comparison (e.g., "Level1 - Level2")
    • Estimate: Mean difference
    • SE: Standard error of the difference
    • df: Degrees of freedom
    • t: t-statistic
    • p: Unadjusted p-value
    • p_adj: Adjusted p-value (if adjustment method specified)
    • Lower: Lower bound of confidence interval
    • Upper: Upper bound of confidence interval

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
pw = pairwise(em)
pw.table  # Access pairwise comparisons table
source
AnovaFun.PlotConfigType
PlotConfig

Bundle of all typed kwarg structs for the AnovaFun plotting system. Construct from flat kwargs via PlotConfig(; violin_color=:red, axis_ylabel="Y", ...).

source
AnovaFun.PlotConfigMethod
PlotConfig(; kwargs...)

Construct a PlotConfig from flat keyword arguments. Kwargs are routed to the appropriate struct by prefix (e.g., violin_colorViolinKwargs.color).

Throws ArgumentError for unrecognized kwargs (catches typos like violin_colr).

source
AnovaFun.PowerResultType
PowerResult

Results from a power analysis.

Fields

  • power::DataFrame: Power estimates for each effect with columns: n, Effect, Power, EffectSize
  • pairwise::Union{DataFrame, Nothing}: Power and effect sizes for pairwise comparisons (columns: Comparison, n, power, effect_size)
  • between::Union{Dict{Symbol, Vector{String}}, Nothing}: Between-subjects factors and their levels
  • within::Union{Dict{Symbol, Vector{String}}, Nothing}: Within-subjects factors and their levels
  • n_sims::Union{Int, Nothing}: Number of simulations (if simulation method)
  • alpha::Float64: Significance level used

Examples

using AnovaFun
result = power_analysis(40,
                        between=Dict(:voice => [:human, :robot]),
                        within=Dict(:emotion => [:cheerful, :sad]),
                        mu=[1.03, 1.41, 0.98, 1.01],
                        sd=1.03,
                        r=0.8)
result.power        # Access power estimates and effect sizes DataFrame
result.power.n      # Access sample size from the DataFrame
result.between      # Access between-subjects factors
result.within       # Access within-subjects factors
source
AnovaFun.RaincloudKwargsType

Raincloud plot customization (prefix: raincloud_). Fields prefixed with x2x2_ map to user kwargs raincloud_2x2_*.

source
AnovaFun.SampleSizeResultType
SampleSizeResult

Results from a sample size calculation.

Fields

  • power::DataFrame: Power estimates for each effect at the recommended sample size (columns: n, Effect, Power, EffectSize)
  • results::DataFrame: DataFrame with columns n and one column per effect/interaction showing power values for each tested sample size

Examples

result = sample_size(80,
                     within=Dict(:factor1 => [1, 2], :factor2 => [1, 2]),
                     mu=[1.0, 1.0, 1.0, 2.0],
                     sd=1.0,
                     r=0.5)
result.power        # Recommended sample size and power for each effect
result.results      # Power for all tested sample sizes
source

Functions

AnovaFun.aggregateMethod
aggregate(data, dv, id, within, between)

Aggregate data to cell means per subject and condition combination. This collapses the data to one value per subject × condition for ANOVA calculations.

Arguments

  • data::AbstractDataFrame: Input data
  • dv::Symbol: Dependent variable name
  • id::Symbol: Subject identifier name
  • within::Union{AbstractVector{Symbol}, Nothing}: Within-subjects factors
  • between::Union{AbstractVector{Symbol}, Nothing}: Between-subjects factors

Returns

  • DataFrame: Aggregated data with one row per subject × condition combination
source
AnovaFun.all_factorsMethod
all_factors(design::DesignInfo)
all_factors(result::AnovaResult)

Get all factors in canonical order (between factors first, then within factors).

Arguments

  • design::DesignInfo: Design information
  • result::AnovaResult: ANOVA result object (convenience overload, equivalent to factors(result))

Returns

A Vector{Symbol} containing all factors in order: between factors followed by within factors.

source
AnovaFun.anovaMethod
anova(data, dv, id; within=nothing, between=nothing, correction=:none, effect_size=:pes)

Perform ANOVA on factorial designs including repeated measures (within-subjects), between-subjects, and mixed designs.

Arguments

  • data::AbstractDataFrame: DataFrame containing the data in long format (one row per observation)
  • dv::Symbol: Symbol naming the dependent variable column
  • id::Symbol: Symbol naming the subject/participant identifier column
  • within::Union{AbstractVector{Symbol}, Nothing}: Vector of Symbols naming within-subjects (repeated measures) factors (default: nothing)
  • between::Union{AbstractVector{Symbol}, Nothing}: Vector of Symbols naming between-subjects factors (default: nothing)
  • correction::Symbol: Sphericity correction type for within-subjects effects. Options: :none (default), :GG (Greenhouse-Geisser), or :HF (Huynh-Feldt). When not :none, adds ε (epsilon) column and adjusts degrees of freedom and p-values in the ANOVA table.
  • effect_size::Symbol: Effect size to include. Options: :none (no effect sizes), :es (eta squared, η²), :pes (partial eta squared, η²ₚ, default), :os (omega squared, ω²)

Returns

An AnovaResult object containing:

  • table::DataFrame: ANOVA table with columns: Effect, DFn, DFd, SSn, SSd, MSE, F, p, sig, and optionally ε (epsilon), η², η²ₚ, ω²
  • design::DesignInfo: Design metadata (type: :between, :within, or :mixed, factors, number of subjects)
  • model: Fitted linear model (GLM.TableRegressionModel) for diagnostics (residuals, fitted values, coefficients, etc.)
  • data::DataFrame: Original data used for analysis
  • dv::Symbol: Dependent variable name
  • id::Symbol: Subject identifier name

Examples

# Between-subjects ANOVA
result = anova(data, :dv, :id, between=[:group])

# Within-subjects (repeated measures) ANOVA
result = anova(data, :dv, :id, within=[:time])

# With Greenhouse-Geisser correction for sphericity
result = anova(data, :dv, :id, within=[:time], correction=:GG)

# Mixed design
result = anova(data, :dv, :id, between=[:group], within=[:time])

# With omega squared effect size
result = anova(data, :dv, :id, within=[:time], effect_size=:os)

Notes

  • Data must be in long format with one row per observation
  • At least one factor (within or between) must be specified
  • For within-subjects designs, sphericity correction is recommended when factors have more than 2 levels
source
AnovaFun.anova_tableMethod
anova_table(result::AnovaResult; backend=:text, include_intercept=false, include_ss=false, include_mse=false, include_es=true, include_sig=true, title="ANOVA Table", io=stdout)

Print an ANOVA table using PrettyTables.

Arguments

  • result::AnovaResult: An AnovaResult object
  • backend::Symbol: Output format. Options: :markdown, :latex, :text (default: :text)
  • include_intercept::Bool: Whether to include the Intercept row (default: false)
  • include_ss::Bool: Whether to include sum of squares columns (default: false)
  • include_mse::Bool: Whether to include MSE column (default: false)
  • include_es::Bool: Whether to include effect size columns (default: true)
  • include_sig::Bool: Whether to include significance column (default: true)
  • title::String: Table title (default: "ANOVA Table")
  • io::IO: Output stream (default: stdout)

Returns

Nothing (prints to io)

Examples

result = anova(data, :dv, :id, within=[:time])
anova_table(result, backend=:markdown)
anova_table(result, backend=:latex)
anova_table(result, backend=:text)

# Minimal table
anova_table(result, include_ss=false, include_mse=false, include_es=false)
source
AnovaFun.between_factorsMethod
between_factors(result::AnovaResult)

Get between-subjects factors.

Arguments

  • result::AnovaResult: ANOVA result object

Returns

A Vector{Symbol} containing between-subjects factor names.

Examples

result = anova(data, :dv, :id, between=[:group])
between_factors(result)  # Returns [:group]
source
AnovaFun.check_homogeneityMethod
check_homogeneity(result::AnovaResult; center::Function=mean)

Levene's test for homogeneity of variance (equal variances across groups).

For between-subjects designs, tests whether variances are equal across groups defined by between-subjects factors. For mixed designs, tests are performed on the between-subjects grouping factors.

Arguments

  • result::AnovaResult: ANOVA result object
  • center::Function: Centering function: mean or median

Returns

An AnovaResult object (same as anova()), containing:

  • table: ANOVA table with test statistics
  • design: Design information
  • model: Fitted linear model
  • Other accessor methods (see anova() documentation)

The main effect in the table (group) tests variance homogeneity across all group combinations.

Examples

result = anova(data, :dv, :subject, between=[:group])
check_homogeneity(result)  
source
AnovaFun.ciMethod
ci(lower::Real, upper::Real; format::Symbol=:markdown)
ci(result::EmmeansResult, effect::String, level::String; format::Symbol=:markdown)

Format confidence interval string according to APA style.

Arguments

  • lower::Real: Lower bound of the confidence interval (for direct call)
  • upper::Real: Upper bound of the confidence interval (for direct call)
  • result::EmmeansResult: Emmeans result object (for method with result)
  • effect::String: Name of the effect (for method with result)
  • level::String: Level of the effect (for method with result)
  • format::Symbol: Output format. Options: :markdown (default), :latex, :text

Returns

A formatted string with the confidence interval (e.g., "95% CI [20.15, 30.71]" in markdown format).

Examples

ci(20.15, 30.71)  # Returns "*95% CI* [20.15, 30.71]"

# From emmeans result
result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
ci(em, "time", "T1")  # Returns "*95% CI* [20.15, 30.71]"
source
AnovaFun.design_typeMethod
design_type(result::AnovaResult)

Get the design type.

Arguments

  • result::AnovaResult: ANOVA result object

Returns

A Symbol indicating the design type: :between, :within, or :mixed.

Examples

result = anova(data, :dv, :id, between=[:group])
design_type(result)  # Returns :between

result = anova(data, :dv, :id, within=[:time])
design_type(result)  # Returns :within

result = anova(data, :dv, :id, between=[:group], within=[:time])
design_type(result)  # Returns :mixed
source
AnovaFun.emmeansMethod
emmeans(result::AnovaResult; by=nothing, group=nothing, level=0.95, adjust=:none)

Compute estimated marginal means from an ANOVA result. This method uses the data stored in the result object.

Arguments

  • result::AnovaResult: An AnovaResult object from anova()
  • by::Union{Symbol, Vector{Symbol}, Nothing}: Effect(s) to compute marginal means for.
    • nothing (default): Compute marginal means for all effects (all factors and their interactions)
    • Symbol: Compute marginal means for a single factor (e.g., :time)
    • Vector{Symbol}: Compute marginal means for an interaction (e.g., [:time, :condition])
  • group::Union{Symbol, Vector{Symbol}, Nothing}: Factor(s) to group results by for display.
    • nothing (default): Show all results in a single table
    • Symbol or Vector{Symbol}: Group results by these factors (must be a subset of by factors)
    • When group is specified, results are displayed in separate sections for each group combination
  • level::Float64: Confidence level for confidence intervals (default: 0.95 for 95% CI)
  • adjust::Symbol: Method for confidence interval adjustment. Options: :none (default), :bonferroni, or :sidak

Returns

An EmmeansResult object containing:

  • means::DataFrame: Marginal means table with columns Effect, Level, N, Mean, SD, SE, Lower, Upper
  • anova::AnovaResult: The original ANOVA result object
  • level::Float64: Confidence level used for intervals
  • group::Union{Vector{Symbol}, Nothing}: Grouping factors (if specified)

Note: The original data can be accessed via result.anova.data.

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)                               # all effects
em = emmeans(result, by=:time)                     # single factor
em = emmeans(result, by=[:time, :condition])       # interaction
em = emmeans(result, by=[:time, :condition], group=:condition)  # grouped by condition
em = emmeans(result, by=:time, adjust=:bonferroni) # with correction
source
AnovaFun.emmeans_tableMethod
emmeans_table(result::EmmeansResult; backend=:text, title="Estimated Marginal Means", io=stdout)

Print an estimated marginal means table using PrettyTables.

Arguments

  • result::EmmeansResult: An EmmeansResult object
  • backend::Symbol: Output format. Options: :markdown, :latex, :text (default: :text)
  • title::String: Table title (default: "Estimated Marginal Means")
  • io::IO: Output stream (default: stdout)

Returns

Nothing (prints to io)

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
emmeans_table(em, backend=:markdown)
emmeans_table(em, backend=:latex)
emmeans_table(em, backend=:text)
source
AnovaFun.errorbar_limits!Method
errorbar_limits!(result, errorbars)

Add error bar distances from mean to the EmmeansResult (mutating).

Adds an error column to result.means with the symmetrical distance from the mean (error bars extend Mean ± error).

Arguments

  • result::EmmeansResult: The emmeans result (will be mutated)
  • errorbars::Symbol: Error bar type (:none, :SE, :CI, :withinSE, :withinCI)

Returns

  • nothing (mutates result.means in place)
source
AnovaFun.fMethod
f(result::AnovaResult, effect::String; format::Symbol=:markdown)

Format F-statistic string according to APA style.

source
AnovaFun.factorsMethod
factors(result::AnovaResult)

Get all factors in the design (both between and within).

Arguments

  • result::AnovaResult: ANOVA result object

Returns

A Vector{Symbol} containing all factor names (between-subjects and within-subjects combined).

Examples

result = anova(data, :dv, :id, between=[:group], within=[:time])
factors(result)  # Returns [:group, :time]
source
AnovaFun.fstatMethod
fstat(result::AnovaResult, effect::String; format::Symbol=:markdown)

Return full APA formatted statistics string for an ANOVA effect.

Combines F-statistic, p-value, effect size, and sphericity correction (if applicable) into a single formatted string.

Arguments

  • result::AnovaResult: ANOVA result object
  • effect::String: Name of the effect from the ANOVA table
  • format::Symbol: Output format. Options: :markdown (default), :latex, :text

Returns

A formatted string containing F-statistic, p-value, effect size, and sphericity correction (if applicable), separated by commas.

Examples

result = anova(data, :dv, :subject, within=[:time], correction=:GG)
fstat(result, "time", format=:markdown)
# Returns: "*F*(2, 18) = 5.43, *p* = .012, *η²ₚ* = 0.38, *ε* = 0.85" (example)
source
AnovaFun.independent_ttestMethod
independent_ttest(x::AbstractVector, y::AbstractVector; tail::Symbol = :both)

Compute independent sample t-test with degrees of freedom, t-statistic, and p-value. Assumes equal variances (standard independent t-test). Also returns Cohen's d (reported as d).

Arguments

  • x::AbstractVector: First group data (must have at least 2 observations)
  • y::AbstractVector: Second group data (must have at least 2 observations)
  • tail::Symbol: Type of test - :both (two-tailed, default), :left (one-tailed, A < B), or :right (one-tailed, A > B)

Returns

  • Named tuple with fields:
    • df: degrees of freedom
    • t: t-statistic
    • p: p-value (returns NaN if t is NaN/Inf)
    • d: Cohen's d using pooled SD
source
AnovaFun.independent_ttestMethod
independent_ttest(df::DataFrame, col::Symbol; by::Symbol, levels = nothing, tail::Symbol = :both)

Convenience method for independent t-test from a DataFrame.

Splits df by the by column into exactly two groups and runs an independent t-test on the values in col.

Arguments

  • df::DataFrame: DataFrame containing the data
  • col::Symbol: Column to test
  • by::Symbol: Grouping column (must have exactly 2 unique values, or use levels)
  • levels: Optional vector of 2 values to select from by column (useful when >2 groups exist)
  • tail::Symbol: Type of test (:both, :left, or :right)

Examples

# Auto-detect two groups
independent_ttest(df, :dv_col, by = :grouping_col)

# Specify which two groups to compare
independent_ttest(df, :dv_col, by = :grouping_col, levels = [1, 2])
source
AnovaFun.mMethod
m(result::EmmeansResult, effect::String, level::String; unit::String="", format::Symbol=:markdown)

Format marginal mean string according to APA style.

Arguments

  • result::EmmeansResult: Emmeans result object
  • effect::String: Name of the effect
  • level::String: Level of the effect (e.g., "Level1" or "Level1, Level2" for interactions)
  • unit::String: Optional unit to append to the mean value (default: "")
  • format::Symbol: Output format. Options: :markdown (default), :latex, :text

Returns

A formatted string with the mean value (e.g., "M = 25.43" in markdown format).

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
m(em, "time", "T1")             # Returns "*M* = 25.43"
m(em, "time", "T1", unit="ms")  # Returns "*M* = 25.43 ms"
source
AnovaFun.m_ciMethod
m_ci(result::EmmeansResult, effect::String, level::String; unit::String="", format::Symbol=:markdown)

Format marginal mean with confidence interval string according to APA style.

This is a convenience function that combines m() and ci() into a single formatted string.

Arguments

  • result::EmmeansResult: Emmeans result object
  • effect::String: Name of the effect
  • level::String: Level of the effect (e.g., "Level1" or "Level1, Level2" for interactions)
  • unit::String: Optional unit to append to the mean value (default: "")
  • format::Symbol: Output format. Options: :markdown (default), :latex, :text

Returns

A formatted string combining mean and confidence interval (e.g., "M = 25.43, 95% CI [20.15, 30.71]" in markdown format).

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
m_ci(em, "time", "T1")  # Returns "*M* = 25.43, *95% CI* [20.15, 30.71]" 
source
AnovaFun.modelMethod
model(result::AnovaResult)

Get the fitted linear model (always available).

Use this to access GLM functionality directly, e.g.:

  • GLM.residuals(model(result))
  • GLM.fitted(model(result))
  • GLM.coef(model(result))
  • GLM.vcov(model(result))
  • GLM.stderror(model(result))
  • GLM.r2(model(result))
  • GLM.adjr2(model(result))
source
AnovaFun.n_effectsMethod
n_effects(result::AnovaResult)

Get number of effects in the ANOVA table (excluding Intercept).

Arguments

  • result::AnovaResult: ANOVA result object

Returns

An Int representing the number of effects (main effects and interactions, excluding Intercept).

Examples

result = anova(data, :dv, :id, between=[:group], within=[:time])
n_effects(result)  # Returns number of effects (e.g., 3 for group, time, group×time)
source
AnovaFun.n_idMethod
n_id(result::AnovaResult)

Get number of subjects/participants in the design.

Arguments

  • result::AnovaResult: ANOVA result object

Returns

An Int representing the number of unique subjects.

Examples

result = anova(data, :dv, :id, within=[:time])
n_id(result)  # Returns number of subjects (e.g., 20)
source
AnovaFun.pMethod
p(p::Real; format::Symbol=:markdown)
p(result::AnovaResult, effect::String; format::Symbol=:markdown)

Format a p-value string according to APA style. Supported formats: :markdown, :latex, :text.

source
AnovaFun.paired_ttestMethod
paired_ttest(x::AbstractVector, y::AbstractVector; tail::Symbol = :both)

Compute paired t-test with degrees of freedom, t-statistic, and p-value. Also returns Cohen's dz (reported as dz).

Arguments

  • x::AbstractVector: First condition data (must have same length as y)
  • y::AbstractVector: Second condition data (must have same length as x)
  • tail::Symbol: Type of test - :both (two-tailed, default), :left (one-tailed, A < B), or :right (one-tailed, A > B)

Returns

  • Named tuple with fields:
    • df: degrees of freedom
    • t: t-statistic
    • p: p-value (returns NaN if t is NaN/Inf)
    • dz: Cohen's dz computed as mean(diff) / std(diff)
source
AnovaFun.paired_ttestMethod
paired_ttest(df::DataFrame, col::Symbol; by::Symbol, levels = nothing, tail::Symbol = :both)

Convenience method for paired t-test from a DataFrame.

Splits df by the by column into exactly two groups and runs a paired t-test on the values in col.

Arguments

  • df::DataFrame: DataFrame containing the data
  • col::Symbol: Column to test
  • by::Symbol: Grouping column (must have exactly 2 unique values, or use levels)
  • levels: Optional vector of 2 values to select from by column (useful when >2 groups exist)
  • tail::Symbol: Type of test (:both, :left, or :right)

Examples

# Auto-detect two groups
paired_ttest(df, :dv_col, by = :grouping_col)

# Specify which two groups to compare
paired_ttest(df, :dv_col, by = :grouping_col, levels = [1, 2])
source
AnovaFun.pairwiseMethod
pairwise(emmeans_result::EmmeansResult; simple=nothing, adjust=:none)

Compute pairwise comparisons from an emmeans result. Matches R's pairs() function from the emmeans package.

Arguments

  • emmeans_result::EmmeansResult: EmmeansResult object from emmeans()
  • simple::Union{Symbol, Nothing}: Simple contrasts specification (default: nothing):
    • nothing: All pairwise comparisons across all cell means (like R's pairs(em))
    • :each: Simple contrasts for each factor within levels of other factors
    • :FactorName: Simple contrasts for specified factor within levels of other factors
  • adjust::Symbol: Method for p-value and confidence interval adjustment. Options: :none (default), :bonferroni, or :sidak

Returns

A PairwiseResult object containing:

  • table::DataFrame: Pairwise comparison results with columns:
    • Context: Conditioning context (e.g., "CurrentCongruency = Congruent") for simple contrasts
    • Effect: Name of the effect being compared
    • Contrast: Description of the comparison (e.g., "Level1 - Level2")
    • Estimate: Mean difference
    • SE: Standard error of the difference
    • df: Degrees of freedom
    • t: t-statistic
    • p: Unadjusted p-value
    • p_adj: Adjusted p-value (if adjustment method specified)
    • Lower: Lower bound of confidence interval
    • Upper: Upper bound of confidence interval

The confidence level is taken from emmeans_result.level.

Examples

result = anova(data, :dv, :id, within=[:A, :B])
em = emmeans(result, by=[:A, :B])

# All pairwise comparisons across all cell means
pw = pairwise(em)

# Simple contrasts for factor A within levels of B
pw = pairwise(em, simple=:A)

# Simple contrasts for each factor
pw = pairwise(em, simple=:each)

# With p-value correction
pw = pairwise(em, adjust=:bonferroni)
source
AnovaFun.pairwise_tableMethod
pairwise_table(result::PairwiseResult; backend=:text, title="Pairwise Comparisons", io=stdout)

Print a pairwise comparisons table using PrettyTables.

Arguments

  • result::PairwiseResult: A PairwiseResult object
  • backend::Symbol: Output format. Options: :markdown, :latex, :text (default: :text)
  • title::String: Table title (default: "Pairwise Comparisons")
  • io::IO: Output stream (default: stdout)

Returns

Nothing (prints to io)

Examples

result = anova(data, :dv, :id, within=[:time])
em = emmeans(result)
pw = pairwise(em)
pairwise_table(pw, backend=:markdown)
source
AnovaFun.plot_anova!Method
plot_anova!(position, result; x_grouping, y_grouping=nothing, ...)

Mutating variant of plot_anova that renders into an existing figure position, enabling multiple plots to be combined in a single Figure.

Arguments

  • position: A grid position in an existing figure, e.g. fig[1, 1] or fig[1, 2]
  • All remaining arguments are identical to plot_anova

Returns

The parent Figure (already provided by the caller, returned for convenience).

Examples

fig = Figure(size = (1600, 700))
plot_anova!(fig[1, 1], result_rt, x_grouping=:pola, y_grouping=:comp,
            plot_type=:raincloud_custom_2x2, axis_ylabel="RT [ms]")
plot_anova!(fig[1, 2], result_er, x_grouping=:pola, y_grouping=:comp,
            plot_type=:raincloud_custom_2x2, axis_ylabel="Error Rate [%]")
save("combined.png", fig)
source
AnovaFun.plot_sample_sizeMethod
plot_sample_size(result::SampleSizeResult; target_power=nothing, kwargs...)

Plot power curves for sample size analysis.

Shows how power changes with sample size for each effect. Includes a horizontal line at the target power and a vertical line at the recommended N.

Arguments

  • result::SampleSizeResult: Result from sample_size()
  • target_power::Union{Real, Nothing}: Target power level (0-100). If nothing, inferred from minimum power in result
  • figure_size::Tuple{Int,Int}: Figure size in pixels (default: (800, 600))
  • theme::Union{Theme, Nothing}: Makie theme for customization

Returns

A Makie.Figure object that auto-displays in the REPL.

Examples

result = sample_size(80, ...)
plot_sample_size(result)  # Basic plot
source
AnovaFun.power_analysisMethod
power_analysis(n; within=nothing, between=nothing, mu, sd, r=nothing, n_sims=1000, alpha=0.05, pairwise=false)

Perform power analysis for an ANOVA design using simulation.

Arguments

  • n::Int: Number of subjects/participants (positional argument)
    • For between-subjects designs: number of subjects per group
    • For within-subjects designs: total number of subjects
    • For mixed designs: number of subjects per between-subjects group
  • within::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping within-subjects factor names to level labels
  • between::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping between-subjects factor names to level labels
  • mu::Union{Real, Vector{<:Real}}: Cell means. Single value for all cells, or vector (one per cell, matching cell order)
  • sd::Union{Real, Vector{<:Real}}: Standard deviation. Single value for all cells, or vector (one per cell, matching mu order)
  • r::Union{Real, Vector{<:Real}, Nothing}: Correlation for within-subjects factors (default: nothing)
  • n_sims::Int: Number of simulations to run (default: 1000)
  • alpha::Float64: Significance level (default: 0.05)
  • pairwise::Bool: Whether to compute pairwise comparison power (default: false)

Returns

A PowerResult object containing:

  • Power estimates and effect sizes (partial eta-squared) for each ANOVA effect
  • Power and effect sizes (Cohen's d) for pairwise comparisons (all pairwise comparisons across all cell means), if pairwise=true

Examples

# Within-subjects design
result = power_analysis(20, 
                        within=Dict(:factor1 => [1, 2], :factor2 => [1, 2]),
                        mu=[1.1, 1.2, 1.6, 1.8], 
                        sd=1.0, 
                        r=0.5, 
                        n_sims=1000)
result.power  # View power estimates and effect sizes

# Mixed design
result = power_analysis(40,
                        between=Dict(:voice => [:human, :robot]),
                        within=Dict(:emotion => [:cheerful, :sad]),
                        mu=[1.03, 1.41, 0.98, 1.01],
                        sd=1.03,
                        r=0.8)
source
AnovaFun.sample_sizeMethod
sample_size(; target_power=80, within=nothing, between=nothing, mu, sd, r=nothing, method=:binary, n_sims=1000, alpha=0.05, min_n=5, max_n=500, step=1, n_anchors=10)

Estimate the required sample size to achieve a target power level using simulation.

Arguments

  • target_power::Real: Target power level (e.g., 80 for 80% power) on 0-100 scale (default: 80)
  • within::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping within-subjects factor names to level labels
  • between::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping between-subjects factor names to level labels
  • mu::Union{Real, Vector{<:Real}}: Cell means. Single value for all cells, or vector (one per cell, matching cell order)
  • sd::Union{Real, Vector{<:Real}}: Standard deviation. Single value for all cells, or vector (one per cell, matching mu order)
  • r::Union{Real, Vector{<:Real}, Nothing}: Correlation for within-subjects factors (default: nothing)
  • method::Symbol: Search method. Options:
    • :binary (default): Binary search with independent per-effect search and anchor points
    • :sequential: Sequential search from minn to maxn (slower, dense results for plotting)
  • step::Int: Step size for sequential search (default: 1). Use larger values (e.g., 5-10) for faster sequential search
  • n_anchors::Int: Number of evenly-spaced anchor points to test initially (binary method only, default: 10). Higher values give smoother plots but take longer
  • n_sims::Int: Number of simulations per sample size tested (default: 1000)
  • alpha::Float64: Significance level (default: 0.05)
  • min_n::Int: Minimum sample size to test (default: 5)
    • For between-subjects designs: minimum number of subjects per group
    • For within-subjects designs: minimum total number of subjects
    • For mixed designs: minimum number of subjects per between-subjects group
  • max_n::Int: Maximum sample size to test (default: 500)
    • For between-subjects designs: maximum number of subjects per group
    • For within-subjects designs: maximum total number of subjects
    • For mixed designs: maximum number of subjects per between-subjects group

Returns

A SampleSizeResult object containing:

  • power::DataFrame: Power estimates for each effect at the recommended sample size (columns: n, Effect, Power, EffectSize)
    • n represents per-group sample size for between-subjects designs, total sample size for within-subjects designs
  • results::DataFrame: DataFrame with columns n and one column per effect/interaction showing power values for each tested sample size
    • n represents per-group sample size for between-subjects designs, total sample size for within-subjects designs

Examples

# Within-subjects design
result = sample_size(target_power=80,  # 80% power
                     within=Dict(:factor1 => [1, 2], :factor2 => [1, 2]),
                     mu=[1.0, 1.0, 1.0, 2.0], 
                     sd=1.0, 
                     r=0.5, 
                     n_sims=100,
                     method=:binary)

# Sequential search with larger step size (faster, coarser)
result = sample_size(target_power=80,  # 80% power
                     within=Dict(:factor1 => [1, 2], :factor2 => [1, 2]),
                     mu=[1.0, 1.0, 1.0, 2.0], 
                     sd=1.0, 
                     r=0.5,
                     method=:sequential, 
                     min_n=10, 
                     max_n=100,
                     step=5)  # Test every 5th sample size for speed
source
AnovaFun.simulate_dataMethod
simulate_data(n; within=nothing, between=nothing, mu, sd, r=nothing)

Generate a simulated DataFrame with known properties for ANOVA analysis.

This function creates a DataFrame with the specified design structure, means, standard deviations, and correlations. The design is specified using dictionaries mapping factor names to their level labels, making it consistent with the anova function signature.

Arguments

  • n::Int: Number of subjects/participants (positional argument)
    • For between-subjects designs: number of subjects per group
    • For within-subjects designs: total number of subjects
    • For mixed designs: number of subjects per between-subjects group
  • within::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping within-subjects factor names to level labels. Example: Dict(:factor1 => [:a1, :a2], :factor2 => [:b1, :b2])
  • between::Union{Dict{Symbol, Vector}, Nothing}: Dictionary mapping between-subjects factor names to level labels. Example: Dict(:group => [:control, :treatment])
  • mu::Union{Real, Vector{<:Real}}: Cell means in cell order (all combinations of factors)
  • sd::Union{Real, Vector{<:Real}}: Standard deviation. Single value for all cells, or vector (one per cell, matching mu order)
  • r::Union{Real, Vector{<:Real}, Nothing}: Correlation for within-subjects factors (compound symmetry). Default: nothing (uses 0.0)

Returns

A DataFrame with columns in order:

  • id: Subject/participant ID (first column)
  • Factor columns: One column per factor with level labels (middle columns)
  • dv: Dependent variable values (last column)

Examples

# Generate data for a 2×2 within-subjects design
data = simulate_data(20, 
                     within = Dict(:factor1 => [:a1, :a2], :factor2 => [:b1, :b2]),
                     mu = [1.0, 1.0, 1.0, 2.0], 
                     sd = 1.0, 
                     r = 0.5)
source
AnovaFun.sphericityMethod
sphericity(result::AnovaResult, effect::String; format::Symbol=:markdown)

Format sphericity epsilon (ε) string for an effect.

Returns an empty string if the effect does not have sphericity correction applied (ε = 1.0 or missing).

Arguments

  • result::AnovaResult: ANOVA result object
  • effect::String: Name of the effect from the ANOVA table
  • format::Symbol: Output format. Options: :markdown (default), :latex, :text

Returns

A formatted string with the epsilon value, or an empty string if no correction was applied.

Examples

result = anova(data, :dv, :subject, within=[:time], correction=:GG)
sphericity(result, "time", format=:markdown)  # Returns "*ε* = 0.85" (example)
source
AnovaFun.sphericity_checkMethod
sphericity_check(result::AnovaResult)

Mauchly's test for sphericity for within-subjects designs with factor with more than two levels.

Tests whether the assumption of sphericity holds in repeated measures ANOVA. Sphericity requires that the variances of the differences between all pairs of within-subject conditions are equal.

Arguments

  • result::AnovaResult: ANOVA result object

Returns

A DataFrame with columns:

  • Effect: Name of the within-subjects effect
  • W: Mauchly's W statistic
  • p: p-value

Examples

result = anova(data, :dv, :subject, within=[:time])
sphericity_check(result)
source
AnovaFun.sphericity_correctionMethod
sphericity_correction(result::AnovaResult; type::Symbol=:GG)

Apply sphericity correction to an existing ANOVA result.

This function applies Greenhouse-Geisser or Huynh-Feldt correction to within-subjects effects in an ANOVA result. This is useful if you want to apply a different correction method than was used initially, or if you want to apply correction to a result that was computed without it.

Arguments

  • result::AnovaResult: ANOVA result object to apply correction to
  • type::Symbol: Correction type. Options: :GG (Greenhouse-Geisser, default) or :HF (Huynh-Feldt)

Returns

A new AnovaResult object with sphericity correction applied. The correction modifies:

  • ε (epsilon) column: Added or updated with correction factor
  • DFn and DFd: Adjusted by epsilon (may become non-integer)
  • p: Recalculated using corrected degrees of freedom
  • MSE: Recalculated based on corrected DFd

Examples

# Run ANOVA without correction
result = anova(data, :dv, :subject, within=[:time], correction=:none)
result_gg = sphericity_correction(result, type=:GG) # Greenhouse-Geisser correction
result_hf = sphericity_correction(result, type=:HF) # Huynh-Feldt correction

Note

This function requires at least one within-subjects factor. For between-subjects designs, this function will return the result unchanged.

source
AnovaFun.to_dictMethod
to_dict(config::PlotConfig) → Dict{Symbol,Any}

Convert a PlotConfig back to the flat Dict{Symbol,Any} format expected by internal plotting code. Used for backward compatibility during migration.

source
AnovaFun.to_fields_dictMethod
to_fields_dict(obj; exclude=Set{Symbol}())

Convert any kwarg struct to a Dict{Symbol,Any} for splatting into Makie calls. Skips nothing values and the makie_attrs field. Use exclude to skip specific fields.

source
AnovaFun.to_makie_dictMethod
to_makie_dict(a::AxisKwargs)

Convert AxisKwargs to a Dict containing only valid Makie.Axis attributes. Custom fields (xticklabels, xorder, yticks, xlim, ylim) are excluded — they're handled separately.

source
AnovaFun.to_makie_dictMethod
to_makie_dict(f::FigureKwargs)

Convert FigureKwargs to a Dict containing only valid Makie.Figure attributes.

source
AnovaFun.to_makie_dictMethod
to_makie_dict(l::LegendKwargs; exclude_positioning=false)

Convert LegendKwargs to a Dict containing valid Makie.Legend attributes.

source
AnovaFun.tstatMethod
tstat(result; format::Symbol=:markdown)

Return APA-style formatted statistics string for a t-test result.

Accepts a named tuple like the outputs of paired_ttest or independent_ttest, containing:

  • df, t, p, and either dz (paired) or d (independent).

Examples:

res = paired_ttest(x, y)
tstat(res)  # "*t*(4) = -3.92, *p* = .017, dz = 1.75"
source
AnovaFun.validate_anova_inputsMethod
validate_anova_inputs(data, dv, id, within, between, correction, effect_size)

Centralized validation for all ANOVA inputs. Throws informative errors for invalid inputs.

source
AnovaFun.within_correlation_matrixMethod
within_correlation_matrix(data::DataFrame)

Return the within-subjects correlation matrix for a design from a DataFrame (e.g., from simulate_data).

Data must be in long format (with :id, factor columns, and :dv). It will be converted to wide format internally.

Arguments

  • data::DataFrame: DataFrame in long format with :id, factor columns, and :dv

Returns

A DataFrame with cell names as row and column names, containing correlation values.

Examples

data = simulate_data(40, 
                     between=Dict(:voice => [:human, :robot]),
                     within=Dict(:emotion => [:cheerful, :sad]),
                     mu=[1.03, 1.41, 0.98, 1.01], sd=1.03, r=0.8)
corr = within_correlation_matrix(data)
source
AnovaFun.within_factorsMethod
within_factors(result::AnovaResult)

Get within-subjects (repeated measures) factors.

Arguments

  • result::AnovaResult: ANOVA result object

Returns

A Vector{Symbol} containing within-subjects factor names.

Examples

result = anova(data, :dv, :id, within=[:time])
within_factors(result)  # Returns [:time]
source