Skip to content

ANOVA1S

Description

ANOVA1S performs one-factor analysis of variance using group statistics as inputs. The intent and output of the function are exactly the same as ANOVA; it is just the nature of the inputs that is different.

Syntax

ANOVA1S(n_i, xbar_i, s_i, [sb_stats]) where

  • n_i is a row or column vector of replicate counts for each group
  • xbar_i is a row or column vector of group means
  • s_i is a row or column vector of group standard deviations
  • sb_stats is an optional boolean (default FALSE) that will display an additional column of information about sbs_b

The output of the function is exactly the same as with ANOVA, a labeled table with 4 rows and either 4 or 6 columns (not counting the row labels) depending on the value of sb_stats. Please read the documentation for ANOVA for more information about the output.

Example

The example below shows the same data as in the ANOVA example but formatted differently. To perform ANOVA on the data you have two options: reformat the data using Unfold (described elsewhere) and use ANOVA, or calculate group statistics and use ANOVA1S. The latter approach is shown below.

There may be cases when the original measurements are not available but the group statistics are, in which case ANOVA1S is the only option.

The same leaf data summarised as n_i, xbar_i and s_i per group; ANOVA1S on those gives the same ANOVA table

Download: ANOVA1S.xlsx

Source Code

ANOVA1S = LAMBDA(
    n_i,    // vector of replicate counts
    xbar_i, // vector of means within a group
    s_i,    // vector of within-group std deviations
    [sb_stats],     // add column of s_b info?
    LET(
        // before doing calcs convert all inputs to column vectors
        n_i, TOCOL(n_i),
        xbar_i, TOCOL(xbar_i),
        s_i, TOCOL(s_i),
        xbar_global, SUM(n_i*xbar_i)/sum(n_i),
        sb_stats, IF(ISOMITTED(sb_stats), FALSE, sb_stats),
        SS_b, SUM(n_i * (xbar_i - xbar_global) ^ 2),
        // don't use groups with just one member to calculate SS_w (s_i doesn't exist)
        SS_w, SUM(FILTER((n_i - 1) * s_i ^ 2, n_i > 1)),
        SS_t, SS_b + SS_w,
        DF_b, COUNT(n_i) - 1,
        DF_w, SUM(n_i - 1),
        DF_t, SUM(n_i) - 1,
        MS_b, SS_b / DF_b,
        MS_w, SS_w / DF_w,
        MS_t, SS_t / DF_t,
        s_w, SQRT(MS_w),
        // if MS_b < MS_w then s_b is not defined
        // output zero in that case
        n0, (SUM(n_i) - SUMSQ(n_i) / SUM(n_i)) / (COUNT(n_i) - 1),
        s_b, IFERROR(SQRT((MS_b - MS_w) / n0), 0),
        s_r, SQRT(s_w ^ 2 + s_b ^ 2),
        Fobs, MS_b / MS_w,
        F_LL, Fobs / F.INV.RT(5%, DF_b, DF_w),
        F_crit, F.INV.RT(5%, DF_b, DF_w),
        P_obs, F.DIST.RT(Fobs, DF_b, DF_w),
        results, VSTACK(
                HSTACK("", "SS", "DF", "MS", "s"),
                HSTACK("Within", SS_w, DF_w, MS_w, s_w),
                HSTACK("Between", SS_b, DF_b, MS_b, s_b),
                HSTACK("Total", SS_t, DF_t, MS_t, s_r),
                HSTACK("F test", Fobs, F_LL, F_crit, P_obs)
            ),
        // optional columns of s_b info, with their own IFERROR so a
        // problem here can't wipe out the ANOVA table itself
        sb_col, IFERROR(
            IF(
                MS_b > MS_w,
                LET(
                    // Satterthwaite DOF for s_b^2 = (MS_b - MS_w)/n0 (a difference)
                    DF_sb, (MS_b - MS_w) ^ 2 / (MS_b ^ 2 / DF_b + MS_w ^ 2 / DF_w),
                    // GAMMA.INV = chi-square quantile that allows fractional DOF
                    // (CHISQ.INV truncates DOF to an integer)
                    LL, SQRT(DF_sb * s_b ^ 2 / GAMMA.INV(0.975, DF_sb / 2, 2)),
                    UL, SQRT(DF_sb * s_b ^ 2 / GAMMA.INV(0.025, DF_sb / 2, 2)),
                    VSTACK("s_b", DF_sb, LL, UL, "")
                ),
                VSTACK("s_b", "n/a", 0, "n/a", "")   // s_b clamped to 0: no CI
            ),
            VSTACK("s_b", "error", "", "", "")
        ),
        sb_labels, VSTACK("", "<-- s_b DOF", "<-- s_b 95% LL", "<-- s_b 95% UL", ""),
        output, IF(sb_stats, HSTACK(results, sb_col, sb_labels), results),
        IFERROR(output, "calc error")
    )
);