Produces the market-research "banner" table: one master table with a stack of
question variables down the side (rows) and one or more grouping variables
across the top (cols), plus an Overall column for the whole sample.
Categorical questions become column-percentage blocks (each banner column sums
to ~100 within the block); numeric questions become a mean / median / sd /
quartile block. It generalises crosstab() from a single pair to a whole
table, and picks the cell content per question automatically.
Arguments
- data
A data frame. If omitted, the session default (
use_dataset()) is used.- rows
Stub variables, down the side (tidyselect, e.g.
c(satis_return, demo_edu)orstarts_with("ratings_")). If omitted, every eligible variable is used (seemax_levelsand Details).- cols
Banner / grouping variables, across the top (tidyselect). Pass several to get several spanning column groups. If omitted, every eligible variable is used, giving a full variable-by-variable banner.
- cell
What each body cell holds:
"auto"(default) uses column percentages for categorical questions and a statistics block for numeric ones;"pct"forces column percentages;"count"uses (weighted) counts;"mean"forces a numeric mean (errors on a categorical question);"diff"shows each cell's difference from the Overall column (percentage points, or mean difference for numeric questions).- stats
For numeric questions, which statistics form the block. Any of
"mean","median","sd","p25","p75". Default all five.- total
Include the whole-sample Overall column. Default
TRUE.- digits
Decimal places.
NULL(default) uses0for percentages / counts and2for numeric statistics; a value overrides both.- na_rm
Drop blanks / non-answers in the questions and banner variables. Default
TRUE.- drop
Answer values to remove before tabulating (see
drop_items()), passed to the underlyingcrosstab()calls. Defaults to thedrop_answersoption.- weights
Survey weighting:
NULL(default) uses the session scheme fromset_weights()if set;FALSEforces unweighted; or pass an ad-hoc scheme. When weighting is active the cells are weighted (weighted percentages, counts, means and quartiles).- max_levels
When
rows/colsare omitted, the largest number of distinct answers a categorical variable may have to be used automatically (default20). Bigger categorical variables, identifier columns and free-text are skipped; numeric scales are always kept as stub rows.- long
If
TRUE, return the tidy long form (variable,item,group,group_item,value) instead of the wide master table. DefaultFALSE.- flextable
If
TRUE, return a flextable with the two-row banner header ready for a slide or Word report. DefaultFALSE. Requires the suggestedflextablepackage.- checkpoint
Save each question as it finishes, so re-running the same call picks up where an interrupted run stopped.
TRUEkeeps the file undertools::R_user_dir()and deletes it once the run completes; a file path puts it where you choose and leaves it there for you to manage.NULL(default) orFALSEwrites nothing. See Details andclear_checkpoints().- confirm
When
rows/colsare left to the automatic selection, show which variables were chosen and which were skipped, and wait for a yes before the run starts.NULL(default) follows theconfirmoption, which asks in an interactive session and never asks in a script;TRUEorFALSEforce it either way. Answering no returnsNULLand computes nothing.
Value
By default a wide tibble: variable, item,
Overall, then one column per banner item. The banner grouping (which
column belongs to which top-row variable) is stored in the
"banner_spanners" attribute, which flextable = TRUE turns into a
spanning two-row header. With long = TRUE, the tidy long form.
Details
A tibble has a single header row, so the two-row banner header (each grouping
variable's name spanning its items) cannot be stored in the data itself: the
wide return carries the grouping in the "banner_spanners" attribute and
flextable = TRUE renders the real spanning header. Column percentages are
computed within each banner column, so every column (Overall included) sums
to about 100 down each question block. Registered orders (register_order())
set the item and banner-column ordering automatically. Passing the same
selection to rows and cols gives the full every-question-by-every-question
matrix (a variable is never crossed with itself). Supplying only the data
frame does this automatically: every variable with at most max_levels
distinct answers becomes both a stub and a banner group, numeric scales are
added as stub statistics blocks, and identifier / free-text columns are
skipped (and named in a message). That selection decides the whole table, so
an interactive session prints it and waits for a yes before starting the run
(see confirm). Check-all-that-apply blocks (columns sharing
a prefix that each hold one option or blank, such as motivations_*) are
recognised as a single multi-select stub question and tabulated with
calc_percentage_multi(), whose base is the respondents who picked any option
(so those rows can sum past 100). Multi-select blocks appear as stubs only, not
banner groups, and are unweighted.
A full every-variable banner is one crosstab() per question per grouping
variable, so a wide survey takes minutes rather than seconds. In an
interactive session it reports which question it is on, with an estimate of
the time left; ezrsurvey_options(progress = FALSE) turns that off, and
scripts are silent by default. checkpoint = TRUE additionally saves each
question as it completes, so re-running the identical call after an
interruption resumes instead of starting again. The managed file is named
after the run's own fingerprint, so a call finds its own interrupted run and
a call with different data or arguments never sees it, and it is deleted as
soon as the table is built. Pass a path instead if you would rather choose
the location; that file is yours, so the package neither deletes it nor
counts it as one of its own. clear_checkpoints() empties the managed
folder if a run was interrupted and never repeated.
See also
crosstab() for a single pair, calc_percentage_batch() for stacked
one-variable percentages, export_summary_xlsx(), register_order().
Other summaries:
calc_percentage(),
calc_percentage_batch(),
calc_percentage_multi(),
calc_summary(),
clear_checkpoints(),
crosstab()
Examples
# gender and region banner over two questions (column percentages)
crosstab_banner(podracing_survey,
rows = c(satis_return, demo_edu),
cols = c(demo_gender, region))
#> # A tibble: 12 × 11
#> variable item Overall Female Male `Non-binary` Asia Europe `Latin America`
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 demo_edu Bach… 25 26 25 22 23 28 15
#> 2 demo_edu Doct… 4 3 4 4 4 3 5
#> 3 demo_edu Lowe… 11 12 11 15 12 10 10
#> 4 demo_edu Mast… 13 12 13 19 11 15 9
#> 5 demo_edu Prim… 4 3 5 7 7 6 4
#> 6 demo_edu Shor… 13 14 12 4 19 11 17
#> 7 demo_edu Uppe… 30 30 31 30 25 26 41
#> 8 satis_r… Like… 27 28 27 15 24 28 30
#> 9 satis_r… Not … 24 25 22 33 25 25 21
#> 10 satis_r… Unli… 16 14 17 26 12 16 11
#> 11 satis_r… Very… 26 24 26 26 34 25 28
#> 12 satis_r… Very… 8 9 7 0 5 6 10
#> # ℹ 2 more variables: `North America` <dbl>, Oceania <dbl>
# numeric questions become a mean / median / sd / quartile block
crosstab_banner(podracing_survey,
rows = c(nps_value, demo_age),
cols = demo_gender)
#> # A tibble: 10 × 6
#> variable item Overall Female Male `Non-binary`
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 demo_age mean 32.6 32.9 32.3 31.2
#> 2 demo_age median 32 33 32 31
#> 3 demo_age sd 11.2 11.4 11.1 11.1
#> 4 demo_age p25 24 25 24 23.5
#> 5 demo_age p75 40 40 40 37
#> 6 nps_value mean 7.56 7.51 7.61 7.56
#> 7 nps_value median 8 8 8 8
#> 8 nps_value sd 1.76 1.81 1.72 1.69
#> 9 nps_value p25 6 6 7 7
#> 10 nps_value p75 9 9 9 8
# each cell as its difference from the Overall column
crosstab_banner(podracing_survey, rows = satis_return,
cols = region, cell = "diff")
#> # A tibble: 5 × 8
#> variable item Overall Asia Europe `Latin America` `North America` Oceania
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 satis_retu… Like… 27 -3 1 3 -1 4
#> 2 satis_retu… Not … 24 1 1 -3 0 -12
#> 3 satis_retu… Unli… 16 -4 0 -5 1 8
#> 4 satis_retu… Very… 26 8 -1 2 -2 -2
#> 5 satis_retu… Very… 8 -3 -2 2 0 2
# \donttest{
# full variable-by-variable banner: just pass the data frame
crosstab_banner(podracing_survey)
#> crosstab_banner: skipped 3 identifier / free-text / high-cardinality column(s): respondent_id, nps_com, show_com. Raise max_levels or name them in rows/cols to include them.
#> # A tibble: 129 × 126
#> variable item Overall email in_app panel socials Female Male `Non-binary`
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 collector email 28 NA NA NA NA 29 29 33
#> 2 collector in_a… 16 NA NA NA NA 15 17 26
#> 3 collector panel 35 NA NA NA NA 35 34 33
#> 4 collector soci… 20 NA NA NA NA 21 20 7
#> 5 demo_age mean 32.6 32.3 32.5 32.5 33.2 32.9 32.3 31.2
#> 6 demo_age medi… 32 32 33 32 32 33 32 31
#> 7 demo_age sd 11.2 11.5 10.5 11.4 11.0 11.4 11.1 11.1
#> 8 demo_age p25 24 24 25 23.5 25 25 24 23.5
#> 9 demo_age p75 40 40 39 40 41 40 40 37
#> 10 demo_gend… Fema… 42 42 39 43 44 NA NA NA
#> # ℹ 119 more rows
#> # ℹ 116 more variables: `Bachelor or equivalent` <dbl>,
#> # `Doctoral or equivalent` <dbl>, `Lower secondary` <dbl>,
#> # `Master or equivalent` <dbl>, `Primary or less` <dbl>,
#> # `Short-cycle tertiary` <dbl>, `Upper secondary` <dbl>, Australia <dbl>,
#> # Brazil <dbl>, Canada <dbl>, France <dbl>, Germany <dbl>, Japan <dbl>,
#> # Mexico <dbl>, Sweden <dbl>, `United Kingdom` <dbl>, …
# }
