--- title: "Banner tables" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Banner tables} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(ezrsurvey) ``` The banner is the table a client actually works from: every question down the side, every way of splitting the sample across the top, and one column for the sample as a whole. It is the first deliverable of most projects and the one that takes longest to build by hand, because it is the same cross-tab written out dozens of times. `crosstab_banner()` writes it in one call. ## The shape of it Name the questions as `rows` and the splits as `cols`. ```{r} crosstab_banner( podracing_survey, rows = c(satis_return, demo_edu), cols = c(demo_gender, region) ) ``` Three things are worth noticing in that output. Every question keeps its own answers as rows, so questions with different scales stack in one table. The `Overall` column is the whole sample, which is what a reader compares each group against. And the percentages are column percentages: they run down each group, so they answer "what does this group look like", not "where do this answer's respondents come from". `tidyselect` helpers work, which is how a block of rating questions goes in: ```{r} crosstab_banner( podracing_survey, rows = dplyr::starts_with("ratings_"), cols = demo_gender ) ``` ## Numbers and categories in one table A numeric question has no answers to count, so counting it would produce a row per distinct value. Handed one, the banner switches to a statistics block instead, and says so by labelling the rows: ```{r} crosstab_banner( podracing_survey, rows = c(nps_value, demo_age), cols = demo_gender ) ``` `cell` overrides the choice when you want something specific: `"pct"`, `"count"`, `"mean"`, or `"diff"` for each group's distance from `Overall`, which is the version to read when you are hunting for what makes a group different. ```{r} crosstab_banner( podracing_survey, rows = satis_return, cols = demo_gender, cell = "diff" ) ``` ## Weighting A banner built on a weighted sample has to be weighted in every cell, not corrected afterwards. Set the scheme once and it applies throughout: ```{r} set_weights(c(variable = "demo_gender", "Male" = 0.49, "Female" = 0.50, "Non-binary" = 0.01)) crosstab_banner( podracing_survey, rows = satis_return, cols = region ) clear_weights() ``` Weights are computed once per dataset and scheme and then reused, rather than re-running the raking loop for every cell. `clear_weights_cache()` empties that store if you need to force a recalculation. ## Letting it choose the variables Called with no `rows` or `cols`, the banner picks them itself: every question that looks like a question, crossed by every variable that looks like a split. That choice decides the entire table, so in an interactive session it shows the choice and waits: ``` Banner variables chosen automatically: 34 question(s) across 12 grouping variable(s). Questions (34): satis_return, demo_gender, ... Grouping variables (12): demo_gender, region, ... Skipped (11): respondent_id, start_date, nps_com, ... Name `rows` / `cols` yourself, or raise `max_levels` (now 20), to change this. Continue? [Y/n] ``` Identifier columns, free text and anything with more distinct answers than `max_levels` are left out. Naming the variables yourself is your own decision and is never questioned. The prompt only appears when someone is there to answer it, so an unattended script cannot stall on it; `ezrsurvey_options(confirm = FALSE)` removes it and `TRUE` forces it. ## Runs long enough to worry about A full every-variable banner on a wide survey is minutes of work. While it runs it says where it is, with an estimate built from the throughput measured so far rather than a guess: ``` Banner table: 34 question(s) across 12 grouping variable(s) [7/34] satis_return (about 2m left) ``` Progress reporting is on in an interactive session and silent in scripts, vignettes and `R CMD check`. `ezrsurvey_options(progress = FALSE)` turns it off everywhere. For a table long enough that losing it would hurt, ask for a checkpoint: ```r crosstab_banner(survey, checkpoint = TRUE) # managed for you crosstab_banner(survey, checkpoint = "banner.rds") # or choose the location ``` Each question is saved as it finishes, so re-running the identical call after a crash carries on from where it stopped. The managed file is named after the run's own fingerprint, so a call finds its own interrupted run and never sees one belonging to different data or different arguments: a stale file cannot quietly corrupt a table. A finished run deletes the file `checkpoint = TRUE` made for it, and `clear_checkpoints()` clears anything left behind by a run that was never repeated. A path you chose yourself is your file: the package leaves it in place when the run finishes, so delete it when you no longer need it. ## Getting it out A banner is usually delivered as a spreadsheet, and `long = TRUE` gives the tidy form to pivot or join instead of the printed one. ```r banner <- crosstab_banner(survey, rows = ..., cols = ...) export_xlsx("Banner" = banner, path = "banner.xlsx") save_data(banner, "banner.csv") ``` `flextable = TRUE` returns a formatted table ready to drop on a slide or into a Word document through [`report_add_table()`](../reference/report_add_table.html).