The questions asked of a published table are always the same: what is in it, what changed between periods and how sure can one be, what the rates are if there is an exposure, whether a short series trends, and whether this release differs from the one held before. Each has a function in this package; this runs them together, with the pieces a reviewer needs and that are easy to forget on a deadline: exact intervals on every change, multiple-comparison adjustment over the groups scanned, the envelope that rounding and suppression in the release imply, and a drift screen against the prior capsule.
Arguments
- data
A data frame in long form: one row per period and group.
- value
Name of the column (a string) with the published count (or measure).
- prd
Name of the column with the period (fiscal year, quarter, ...); numeric periods are used as the time axis of the trend tests. Text periods (
"2019/20","2021 Q3","Mar 2021") are ordered asyoy()reads them (see itsprd), or asprdordgives.- by
Optional character vector of grouping column names (institution, region, ...).
NULL(the default) treats the table as one series.- pop
Optional name of an exposure column for rates (
NULL, the default, skips the rate step).- prior
Optional data frame: the previous capsule of the same table, for the drift screen.
NULL(the default) skips it.- units
"count"(the default),"continuous"or"percent", as inyoy().- rnd, rndkind, suplim
How the release rounds or suppresses cells; see
pubbnd().rndis the rounding base (for example 5),rndkind"nearest"(the default) or"random",suplimthe threshold below which cells are suppressed.NULLwhen the counts are exact. Used only for counts: with otherunitsthey are ignored, with a warning.- dir
Which way is an improvement, as in
yoy():"neutral"(the default),"higher"or"lower".- per
Rate denominator, as in
rtcalc(); default 1000 (rates per 1,000 ofpop).- conflvl
Confidence level for every interval, default 0.95.
- alpha
Level for the multiple-comparison decision and the drift screens, default 0.05.
- adjust
Multiple-comparison method for
scanadj(). The default is"BH"(Benjamini-Hochberg).- prdord
Optional character vector: the period labels in order, for text periods the reader does not know (see
yoy()); passed toyoy(),ratechg()and the trend tests.
Value
A list of class bricklayer_analysis (with a print method that
summarises it in a few lines):
profileprofcols()ofdata.missingnessnamed numeric from
misssmry().changethe
yoy()table; for counts with the added columnsp_value,padjandsignificant, and withenv_*andcompctlo/compctupwhen publication bounds were requested.rates,ratechgthe
rtcalc()andratechg()tables whenpopulationis given, otherwiseNULL.trenddata frame with one row per group: the
bycolumns,periods,first,last,tau,trndp,slope,rateratio,rateratiolo,rateratioup.driftcpsdrft()result againstprior, orNULL.metalist of the arguments used,
nrows, the sortedperiods,prior(logical) andwhen(a time stamp).
Details
The steps, in order:
profile:
profcols()andmisssmry()ondata;change:
yoy()between consecutive periods within eachbygroup. Forunits = "count"the exact p-values are then adjusted across all comparisons withscanadj(), and, whenrndorsuplimis given,yoybnd()adds the publication envelope (seepubbnd()). For"continuous"and"percent"units neither step runs:rndandsuplimare then ignored, with a warning;rates (only with
pop):rtcalc()per group and period, andratechg()between periods, adjusted withscanadj();trend: per group, the values summed within each period, then
trndtst()(Mann-Kendall tau, p-value and Theil-Sen slope) and, for counts,cnttrnd()(Poisson rate ratio per period). A group with fewer than three periods getsNA; a test that fails getsNArather than an error;drift (only with
prior):cpsdrft()ofdataagainstprior.
Nothing is written and nothing is fetched; a progress bar for the trend step
is drawn on stderr unless options(morie.quiet = TRUE). Errors:
data or prior not a data frame; a named column not in
data; an invalid units, dir or rndkind; a
conflvl outside (0, 1); and any error of the functions called (for
example negative counts in yoy()).
See also
rptanl() writes the result as a
Markdown or HTML
report.
Examples
path <- system.file("extdata", "otis_a01_individuals.csv",
package = "rmoriebricklayer")
otis <- read.csv(path)
a <- anltab(otis, value = "individuals", prd = "year",
by = c("table", "group"))
a
#> ╭── Analysis of a published table ────────────────────────────────────────╮
#> │ Value `individuals` │
#> │ Period year │
#> │ Periods 3 (2023 to 2025) │
#> │ Grouped by table x group │
#> │ Rows 15 │
#> │ Columns 4 │
#> │ Missing no missing values │
#> │ Changes 10 comparison(s), 9 significant after BH at 0.05 │
#> │ Trend 0 of 5 series with Mann-Kendall p < 0.05 │
#> │ │
#> │ Changes are between consecutive periods with exact or interval tests, │
#> │ adjusted for the number of comparisons; rptanl() writes the full │
#> │ tables as a report, and x$change, x$rates and x$trend hold them. │
#> │ │
#> │ Run 2026-10-30 17:24 │
#> ╰─────────────────────────────────────────────────────────────────────────╯
a$change[, c("table", "group", "year", "pctchg", "padj")]
#> table group year pctchg padj
#> 1 age_category 18 to 24 2023 NA NA
#> 2 age_category 18 to 24 2024 -16.053607 3.164937e-12
#> 3 age_category 18 to 24 2025 25.271739 1.664477e-19
#> 4 age_category 25 to 49 2023 NA NA
#> 5 age_category 25 to 49 2024 -3.248493 5.269786e-03
#> 6 age_category 25 to 49 2025 27.947387 3.609584e-109
#> 7 age_category 50+ 2023 NA NA
#> 8 age_category 50+ 2024 -3.924915 1.794906e-01
#> 9 age_category 50+ 2025 27.664298 6.794641e-18
#> 10 gender Female 2023 NA NA
#> 11 gender Female 2024 27.332892 2.786935e-12
#> 12 gender Female 2025 46.621622 2.223495e-38
#> 13 gender Male 2023 NA NA
#> 14 gender Male 2024 -8.059159 1.161620e-15
#> 15 gender Male 2025 25.438844 8.427443e-112
a$trend[, c("group", "tau", "trndp", "rateratio")]
#> group tau trndp rateratio
#> 1 18 to 24 0.3333333 1.0000000 1.027143
#> 2 25 to 49 0.3333333 1.0000000 1.118024
#> 3 50+ 0.3333333 1.0000000 1.112728
#> 4 Female 1.0000000 0.3333333 1.376319
#> 5 Male 0.3333333 1.0000000 1.077781
# counts published rounded to base 5: the intervals widen
b <- anltab(otis, value = "individuals", prd = "year",
by = c("table", "group"), rnd = 5)
b$change[1:3, c("group", "year", "pctlo", "compctlo")]
#> group year pctlo compctlo
#> 1 18 to 24 2023 NA NA
#> 2 18 to 24 2024 -20.09432 -20.09432
#> 3 18 to 24 2025 19.31564 19.31564
# rates with an exposure column
d <- data.frame(year = rep(2019:2022, 2), site = rep(c("A", "B"), each = 4),
n = c(10, 12, 15, 9, 30, 28, 35, 40),
pop = rep(c(1000, 2000), each = 4))
r <- anltab(d, "n", "year", by = "site", pop = "pop", per = 1000)
r$ratechg[, c("site", "year", "rate", "rateratio", "padj")]
#> ╭── Change in rate ─────────────────────────────────────────────────────╮
#> │ Rows 8 │
#> │ Columns 5 │
#> │ │
#> │ site year rate rateratio padj │
#> │ ---- ---- ----- --------- ----- │
#> │ A 2019 10.00 │
#> │ A 2020 12.00 1.200 0.896 │
#> │ A 2021 15.00 1.250 0.896 │
#> │ A 2022 9.00 0.600 0.896 │
#> │ B 2019 15.00 │
#> │ B 2020 14.00 0.933 0.896 │
#> │ B 2021 17.50 1.250 0.896 │
#> │ B 2022 20.00 1.143 0.896 │
#> │ │
#> │ Some of this result's columns are not here (a subset of it?), so it │
#> │ is shown as a plain table. │
#> ╰───────────────────────────────────────────────────────────────────────╯
# a column that is not in the data is an error
try(anltab(otis, value = "count", prd = "year"))
#> Error : anltab: column `count` not found in `data`
