| Type: | Package |
| Title: | Single-Line Helpers for Consumer Survey Analysis |
| Version: | 0.7.1 |
| Description: | Simplifies the day-to-day work of research and insights professionals who analyse consumer and customer survey data but have limited coding experience. Wraps common 'tidyverse' patterns into single-line functions for the tasks these teams repeat constantly: loading and combining survey exports, turning questions into percentages and summaries, recoding rating and Net Promoter scales, deriving demographics such as age cohorts and regions, modelling the drivers of satisfaction, checking sampling precision, selecting illustrative open-text comments, and producing presentation-ready charts and reports. A simulated consumer-survey dataset is included for learning and examples. Weighting rakes to target margins as in Deming and Stephan (1940) <doi:10.1214/aoms/1177731829> and reports the design effect of Kish (1965, ISBN:978-0-471-10949-5); driver models use the relative weights of Johnson (2000) <doi:10.1207/S15327906MBR3501_1> or the random forests of Breiman (2001) <doi:10.1023/A:1010933404324>; the Net Promoter Score follows Reichheld (2003) https://hbr.org/2003/12/the-one-number-you-need-to-grow; and diverse comments are chosen by maximal marginal relevance as in Carbonell and Goldstein (1998) <doi:10.1145/290941.291025>. |
| License: | MIT + file LICENSE |
| URL: | https://mashud37.github.io/ezr-research/ezr-survey/, https://github.com/mashud37/ezr-research |
| BugReports: | https://github.com/mashud37/ezr-research/issues |
| Encoding: | UTF-8 |
| Language: | en-GB |
| LazyData: | true |
| Depends: | R (≥ 4.1.0), dplyr (≥ 1.1.0), ggplot2, tidyr (≥ 1.2.0), tibble, readr, stringr, purrr |
| Imports: | rlang (≥ 1.0.0), withr |
| Suggests: | rwa, randomForest, treemapify, ggrepel, scales, officer (≥ 0.6.0), flextable, openxlsx2, xml2, systemfonts, quarto, knitr, rmarkdown, svglite, writexl, yaml, stopwords, testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| Config/roxygen2/version: | 8.0.0 |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-10-22 14:42:37 UTC; andreas |
| Author: | Andreas Schellewald [aut, cre] |
| Maintainer: | Andreas Schellewald <aschellewald@acm.org> |
| Repository: | CRAN |
| Date/Publication: | 2026-11-04 21:40:02 UTC |
ezrsurvey: Single-Line Helpers for Consumer Survey Analysis
Description
Simplifies the day-to-day work of research and insights professionals who analyse consumer and customer survey data but have limited coding experience. Wraps common 'tidyverse' patterns into single-line functions for the tasks these teams repeat constantly: loading and combining survey exports, turning questions into percentages and summaries, recoding rating and Net Promoter scales, deriving demographics such as age cohorts and regions, modelling the drivers of satisfaction, checking sampling precision, selecting illustrative open-text comments, and producing presentation-ready charts and reports. A simulated consumer-survey dataset is included for learning and examples. Weighting rakes to target margins as in Deming and Stephan (1940) doi:10.1214/aoms/1177731829 and reports the design effect of Kish (1965, ISBN:978-0-471-10949-5); driver models use the relative weights of Johnson (2000) doi:10.1207/S15327906MBR3501_1 or the random forests of Breiman (2001) doi:10.1023/A:1010933404324; the Net Promoter Score follows Reichheld (2003) https://hbr.org/2003/12/the-one-number-you-need-to-grow; and diverse comments are chosen by maximal marginal relevance as in Carbonell and Goldstein (1998) doi:10.1145/290941.291025.
Author(s)
Maintainer: Andreas Schellewald aschellewald@acm.org
Authors:
Andreas Schellewald aschellewald@acm.org
See Also
Useful links:
Report bugs at https://github.com/mashud37/ezr-research/issues
Pipe operator
Description
Re-exported from dplyr. See dplyr::%>%
for details.
Usage
lhs %>% rhs
Arguments
lhs |
A value or the magrittr placeholder. |
rhs |
A function call using the magrittr semantics. |
Value
The result of calling rhs(lhs).
Add a converted-currency column to a data frame
Description
Convenience wrapper around convert_currency() that appends a converted
column to data. The source currency can be a fixed code or a per-row column.
Usage
add_currency(data = NULL, amount, from, to = "USD", into = NULL, rates = NULL)
Arguments
data |
A data frame. |
amount |
The amount column to convert (unquoted). |
from |
Source currency: either a bare column name holding per-row codes
(e.g. |
to |
Target currency code. Defaults to |
into |
Name of the new column. Defaults to |
rates |
Passed to |
Details
The from argument is clever about whether you mean a column or a constant: a
bare name (from = currency) is read as a per-row source-currency column,
while a quoted string (from = "EUR") is a fixed code applied to every row.
This is the common case where each respondent reported spend in their own
currency. The new column defaults to <amount>_<to> (e.g. spend_usd);
override with into. Conversion uses convert_currency(), so the same rates,
aliases and warnings apply.
Value
data with the converted column added.
See Also
Other currency:
convert_currency(),
list_currencies()
Examples
df <- tibble::tibble(spend = c(100, 200, 50),
currency = c("EUR", "GBP", "JPY"))
# per-row source currency (a column)
add_currency(df, spend, from = currency, to = "USD")
# a fixed source currency (a constant), custom output name
add_currency(df, spend, from = "EUR", to = "USD", into = "spend_usd")
Add region (and subregion) columns from a country column
Description
Convenience wrapper that appends a region column (and optionally a
subregion) to a data frame by looking up an existing country column with
recode_region().
Usage
add_region(
data = NULL,
country,
region_to = "region",
subregion = FALSE,
quiet = FALSE
)
Arguments
data |
A data frame. |
country |
The country column (unquoted). |
region_to |
Name of the region column to add. Defaults to |
subregion |
If |
quiet |
Passed to |
Details
This is the data-frame-friendly form of recode_region(): point it at an
existing country column and it appends a region column (named via
region_to) and, optionally, a subregion. Handy right after read_folder()
to enrich raw exports before grouping by region. The lookup, matching and
unmatched-country warning behave exactly as in recode_region().
Value
data with the new column(s) added.
See Also
recode_region(), country_region.
Other recode:
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
df <- tibble::tibble(demo_country = c("Germany", "Japan", "Brazil"))
add_region(df, demo_country, subregion = TRUE)
Annotate a plot with labelled decision bands
Description
Programmatically adds the BAD / OK / GOOD style decision markers survey
charts carry: for each band a thin coloured marker line runs
along one axis, with a bold centred label. This turns the copy-pasted
geom_rect() + annotate("text", x = median(seq(from, to, .1)), ...) blocks
into one call, so any chart can be given consistent "where's good, where's
bad" guidance.
Usage
annotate_bands(
plot,
bands,
axis = c("x", "y"),
at = NULL,
label_offset = NULL,
labels = TRUE,
text_colour = NULL,
text_size = NULL,
linewidth = 1
)
Arguments
plot |
A ggplot object. |
bands |
A band specification: a data frame (or one of |
axis |
Which axis the bands run along: |
at |
Position on the opposite axis at which to draw the marker line and
labels (e.g. the top of a bar chart). If |
label_offset |
Distance to nudge labels away from the marker line, in
data units of the opposite axis. If |
labels |
Whether to draw the band labels. Defaults to |
text_colour, text_size |
Label appearance. |
linewidth |
Marker line width. Defaults to |
Details
Bands turn a chart into a decision aid: a thin coloured marker line runs along
one axis for each band, with a bold centred label, so a reader instantly sees
where "good" and "bad" lie. Supply a band spec (a data frame with from,
to, label and optional colour, or one of the bands_rating_3()
presets), the axis the bands run along, and at – the position on the
opposite axis for the marker line (usually the top of the panel; inferred from
the plot when omitted).
Value
The plot with the band layers added.
See Also
mark_value() to add a single "you are here" marker.
Other decisions:
bands_rating_3(),
mark_value(),
rescale_bands()
Examples
# the performance axis of an IPM chart is the 1-5 rating scale the
# bands describe, so "where is good" lands where a reader expects it
ipm_model(podracing_survey, nps_value, "ratings_") %>%
plot_ipm() %>%
annotate_bands(bands_rating_3(), axis = "x")
Apply a registered order to a vector
Description
Turns a vector into an ordered factor using a registered order, selected
either by order name or by looking up the order linked to a variable name.
Usage
apply_order(x, name = NULL, var = NULL)
Arguments
x |
A vector. |
name |
Order name (see |
var |
A variable name to look up via |
Value
A factor with the registered levels, or x unchanged if no order is
found.
See Also
register_order(), order_for().
Other config:
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order("size", c("S", "M", "L"))
apply_order(c("L", "S", "M"), name = "size")
remove_order("size")
Built-in decision-band presets
Description
Ready-made band specifications for annotate_bands().
Usage
bands_rating_3(from = NULL, to = NULL)
bands_rating_5(from = NULL, to = NULL)
bands_nps(from = NULL, to = NULL)
bands_nps_score(from = NULL, to = NULL)
Arguments
from, to |
Optional axis limits. A band reaching past them is trimmed and a band entirely outside them is dropped, so a preset can be reused on a chart that shows only part of the scale. |
Details
-
bands_rating_3()– BAD / OK / GOOD over a 1-5 rating axis. -
bands_rating_5()– per-point labels (1 Very bad .. 5 Very good) over 1-5. -
bands_nps()– Detractor / Passive / Promoter over a 0-10 answer axis. -
bands_nps_score()– Needs work / Good / Great / Excellent over a -100..100 Net Promoter Score axis (the scale a headline NPS sits on, not the 0-10 answers it is computed from).
Pass from / to when the chart's panel is narrower than the full scale.
Plotting a 2-5 range with the untrimmed bands_rating_3() would open the BAD
band at 1, off the left edge, and stretch the panel to reach it.
Value
A tibble with from, to, label and colour.
See Also
Other decisions:
annotate_bands(),
mark_value(),
rescale_bands()
Examples
bands_rating_3()
# only the part of the scale a 2-5 panel actually shows
bands_rating_3(from = 2)
bands_nps_score()
Bin a numeric vector into labelled groups
Description
A thin, survey-friendly wrapper around base::cut() that returns a factor in
band order and uses left-closed, right-open intervals by default
so that age bands like 18-21 behave intuitively. Generalises the
case_when(age %in% seq(...)) age-grouping pattern.
Usage
bin_numeric(x, breaks, labels, right = FALSE, quiet = FALSE)
Arguments
x |
A numeric vector. |
breaks |
Numeric vector of cut points. With |
labels |
Character vector of group labels, length |
right |
If |
quiet |
If |
Details
Bands are built with base::cut() using include.lowest = TRUE, so the very
lowest break is included. With right = FALSE (the default) a band runs from
its lower break up to but not including the next – i.e. [18, 25) – which
is what you want for age groups like "18 to 24". Text input is salvaged with
ensure_numeric(), so "27 years" bins correctly. The result is a factor
whose levels follow labels, so tables and charts built from it list the
bands low to high ("40-70k" before "100-150k") rather than alphabetically.
Wrap it in as.character() if you need plain text.
A value below the first break or above the last becomes NA and drops out of
every chart built from the result, so the function says how many did and what
their range was. A closed top band such as 35 to 40.5 under a label of
"35 to 40+" is the usual cause; Inf is what that label means.
Value
A factor whose levels are labels in the order given (values
outside the range or NA become NA).
See Also
recode_age() for a ready-made age-band wrapper, ensure_numeric().
Other recode:
add_region(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
bin_numeric(c(15, 19, 27, 41),
breaks = c(0, 18, 25, 35, Inf),
labels = c("<18", "18-24", "25-34", "35+"))
Show the active brand settings
Description
Show the active brand settings
Usage
brand_info()
Value
An ezrsurvey_brand list with elements colors, color_primary,
font_major, font_minor, template_pptx, template_docx (each NULL
when unset).
See Also
Other brand:
clear_brand(),
pal_brand(),
scale_fill_brand(),
use_brand()
Examples
brand_info()
Driver importance
Description
Ranks how much each predictor drives an outcome such as the NPS rating, as importance scores summing to 100. Relative weights analysis is the default; a random forest and a plain correlation are available as alternatives.
Usage
calc_importance(
data = NULL,
outcome,
predictors,
method = c("rwa", "forest", "correlation"),
recode = TRUE,
likert_levels = c("Very bad", "Bad", "Ok", "Good", "Very good")
)
Arguments
data |
A data frame. |
outcome |
The outcome column (unquoted), e.g. |
predictors |
The predictor columns, using tidyselect (e.g.
|
method |
How to measure importance. |
recode |
If |
likert_levels |
Scale wordings passed to |
Details
All three methods answer the same question and are scaled the same way, so
each feature's importance reads as "this feature accounts for X% of what
drives the outcome" and any of them can be fed to plot_ipm(). They differ in
what they can see:
-
"rwa", relative weights analysis (Johnson's epsilon), shares out the linear model's explained variance between correlated predictors, which ordinary regression coefficients handle poorly. This is the default because rating batteries are almost always heavily correlated. -
"forest"grows a random forest and measures how much prediction error rises when each predictor is permuted, so it picks up non-linear effects and interactions that relative weights cannot. It is the useful cross-check: if a feature ranks high here and low under"rwa", its effect is not linear. Being a random method, it moves a little between runs; callset.seed()first for a figure you intend to publish. -
"correlation"is the crude one, ignoring the other predictors entirely, so correlated features double-count. Its merit is that it needs no suggested package and cannot fail to converge, which makes it a reasonable sanity check on the other two.
Only complete cases are used. Worded rating columns are recoded to 1-5
automatically (recode = TRUE). Negative importances (which permutation
importance can produce for a predictor that is pure noise) are floored at
zero before rescaling. Most users call ipm_model(), which pairs this with
performance for the importance/performance matrix.
Value
A tibble with feature and importance, the
latter rescaled to sum to 100 whichever method produced it, strongest
driver first.
See Also
Other modelling:
calc_nps(),
ipm_model()
Examples
calc_importance(podracing_survey, nps_value, starts_with("ratings_"))
# a cross-check that can see non-linear effects
set.seed(1)
calc_importance(podracing_survey, nps_value, starts_with("ratings_"),
method = "forest")
Net Promoter Score
Description
Computes NPS from a 0-10 recommendation question. The score is
% promoters - % detractors, equivalently 100 * mean(nps_group(x)) over the
signed -1/0/1 coding (see nps_group()).
Usage
calc_nps(data = NULL, value, by = NULL, weights = NULL)
Arguments
data |
A data frame. |
value |
The 0-10 recommendation column (unquoted). |
by |
Optional grouping column(s); see |
weights |
Survey weighting: |
Details
Respondents are bucketed by nps_group() into detractors (0–6), passives
(7–8) and promoters (9–10); the score is the percentage of promoters minus
the percentage of detractors, which equals 100 * mean() of the signed
-1/0/1 coding. Missing or out-of-range scores are dropped before the mean.
Text answers are coerced with ensure_numeric(). Use plot_nps() for the
full 0–10 distribution chart and plot_nps_gauge() for a single-number
gauge.
The three group counts and shares are reported alongside the score because a
single NPS hides how it was reached: +20 from 40% promoters and 20%
detractors is a different picture from +20 with 25% and 5%. Counts are always
unweighted respondent counts; the shares follow nps, so they are weighted
when a weighting scheme is active. All three shares and nps are rounded to
whole numbers independently, so pct_promoters - pct_detractors can land one
point away from nps; the identity holds exactly before rounding.
Value
A tibble with n (valid responses), nps (an
integer from -100 to 100), the three group shares (pct_detractors,
pct_passives, pct_promoters) and the counts behind them (detractors,
passives, promoters), one row per group when by is given. The shares
come first because they are what a report quotes.
See Also
nps_group(), plot_nps(), plot_nps_gauge().
Other modelling:
calc_importance(),
ipm_model()
Examples
calc_nps(podracing_survey, nps_value)
calc_nps(podracing_survey, nps_value, by = region)
Count a categorical question as percentages
Description
The headline helper: replaces the ubiquitous
count(x) %>% mutate(pct = round(n / sum(n) * 100)) %>% select(-n) dance with a
single call. Returns both the raw counts and the percentages, optionally
grouped by one or more variables and optionally pivoted to a wide
cross-tabulation.
Usage
calc_percentage(
data = NULL,
column,
by = NULL,
sort = c("none", "desc", "asc"),
levels = NULL,
digits = 0,
wide = FALSE,
na_rm = TRUE,
drop = NULL,
weights = NULL
)
Arguments
data |
A data frame. If omitted, the session default set with
|
column |
The categorical column to tabulate (unquoted). |
by |
Optional grouping column(s). Percentages are computed within each
group so they sum to ~100 per group. Pass one bare name ( |
sort |
Level ordering of |
levels |
Optional character vector giving an explicit level order for
|
digits |
Decimal places for the percentage. Defaults to |
wide |
If |
na_rm |
If |
drop |
Optional character vector of answer values to remove before
counting (e.g. |
weights |
Survey weighting for this call: |
Details
Percentages are computed within each group, so they sum to about 100 per
group (subject to rounding). The level order of column is decided in this
order of precedence: an explicit levels argument; then a non-"none"
sort; then a registered order for the variable (see register_order());
then the column's own levels, when it is a factor; otherwise data order. When by is omitted, the default_by option is used if
set (see ezrsurvey_options()), so you can apply a standard breakdown without
repeating it. wide = TRUE pivots to one row per group with a column per
answer – the shape you want for a slide table or an Excel tab.
Value
A tibble with column, n and pct (and wpct
when weighting is active) in long form, or one row per group with an answer
column each (wide form).
See Also
calc_percentage_multi() for check-all-that-apply questions,
calc_percentage_batch() for many questions at once, calc_summary() for
numeric variables, register_order() for reusable level orders.
Other summaries:
calc_percentage_batch(),
calc_percentage_multi(),
calc_summary(),
clear_checkpoints(),
crosstab(),
crosstab_banner()
Examples
calc_percentage(podracing_survey, demo_gender)
# largest first
calc_percentage(podracing_survey, demo_gender, sort = "desc")
# grouped and pivoted to a wide cross-tab
calc_percentage(podracing_survey, satis_return, by = region, wide = TRUE)
Percentages for a batch of questions at once
Description
Runs calc_percentage() over several columns and stacks the results into one
tidy table with a variable column identifying the source question and a
shared answer column – handy for tabulating a whole block of questions
(e.g. every demo_ variable) in a single call.
Usage
calc_percentage_batch(
data = NULL,
...,
by = NULL,
sort = c("none", "desc", "asc"),
digits = 0,
na_rm = TRUE,
drop = NULL,
weights = NULL,
clean_names = FALSE,
prefix = NULL
)
Arguments
data |
A data frame. |
... |
Columns to tabulate, using tidyselect (e.g. |
by, sort, digits, na_rm, drop, weights |
Passed to |
clean_names |
If |
prefix |
Optional question prefix to strip from |
Details
Each selected column is tabulated with calc_percentage() and the results are
row-bound, with a variable column naming the source question and the answers
collected into a shared character answer column (factor levels differ
between questions, so they are coerced to character when stacked). This is the
tidy long shape you want for faceted plots or a single export of a whole
question block. To send each question to its own Excel tab instead, see
export_xlsx().
variable is the raw column name by default. Set clean_names = TRUE (or
name a prefix) to get the same tidied wording calc_percentage_multi() and
ipm_model() produce, which is what lets a batch table join to a model table
on the question name.
Value
A tibble with variable, answer, n, pct
(plus any by columns).
See Also
calc_percentage(), clean_label(), export_xlsx().
Other summaries:
calc_percentage(),
calc_percentage_multi(),
calc_summary(),
clear_checkpoints(),
crosstab(),
crosstab_banner()
Examples
calc_percentage_batch(podracing_survey, demo_gender, demo_job)
calc_percentage_batch(podracing_survey, starts_with("demo_"))
# tidy question names, with the block's prefix removed
calc_percentage_batch(podracing_survey, starts_with("ratings_"),
prefix = "ratings_")
Tabulate a check-all-that-apply (multi-select) question as percentages
Description
Multi-select questions arrive as a block of columns sharing a prefix, each holding the chosen option (or blank). This computes, per option, the share of respondents who selected it – so the percentages can (and usually do) sum to more than 100. The denominator is the number of distinct respondents who selected at least one option.
Usage
calc_percentage_multi(
data = NULL,
prefix,
id = NULL,
by = NULL,
sort = c("none", "desc", "asc"),
digits = 0,
drop = NULL,
clean_names = TRUE,
split = "auto"
)
Arguments
data |
A data frame. |
prefix |
Common column-name prefix identifying the option block, e.g.
|
id |
Optional respondent identifier column (unquoted) used as the distinct-respondent denominator. If omitted, each row is treated as one respondent. |
by |
Optional grouping column(s); percentages are computed within group. |
sort, digits |
As in |
drop |
Optional character vector of option labels to remove before
counting (matched against the cleaned labels, case-insensitive). Defaults to
the |
clean_names |
If |
split |
How to handle a question that arrives packed into a single cell
per respondent ( |
Details
The crucial difference from calc_percentage() is the denominator: it is the
number of distinct respondents who picked any option in the block, not the
number of ticks. So if 700 of 1,000 respondents selected at least one
motivation, each option's percentage is "out of 700", and the percentages can
(and usually do) sum to more than 100. Supply id to count distinct
respondents exactly; without it, each row counts as one respondent. With
clean_names = TRUE the option labels are stripped of prefix and exporter
artefacts like "A...B" are turned back into "A / B".
Two export shapes are handled. The usual one is a block of columns, one per
option, named with a shared prefix; that is what prefix selects. The other
is a single column holding every answer a respondent ticked, joined by a
delimiter, which is what Google Forms and most spreadsheet exports produce. If
prefix matches exactly one column and a delimiter is found in it, that
column is unpacked automatically and the answer text itself becomes the option
label (clean_names is not applied, since the answers are real wording rather
than mangled column names). Behaviour on a column block is unchanged. Use
split_multi() when you want those unpacked columns kept for other work.
Value
A tibble with option, n (respondents choosing
it) and pct.
See Also
calc_percentage(), split_multi(), plot_bars().
Other summaries:
calc_percentage(),
calc_percentage_batch(),
calc_summary(),
clear_checkpoints(),
crosstab(),
crosstab_banner()
Examples
calc_percentage_multi(podracing_survey, "motivations_",
id = respondent_id, sort = "desc")
# a spreadsheet export that packs every answer into one cell
packed <- data.frame(
respondent = 1:4,
motivations = c("Speed; Drivers", "Speed", "", "Betting; Speed")
)
calc_percentage_multi(packed, "motivations", id = respondent, sort = "desc")
Summarise a numeric question (mean / median / sd)
Description
The numeric counterpart to calc_percentage(): a one-liner for the
summarise(mean, median, sd) blocks used on age and other continuous
variables, with optional grouping.
Usage
calc_summary(data = NULL, column, by = NULL, na_rm = TRUE, weights = NULL)
Arguments
data |
A data frame. |
column |
Numeric column to summarise (unquoted). |
by |
Optional grouping column(s); see |
na_rm |
Drop |
weights |
Survey weighting: |
Details
The column is passed through ensure_numeric() first, so a text age column
like "25 years" still summarises. n counts non-missing values (after that
coercion). When a weighting scheme is active the statistics are weighted (and
missing values are dropped); n remains the unweighted respondent count. For a
measure of how precise the mean is, pair this with diagnose() or
se_mean().
Value
A tibble with n (non-missing count), mean,
median and sd, one row per group when by is supplied.
See Also
calc_percentage() for categorical variables, diagnose() for
precision.
Other summaries:
calc_percentage(),
calc_percentage_batch(),
calc_percentage_multi(),
clear_checkpoints(),
crosstab(),
crosstab_banner()
Examples
calc_summary(podracing_survey, demo_age)
calc_summary(podracing_survey, demo_age, by = region)
Tidy an exported column name into a readable label
Description
Turns the mangled column names survey tools produce back into the wording a
reader expects: "Broadcast.quality...audio" becomes
"Broadcast quality / audio". Drop a question prefix at the same time with
prefix, so a block of ratings_* columns becomes plain feature names.
Usage
clean_label(x, prefix = NULL)
Arguments
x |
A character vector of column names. |
prefix |
Optional prefix to strip from the start of each name before
tidying, e.g. |
Details
Exporters replace every character they cannot put in a column name with a
dot, so a slash surrounded by spaces arrives as three dots and a space
arrives as one. This restores both, in that order, then squishes the result.
It is the same cleaning calc_percentage_multi() and ipm_model() apply to
their own output, exported so a hand-built table can match them: labels that
disagree will not join, which is what silently empties a comparison chart.
Value
A character vector of labels, the same length as x.
See Also
calc_percentage_batch(), calc_percentage_multi().
Other recode:
add_region(),
bin_numeric(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
clean_label("Broadcast.quality...audio")
clean_label(c("ratings_Camera.work", "ratings_Talent...analysis"),
prefix = "ratings_")
Clear the active brand
Description
Resets every brand_* option so charts and reports return to the neutral
ezrsurvey defaults.
Usage
clear_brand()
Value
Invisibly TRUE.
See Also
Other brand:
brand_info(),
pal_brand(),
scale_fill_brand(),
use_brand()
Examples
clear_brand()
Delete saved cross-tab checkpoints
Description
Removes the checkpoint files that crosstab_banner(checkpoint = TRUE) keeps
under tools::R_user_dir(). A finished run clears its own checkpoint, so
anything left is from a run that was interrupted and never repeated; this
empties the folder in one call.
Usage
clear_checkpoints()
Details
Only checkpoints the package named for itself are stored there. A checkpoint
you pointed somewhere yourself (checkpoint = "my-run.rds") is your file and
is never touched, by this function or by a completed run.
Value
Invisibly the number of files removed.
See Also
crosstab_banner(), clear_weights_cache().
Other summaries:
calc_percentage(),
calc_percentage_batch(),
calc_percentage_multi(),
calc_summary(),
crosstab(),
crosstab_banner()
Examples
withr::with_envvar(c(R_USER_CACHE_DIR = tempdir()), clear_checkpoints())
Forget cached survey weights
Description
Empties the session's cache of computed weight vectors. Weighting the same rows under the same scheme always gives the same numbers, so ezrsurvey works them out once and reuses them; a table crossing every question against every group would otherwise re-run the raking for each cell.
Usage
clear_weights_cache()
Details
The cache keys on the weighting columns' own contents, so editing the data
produces different weights without any action from you. Clearing it by hand
is only needed to reclaim memory, or after changing a weighting variable
in place inside an object the cache has already seen. clear_weights()
clears it too.
Value
TRUE, invisibly.
See Also
set_weights(), weight_vector().
Other weighting:
get_weights(),
set_weights(),
weight_vector()
Examples
clear_weights_cache()
Compare a metric between two datasets (e.g. two events or waves)
Description
Joins a current and a previous table on a key column and computes the
difference of a metric – for example feature performance from two
ipm_model() outputs, or pct from two calc_percentage() tables for two
events. The result feeds straight into plot_diff().
Usage
compare_values(current, previous, by = "feature", value = "performance")
Arguments
current, previous |
Data frames sharing a key column and a metric column. |
by |
Name of the key column to join on. Default |
value |
Name of the metric column to compare. Default |
Details
The join is a left join keyed on by with previous on the left, so the row
set follows the previous period and difference is current - previous (a
positive number means it went up). Keys present only in current are dropped;
keys missing from current get an NA difference. The inputs are deliberately
generic two-column-or-more tables, so the same function compares feature
performance from two ipm_model() runs, pct from two calc_percentage()
tables for two events, or any other keyed metric.
Value
A tibble with the key column, previous, current
and difference (current - previous).
See Also
plot_diff(), ipm_model(), calc_percentage().
Other compare:
plot_diff()
Examples
a <- data.frame(feature = c("price", "quality"), performance = c(3.1, 4.2))
b <- data.frame(feature = c("price", "quality"), performance = c(2.8, 4.4))
compare_values(current = b, previous = a)
Convert amounts between currencies
Description
Converts monetary amounts from one currency to another using a table of
exchange rates. By default it uses the bundled currency_rates snapshot
(units per US dollar); pass your own rates for up-to-date or custom figures.
Because rates share the USD base, any pair is converted as a cross-rate
through USD automatically (e.g. EUR to CNY goes EUR -> USD -> CNY in one call).
amount, from and to are vectorised and recycled, so you can convert a
whole column with per-row source currencies at once.
Usage
convert_currency(amount, from, to = "USD", rates = NULL)
Arguments
amount |
Numeric amounts (text like |
from |
Source currency code(s), e.g. |
to |
Target currency code(s). Defaults to |
rates |
Exchange rates: |
Details
Each rate is stored as units of the currency per 1 US dollar, so a conversion
is amount / rate(from) * rate(to) – which means any pair is handled as a
cross-rate through USD without you doing anything. The bundled
currency_rates table is a dated, approximate snapshot meant for convenience,
not live trading; for accuracy pass your own rates (a named vector or a
currency/per_usd data frame). Amounts are coerced with ensure_numeric(),
codes are upper-cased and resolved through a small alias map ("RMB" ->
"CNY", "EURO" -> "EUR", ...), and any unknown code yields NA with a
warning rather than a silent wrong number.
Value
A numeric vector of converted amounts; unknown currency codes yield
NA with a warning.
See Also
add_currency(), list_currencies(), currency_rates.
Other currency:
add_currency(),
list_currencies()
Examples
convert_currency(100, "EUR", "USD")
convert_currency(c(100, 50), from = c("EUR", "GBP"), to = "USD")
convert_currency(100, "EUR", "CNY") # cross-rate via USD
convert_currency(100, "EUR", "RMB") # alias -> CNY, same result
Country to region lookup
Description
A tidy lookup table mapping country names to a world region and a finer
subregion, used by recode_region() / add_region() to turn a country
column into regions. Each country also carries its ISO 3166-1 codes, so a
result can be reported against the standard.
Usage
country_region
Format
A tibble with 255 rows and 5 columns, one per entry in ISO 3166-1 that has a UN M49 grouping, plus Kosovo:
- country
Country name.
- iso2
ISO 3166-1 alpha-2 code (e.g.
"DE").NAfor Kosovo, which has no code of its own.- iso3
ISO 3166-1 alpha-3 code (e.g.
"DEU").- region
World region (Africa, Asia, Europe, Middle East, North America, Oceania, South America).
- subregion
Finer subregion (e.g. Western Europe, East Asia).
Note that Namibia's alpha-2 code is the two letters "NA", not a missing
value, which is worth knowing before filtering on the column.
Source
Countries and codes are ISO 3166-1. The regions are the package's
own grouping, which follows the UN M49 sub-regions but treats the Middle
East as a region and splits the Americas north and south, because that is
how consumer research reports them. See data-raw/make_country_region.R.
See Also
recode_region(), add_region().
Other data:
currency_rates,
podracing_survey,
shopping_survey
Examples
head(country_region)
recode_region("Germany")
Cross-tabulate two survey questions
Description
Builds a crosstab from two categorical columns: x forms the rows and y the
columns. The cell contents are chosen with cell – counts or row/column/total
percentages – or, when a numeric value column is supplied, an aggregate of
that column (e.g. the mean spend) for each x by y combination. Registered
orders (see register_order()) are applied to x and y automatically, and
a factor column keeps its own level order when no order is registered.
Usage
crosstab(
data = NULL,
x,
y,
cell = c("count", "row_pct", "col_pct", "total_pct"),
value = NULL,
fn = mean,
wide = TRUE,
digits = NULL,
na_rm = TRUE,
drop = NULL,
weights = NULL
)
Arguments
data |
A data frame. |
x |
Row variable (unquoted). |
y |
Column variable (unquoted). |
cell |
What to put in each cell when |
value |
Optional numeric column (unquoted) to aggregate per cell instead of counting. |
fn |
Aggregation function used with |
wide |
If |
digits |
Decimal places for percentage / aggregated cells. Default |
na_rm |
Drop blanks / non-answers in |
drop |
Optional character vector of answer values to remove from both |
weights |
Survey weighting: |
Details
Choose what the cells mean with cell: "row_pct" makes each row sum to
100 (the distribution of y within each x), "col_pct" makes each
column sum to 100, "total_pct" is the share of the whole table, and
"count" is the raw frequency. Supplying a numeric value switches the cells
to an aggregate of that column – by default the mean – which answers
questions like "what is the average NPS for each region by gender?". Blanks
and non-answers in x/y are dropped when na_rm = TRUE. Any registered
orders (register_order()) set the row/column ordering automatically; a
factor without one keeps its own level order; anything else stays in data
order.
Value
A tibble: wide (x plus one column per y level) or
long (x, y, value). The long form refuses an x or y that is itself
called value, since the two columns would share a name.
See Also
calc_percentage(), compare_values(), register_order().
Other summaries:
calc_percentage(),
calc_percentage_batch(),
calc_percentage_multi(),
calc_summary(),
clear_checkpoints(),
crosstab_banner()
Examples
# counts
crosstab(podracing_survey, demo_gender, region)
# row percentages: gender split within each region (each row ~ 100)
crosstab(podracing_survey, region, demo_gender, cell = "row_pct")
# mean NPS for each region x gender cell
crosstab(podracing_survey, region, demo_gender, value = nps_value, fn = mean)
Build a master banner (cross-tab) table
Description
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.
Usage
crosstab_banner(
data = NULL,
rows,
cols,
cell = c("auto", "pct", "count", "mean", "diff"),
stats = c("mean", "median", "sd", "p25", "p75"),
total = TRUE,
digits = NULL,
na_rm = TRUE,
drop = NULL,
weights = NULL,
max_levels = 20,
long = FALSE,
flextable = FALSE,
checkpoint = NULL,
confirm = NULL
)
Arguments
data |
A data frame. If omitted, the session default ( |
rows |
Stub variables, down the side (tidyselect, e.g.
|
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: |
stats |
For numeric questions, which statistics form the block. Any of
|
total |
Include the whole-sample Overall column. Default |
digits |
Decimal places. |
na_rm |
Drop blanks / non-answers in the questions and banner variables.
Default |
drop |
Answer values to remove before tabulating (see |
weights |
Survey weighting: |
max_levels |
When |
long |
If |
flextable |
If |
checkpoint |
Save each question as it finishes, so re-running the same
call picks up where an interrupted run stopped. |
confirm |
When |
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); those stub rows are unweighted. Across the
top, a binary-encoded column gives one column of the respondents who ticked
it, and the columns of a multi-select block share one spanner named after the
block. Those columns overlap, since a respondent can tick several. A lone
binary column is used across the top only, never as a stub.
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.
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.
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))
# numeric questions become a mean / median / sd / quartile block
crosstab_banner(podracing_survey,
rows = c(nps_value, demo_age),
cols = demo_gender)
# each cell as its difference from the Overall column
crosstab_banner(podracing_survey, rows = satis_return,
cols = region, cell = "diff")
# full variable-by-variable banner: just pass the data frame
crosstab_banner(podracing_survey)
Currency exchange-rate snapshot
Description
A dated, approximate reference table of exchange rates used by
convert_currency() / add_currency() when no custom rates are supplied.
Rates are expressed as units of the currency per 1 US dollar (base USD).
These are a convenience snapshot, not live rates – pass your own rates
to the conversion helpers when accuracy matters.
Usage
currency_rates
Format
A tibble with one row per currency and columns:
- currency
ISO 4217 code (e.g.
"EUR").- name
Currency name.
- per_usd
Units of the currency per 1 US dollar.
The snapshot date is stored in attr(currency_rates, "snapshot_date").
Source
Approximate reference snapshot. See
data-raw/make_currency_rates.R.
See Also
convert_currency(), add_currency(), list_currencies().
Other data:
country_region,
podracing_survey,
shopping_survey
Examples
head(currency_rates)
attr(currency_rates, "snapshot_date")
Survey precision diagnostics for one or more columns
Description
The headline diagnostics wrapper: for each selected column it auto-detects whether it is a point estimate (numeric, e.g. a 1-5 rating) or a proportion (categorical), and returns a tidy table of sample size, estimate, standard error, relative standard error and margin of error – i.e. the whole appendix "Data info" block as one call.
Usage
diagnose(
data = NULL,
...,
type = c("auto", "mean", "prop"),
by = NULL,
z = 1.96,
digits = 2
)
Arguments
data |
A data frame. |
... |
Columns to diagnose, using tidyselect (e.g.
|
type |
Force the estimate type: |
by |
Optional grouping column(s); diagnostics are computed within group. |
z |
Margin-of-error multiplier passed to |
digits |
Decimal places for the numeric output columns. Defaults to |
Details
For categorical columns the reported estimate is the largest answer
category's share, which gives a concrete +/- percentage-point margin to
quote in a report footnote.
Each column is classified (or forced via type) as a point estimate or a
proportion. For numeric columns the estimate is the mean and the error is in
rating points; for categorical columns the estimate is the largest answer
category's share, which gives a single concrete +/- percentage-point
margin to quote (the largest category is also the worst case among the
observed categories, so it is a sensible headline). The precision column is
the five-band rating from rse_rating(). This is the per-variable form of the
report-appendix "Data info" block; for the narrative bullet-point version see
precision_summary().
Value
A tibble with one row per column (per group), with
columns variable, type, unit, n, estimate, se, rse, moe and
precision. For type == "mean", unit is "points"; for proportions it
is "ppt" (percentage points) and estimate is a percentage.
See Also
precision_summary(), rse_rating(), se_mean(), se_prop().
Other diagnostics:
margin_of_error(),
precision_summary(),
rse(),
rse_rating(),
se_mean(),
se_prop()
Examples
diagnose(podracing_survey, demo_gender, nps_value)
diagnose(podracing_survey, starts_with("ratings_"))
Drop unwanted answer categories from a question
Description
Removes specific answer values – typically catch-all or uninformative options
such as "Other", "Don't know" or "Not applicable" – by turning them into
NA, so they fall out of counts, percentages and charts and the remaining
percentages re-base on the answers you keep. The companion to na_blank()
(which targets blanks and standard non-answers): use drop_items() for the
substantive categories you simply do not want to show.
Usage
drop_items(x, items, trim = TRUE)
Arguments
x |
A character (or factor) vector. |
items |
Character vector of exact answer values to drop. Matching is case-insensitive. |
trim |
Whether to trim surrounding whitespace before comparing. Defaults
to |
Details
x is coerced to character (so factors are handled) and, by default,
whitespace-trimmed; any value equal (ignoring case) to one of items becomes
NA. The summary helpers (calc_percentage(), calc_percentage_multi(),
calc_percentage_batch()) and crosstab() take a drop = argument that
applies this for you before counting, so the kept answers re-base to ~100%;
set a session-wide default with ezrsurvey_options(drop_answers = ...).
Value
A character vector the same length as x, with any value matching
items replaced by NA.
See Also
na_blank(), calc_percentage().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
drop_items(c("Yes", "No", "Other", "Don't know"),
items = c("Other", "Don't know"))
Open the ezrsurvey profile for editing
Description
Opens your ezrsurvey YAML profile in the editor (like
usethis::edit_r_profile() for .Rprofile), creating it from a template
first if it does not exist. After saving, reload it with
load_ezrsurvey_profile() or by restarting the session.
Usage
edit_ezrsurvey_profile(path = NULL)
Arguments
path |
Profile path. If |
Value
Invisibly the path opened.
See Also
use_ezrsurvey_profile(), save_ezrsurvey_profile(),
load_ezrsurvey_profile().
Other config:
apply_order(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
tmp <- tempfile(fileext = ".yml")
edit_ezrsurvey_profile(tmp)
Coerce text to numeric, salvaging embedded numbers
Description
A defensive helper for the common survey-export headache where a column that
should be numeric arrives as text – "25 years", "8 - very likely",
"3.5/5". It returns x unchanged if it is already numeric; otherwise it
pulls the first number out of each value (via a digit pattern) and coerces to
numeric, leaving genuinely unparseable entries as NA. The ezrsurvey
functions that need numbers (e.g. calc_nps(), calc_summary()) call this
for you, so they "just work" on lightly messy data.
Usage
ensure_numeric(x, name = NULL, quiet = FALSE)
Arguments
x |
A vector. Numeric input is returned as-is. |
name |
Optional column/argument name, used only to make the message clearer. |
quiet |
If |
Details
The first numeric token in each value is extracted with the pattern
-?[0-9]*\.?[0-9]+, which captures negatives and decimals but takes only the
first number it finds – so "8 - very likely" becomes 8, not -8. A
value that is genuinely numeric already is returned untouched (no copy, no
message). When quiet = FALSE a single informative message reports that
coercion happened and how many values could not be parsed; the internal
callers (calc_nps(), calc_summary(), ipm_model(), bin_numeric(), ...)
pass quiet = TRUE so they don't spam your console. Truly blank entries
(""/NA) are not counted as parse failures.
Value
A numeric vector the same length as x.
See Also
recode_age(), recode_likert(), na_blank().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
ensure_numeric(c("25 years", "31", "forty"), quiet = TRUE)
ensure_numeric(c("8 - very likely", "10", "3.5/5"), quiet = TRUE)
ensure_numeric(c(1, 2, 3)) # already numeric, returned as-is
Copy the worked example report into a folder
Description
Drops the package's complete worked example next to your data: a full
Quarto report over the bundled podracing_survey (every chart type, real
narrative) plus the matching slide-deck script on the officer path. Render
/ run them as they are, then swap in your own data.
Usage
example_report(dir, overwrite = FALSE)
Arguments
dir |
Destination folder, created if missing. |
overwrite |
Overwrite existing files of the same names. Defaults to
|
Details
Two files are copied: podracing-report.qmd (render with
quarto render podracing-report.qmd) and podracing-deck.R
(run with Rscript podracing-deck.R;
writes a 16:9 deck to ezrsurvey-outputs/). Unlike the blank
scaffold_report()
skeletons, the example ships finished narrative over the bundled data, so
you can see every visual and slide element in a finished state before
adapting it.
Value
Invisibly the paths written.
See Also
scaffold_report() for blank skeletons, report_deck().
Other reporting:
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
dir <- file.path(tempdir(), "ezrsurvey-example")
example_report(dir)
list.files(dir)
Export a per-question summary workbook (table + chart per sheet)
Description
Writes one Excel workbook with a worksheet per question, each holding that
question's summary table and its chart. Numeric questions get a
calc_summary() table and a histogram; categorical questions get a
calc_percentage() table and a plot_bars() chart; check-all-that-apply
blocks get a calc_percentage_multi() table (based on the respondents who
picked any option) and a bar chart. This is the "hand the client a tabbed
workbook" counterpart to the slide/Word builders (report_deck()). Requires
the suggested openxlsx2 package (the only xlsx writer here that can embed
images).
Usage
export_summary_xlsx(
data = NULL,
...,
path,
by = NULL,
chart = TRUE,
sort = c("none", "desc", "asc"),
digits = 0,
weights = NULL,
width = 6,
height = 3.4,
confirm = NULL
)
Arguments
data |
A data frame. If omitted, the session default ( |
... |
Variables to summarise, using tidyselect (e.g.
|
path |
Output |
by |
Optional grouping column(s) for the tables (passed to
|
chart |
Include the chart beneath each table. Default |
sort |
Level ordering for categorical tables, passed to
|
digits |
Decimal places for percentages. Default |
weights |
Survey weighting, passed to the table and chart helpers (see
|
width, height |
Chart size in inches. Default |
confirm |
When no variables are named, show which questions were chosen
and which were skipped, and wait for a yes before writing. |
Details
Worksheets are named from each question (cleaned to valid, unique Excel names).
The table is written from cell A1; the chart, when included, is rendered to a
temporary PNG and embedded a few rows below it. A numeric column (after
ensure_numeric()) is treated as a scale question (summary + histogram);
columns that share a prefix and each hold a single option or blank (e.g.
motivations_*) are treated as one check-all-that-apply question; anything
else is categorical (percentages + bar chart). With no ..., every question in
the data is written and identifier / free-text columns are skipped (and named
in a message). For a single table or a pre-named list of tables in one workbook
without charts, see export_xlsx() / save_data().
Value
Invisibly the path written.
See Also
export_xlsx(), save_data(), report_deck(),
calc_percentage_batch().
Other save:
export_xlsx(),
save_data(),
save_output(),
save_plot()
Examples
# named questions
tmp <- tempfile(fileext = ".xlsx")
export_summary_xlsx(podracing_survey, demo_gender, satis_return, nps_value,
path = tmp)
# or every question at once (identifier / free-text columns are skipped)
tmp2 <- tempfile(fileext = ".xlsx")
export_summary_xlsx(podracing_survey, path = tmp2)
Export several tables to one Excel workbook, a tab each
Description
A quick way to drop a handful of summaries into a single .xlsx, one per
worksheet – e.g. export_xlsx(calc_percentage(d, a), calc_percentage(d, b), path = "out.xlsx"). Tabs are named from the argument names you give, else
from each table's question/first column, else Sheet1, Sheet2, ...
Usage
export_xlsx(..., path, sheet_names = NULL)
Arguments
... |
Data frames to write, one per tab. Name them to set tab names
(e.g. |
path |
Output |
sheet_names |
Optional character vector of tab names (overrides argument names). |
Details
Each argument becomes one worksheet. Tab names are taken from the argument
names you give (gender = ...), otherwise from each table's variable column
or first column, otherwise Sheet1, Sheet2, ...; they are then cleaned to
valid, unique Excel names (<= 31 characters, with [ ] : * ? / \\ stripped).
This is the quick way to drop a set of summaries into one workbook for a
colleague. Requires the suggested writexl package.
[ ]: R:%20
Value
Invisibly path.
See Also
save_data() for a single table or a pre-named list.
Other save:
export_summary_xlsx(),
save_data(),
save_output(),
save_plot()
Examples
tmp <- tempfile(fileext = ".xlsx")
export_xlsx(
gender = calc_percentage(podracing_survey, demo_gender),
calc_percentage(podracing_survey, demo_job),
path = tmp
)
file.exists(tmp)
Get or set ezrsurvey defaults
Description
ezrsurvey reads a handful of defaults from R options (prefixed ezrsurvey.),
so you can tune behaviour once instead of repeating arguments. Call with no
arguments to see the current effective values; call with name = value pairs
to set them for the session. Persist them across sessions with a YAML profile
(see use_ezrsurvey_profile()).
Usage
ezrsurvey_options(...)
Arguments
... |
Either nothing (to read all values) or named |
Details
Recognised options:
pct_axis_unitRounding step for percentage y-axes (default
25).pct_axis_maxFixed percentage y-axis maximum, e.g.
100;NULL(default) means dynamic vianice_max().bar_cols_max_items,bar_cols_max_labelThresholds that switch
plot_bars()(orientation = "auto") from vertical columns to horizontal bars: more thanbar_cols_max_itemsbars (6) or any label longer thanbar_cols_max_labelcharacters (12).bar_wrap_cols,bar_wrap_barsstringr::str_wrap()widths used byplot_bars()for column (12) and bar (28) labels.bar_label_size,bar_size_step,bar_size_minData-label text sizing in
plot_bars(): base size (3.5), reduction per item past the item threshold (0.15) and the floor (2.4).bar_width,bar_ref_itemsBar thickness. Bars are drawn at
bar_width(0.66) of a category slot when a chart hasbar_ref_items(6) bars, and the fraction scales with the bar count so the drawn thickness stays the same on every chart. Raisebar_ref_itemsfor thinner bars throughout, lower it for chunkier ones.age_breaks,age_labelsDefault bands used by
recode_age().na_answersStrings treated as non-answers by
na_blank().drop_answersAnswer values dropped by the
drop =argument ofcalc_percentage()and friends whendropis not given;NULL(default) means drop nothing. Seedrop_items().generation_schemeDefault scheme for
recode_generation().current_yearReference year for age-to-cohort conversion;
NULLuses the system year.default_byDefault grouping column name(s) applied by
calc_percentage()/calc_percentage_multi()whenbyis omitted;NULL(default) means no default grouping.brand_colors,brand_color_primaryOrganisation brand colours: a vector of accent hexes and the primary accent used as the default single-series fill. Usually set by
use_brand(), but can be set by hand or in a profile.NULL(default) keeps the neutral ezrsurvey look.brand_font_major,brand_font_minorBrand heading and body typefaces.
brand_font_minorbecomes the defaultbase_familyoftheme_ezrsurvey()when the font is installed on this machine.brand_fonts_enabledSet
FALSEto keep brand colours but ignore brand fonts (defaultTRUE).brand_template_pptx,brand_template_docxPaths to the brand PowerPoint / Word template used as the default reference document by
report_new(),report_deck()andscaffold_report(). These are machine-specific absolute paths – if you persist them, prefer the project-level.ezrsurvey.ymlprofile over the user-level one.progressWhether the slow helpers report which item they are on.
"auto"(default) reports in an interactive session and stays silent in scripts, vignettes andR CMD check;TRUEorFALSEforce it either way. Seecrosstab_banner().confirmWhether a call that picks its own variables shows the selection and waits for a yes before a long run.
"auto"(default) asks in an interactive session and never asks in a script;TRUEorFALSEforce it either way. Seecrosstab_banner().output_dirFolder that a bare output file name is written into, created on demand. The default
"."writes it where it is named: in the working directory. Set a folder, say"outputs", andsave_plot(p, "chart.png")writesoutputs/chart.png, so a script's results collect in one place. A path that names a directory ("./chart.png","charts/chart.png", anything absolute) is always written exactly where it says.
Options are ordinary R options under the ezrsurvey. prefix, so anything you
can do with options() works here too, and a setting lasts for the session.
Reading (ezrsurvey_options() with no arguments) returns every recognised
option's current effective value; setting returns the previous values
invisibly, so you can restore them. To make settings permanent, write them to
a YAML profile – edit it with edit_ezrsurvey_profile() or dump the current
session with save_ezrsurvey_profile() – which is loaded automatically at
package start-up.
Value
When reading, a named list of all current values. When setting, the previous values, invisibly.
See Also
use_ezrsurvey_profile(), load_ezrsurvey_profile(),
reset_ezrsurvey_options().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
ezrsurvey_options() # view all defaults
ezrsurvey_options(pct_axis_max = 100)
ezrsurvey_options()$pct_axis_max # 100
reset_ezrsurvey_options() # back to defaults
Profile file locations ezrsurvey looks in
Description
At load time ezrsurvey reads a YAML profile from each of these paths in turn (later paths override earlier ones), if present: the per-user config directory, your home directory, then the current project.
Usage
ezrsurvey_profile_paths()
Value
A character vector of candidate profile paths.
See Also
use_ezrsurvey_profile(), load_ezrsurvey_profile().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
ezrsurvey_profile_paths()
Generational-cohort definitions
Description
Returns the birth-year boundaries for a named generational scheme, for use by
recode_generation(). The default "pew" scheme follows the widely cited
Pew Research Center cohort definitions.
Usage
generation_scheme(scheme = c("pew"))
Arguments
scheme |
Scheme name. Currently |
Details
The "pew" scheme uses the Pew Research Center boundaries: Silent (1928–45),
Baby Boomer (1946–64), Gen X (1965–80), Millennial (1981–96), Gen Z
(1997–2012) and Gen Alpha (2013+). To use different cut-offs, build your own
tibble with from and label columns and pass it to recode_generation()'s
scheme argument.
Value
A tibble with label, from (first birth year) and
to (last birth year; Inf for the open-ended youngest cohort).
See Also
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
generation_scheme("pew")
Get, check or clear the default dataset
Description
Companions to use_dataset() for inspecting and resetting the session's
default dataset.
Usage
get_dataset()
has_dataset()
clear_dataset()
dataset_vars()
Details
has_dataset() is the safe way to check before calling get_dataset(), which
errors when nothing is set. clear_dataset() removes the default so that
subsequent calls require an explicit data again – useful at the end of a
script or between analyses of different datasets.
Value
get_dataset() returns the default data frame (error if none is set);
has_dataset() returns a logical; clear_dataset() returns TRUE
invisibly; dataset_vars() returns a character vector of column names.
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
has_dataset()
use_dataset(podracing_survey)
has_dataset()
nrow(get_dataset())
clear_dataset()
Get the levels of a registered order
Description
Get the levels of a registered order
Usage
get_order(name)
Arguments
name |
Order name. |
Value
The character vector of levels.
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order("yesno", c("No", "Yes"))
get_order("yesno")
remove_order("yesno")
Inspect or clear the session weighting scheme
Description
Companions to set_weights(): read the stored scheme, test whether one is set,
or remove it.
Usage
get_weights()
has_weights()
clear_weights()
Details
has_weights() is the safe check before get_weights(), which errors when no
scheme is set. clear_weights() turns weighting off again, so the helpers
return purely unweighted results.
Value
get_weights() returns the scheme (a named list of target vectors;
error if none is set); has_weights() returns a logical; clear_weights()
returns TRUE invisibly.
See Also
set_weights(), weight_vector().
Other weighting:
clear_weights_cache(),
set_weights(),
weight_vector()
Examples
has_weights()
set_weights(c(variable = "region", Europe = 0.5, "North America" = 0.5))
get_weights()
clear_weights()
Build an importance / performance model
Description
Combines driver importance (against outcome) with
feature performance (mean rating) into the tidy table consumed by
plot_ipm(). Worded rating columns are recoded to 1-5 automatically.
Usage
ipm_model(
data = NULL,
outcome,
rating_prefix,
method = c("rwa", "forest", "correlation"),
recode = TRUE,
likert_levels = c("Very bad", "Bad", "Ok", "Good", "Very good")
)
Arguments
data |
A data frame. |
outcome |
The outcome column (unquoted), e.g. |
rating_prefix |
Column-name prefix identifying the rating block, e.g.
|
method |
How to measure importance, passed to |
recode |
If |
likert_levels |
Scale wordings passed to |
Details
An importance/performance model answers two questions per feature at once:
how much does it drive the outcome (importance, via calc_importance()) and
how well are we doing on it (performance, the mean 1–5 rating). Plotting one
against the other (plot_ipm()) reveals priorities: high-importance,
low-performance features are where to invest. Worded rating columns are mapped
to 1–5 with recode_likert() automatically (recode = TRUE); the prefix is
stripped from feature names; and perf_class buckets performance into a 1–5
factor by its integer part (a 3.57 mean is band 3, not 4) for colouring.
Importance comes from calc_importance(), so method chooses between
relative weights (the default, requiring the suggested rwa package), a
random forest and a plain correlation.
Value
A tibble with feature, importance,
performance and perf_class (the performance band as a 1-5 factor, from
its integer part so a 3.57 mean sits in band 3, used for colouring).
See Also
calc_importance(), plot_ipm(), compare_values().
Other modelling:
calc_importance(),
calc_nps()
Examples
ipm_model(podracing_survey, nps_value, "ratings_")
Percent label formatter
Description
Returns a function that turns numbers into percent strings, e.g. 42
becomes "42%". The input is assumed to already be on a 0-100 scale (as
produced by calc_percentage()), not a 0-1 proportion.
Usage
label_pct(digits = 0, suffix = "%")
Arguments
digits |
Number of decimal places to keep. Defaults to |
suffix |
String appended after the number. Defaults to |
Details
label_pct() returns a function (a closure), not formatted strings – this
is the form ggplot2 scales expect for their labels argument. The number is
rounded to digits decimal places with formatC() and suffix appended.
Because the input is assumed to be on a 0–100 scale, label_pct()(42) is
"42%", not "4200%".
Value
A function suitable for the labels argument of a ggplot2 scale or
for use with geom_text().
See Also
Other scales:
nice_max(),
scale_y_pct()
Examples
f <- label_pct()
f(c(0, 33.4, 100))
label_pct(1)(33.45)
List the currencies in a rate table
Description
List the currencies in a rate table
Usage
list_currencies(rates = NULL)
Arguments
rates |
Rate table; |
Details
A quick way to see which codes convert_currency() will accept from the
bundled snapshot (or from a rates table you pass). Aliases such as "RMB"
are not listed – they resolve to their ISO code (here "CNY").
Value
A character vector of currency codes.
See Also
currency_rates, convert_currency().
Other currency:
add_currency(),
convert_currency()
Examples
list_currencies()
List registered orders
Description
List registered orders
Usage
list_orders()
Value
A tibble with name, n_levels, vars and
prefixes (the last two comma-joined).
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order("yesno", c("No", "Yes"), vars = "agree")
list_orders()
remove_order("yesno")
Available Quarto report templates
Description
Available Quarto report templates
Usage
list_report_templates()
Value
A character vector of the output formats ezrsurvey ships a Quarto skeleton for.
See Also
Other reporting:
example_report(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
list_report_templates()
Load ezrsurvey defaults from a YAML profile
Description
Reads a YAML file of option: value pairs and applies them with
ezrsurvey_options(). Called automatically when the package loads (over the
standard ezrsurvey_profile_paths()); call it manually to load a specific
file. Requires the suggested yaml package; without it, the function is a
no-op.
Usage
load_ezrsurvey_profile(path = NULL, quiet = TRUE)
Arguments
path |
Profile path(s). If |
quiet |
If |
Value
Invisibly TRUE if any profile was applied, else FALSE.
See Also
use_ezrsurvey_profile() to create a template.
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
tmp <- tempfile(fileext = ".yml")
writeLines("pct_axis_max: 100", tmp)
load_ezrsurvey_profile(tmp, quiet = FALSE)
ezrsurvey_options()$pct_axis_max
reset_ezrsurvey_options()
Margin of error from a standard error
Description
z * se, the half-width of a confidence interval. The default z = 1.96
gives an approximate 95% interval; the survey reports used the 2 * se
rule of thumb, which is z = 2.
Usage
margin_of_error(se, z = 1.96)
Arguments
se |
A standard error (scalar or vector). |
z |
The critical value / multiplier. Defaults to |
Details
A confidence interval is the estimate plus or minus this margin. z = 1.96
gives the standard 95% interval; z = 2 reproduces the "two standard errors"
rule of thumb often quoted in survey reports; z = 2.58 gives 99%. The result
is on the same scale as se, so for a proportion error in percentage points,
pass se_prop(p, n, pctp = TRUE).
Value
The +/- margin of error, on the same scale as se.
See Also
se_mean(), se_prop(), diagnose().
Other diagnostics:
diagnose(),
precision_summary(),
rse(),
rse_rating(),
se_mean(),
se_prop()
Examples
margin_of_error(se_prop(0.33, 1184, pctp = TRUE)) # in percentage points
margin_of_error(0.02, z = 2)
Mark a single value on a plot
Description
Adds a reference line (and optional label) at a single value – the "you are here" marker used on the NPS and quality gauges.
Usage
mark_value(
plot,
value,
axis = c("x", "y"),
colour = "black",
linewidth = 1,
label = NULL,
...
)
Arguments
plot |
A ggplot object. |
value |
Numeric position of the marker. |
axis |
Axis the value is on: |
colour, linewidth |
Line appearance. |
label |
Optional text label drawn at the marker. |
... |
Passed to |
Value
The plot with the marker added.
See Also
Other decisions:
annotate_bands(),
bands_rating_3(),
rescale_bands()
Examples
# a target line across the percentage axis of a bar chart
calc_percentage(podracing_survey, demo_gender) %>%
plot_bars() %>%
mark_value(20, axis = "y", label = "Target 20%")
Convert blank and boilerplate non-answers to NA
Description
Survey exports are littered with empty strings and standard "non-answer"
options such as "Prefer not to answer". This helper turns those into real
NA values so they drop out of counts and summaries, replacing the
repetitive filter(x != "", x != "Prefer not to answer") idiom.
Usage
na_blank(x, also = ezrsurvey_default("na_answers"), trim = TRUE)
Arguments
x |
A character (or factor) vector. |
also |
Additional exact strings to treat as missing. Defaults to the
|
trim |
Whether to trim surrounding whitespace before comparing.
Defaults to |
Details
The input is coerced to character (so factors are handled), optionally
whitespace-trimmed, and any value equal to "" or to one of also becomes
NA. The default also reads the na_answers option, so you can change what
counts as a non-answer package-wide with
ezrsurvey_options(na_answers = ...). Most of the calc_* helpers call
na_blank() internally when na_rm = TRUE, so you usually get this clean-up
for free; call it directly when you want to blank a column in a pipeline.
Value
A character vector the same length as x, with blanks and
non-answers replaced by NA.
See Also
ensure_numeric(), ezrsurvey_options().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
na_blank(c("Yes", "", "Prefer not to answer", "No"))
# add your own non-answers
na_blank(c("a", "n/a", "N/A"), also = c("n/a", "N/A"))
Round an axis maximum up to a "nice" value
Description
Picks the smallest multiple of unit that is greater than or equal to
max(x). This reproduces the dynamic y-axis trick used throughout the
original survey reports, where bar charts are given a tidy ceiling in units
of 25 (percentages) or 5 (NPS counts) so that data labels never collide with
the top of the panel.
Usage
nice_max(x, unit = 25, pad = 0)
Arguments
x |
A numeric vector. |
unit |
Size of the rounding step (e.g. |
pad |
Extra headroom added to the result, in the same units as |
Details
The ceiling is (floor(max(x) / unit) + 1) * unit + pad: the next
multiple of unit strictly above max(x), always leaving headroom even
when the max already sits exactly on a multiple (e.g. nice_max(75) is
100, not 75). Use pad for additional headroom on top of that, e.g.
for annotations above the tallest bar. An all-NA logical column (a common
shape for an empty survey field) is tolerated and returns NA. This is the
engine behind scale_y_pct() and the percentage plot wrappers, which is
why their bars never quite touch the top of the panel.
Value
A single numeric value: the padded, rounded-up ceiling. Returns NA
if x is empty or all NA.
See Also
Other scales:
label_pct(),
scale_y_pct()
Examples
nice_max(c(12, 63, 40))
nice_max(80, unit = 25) # already need >75, so jumps to 100
nice_max(75, unit = 25) # exact multiple still advances, for headroom
nice_max(c(8, 17), unit = 5, pad = 10) # next multiple of 5 (20) + 10
Classify Net Promoter Score answers into groups
Description
Collapses an 0-10 "how likely to recommend" question into the three standard NPS groups: detractors (0-6), passives (7-8) and promoters (9-10).
Usage
nps_group(x, labels = FALSE)
Arguments
x |
A numeric vector of 0-10 ratings (character input is coerced). |
labels |
If |
Details
The signed -1/0/1 coding is deliberate: the mean of it, times 100, is
exactly the Net Promoter Score (% promoters minus % detractors), which is how
calc_nps() computes the headline number. Inputs are run through
ensure_numeric() first, so worded answers like "9 - very likely" are
classified correctly. Values outside 0–10 (and NA) return NA.
Value
Either an integer vector (-1/0/1) or a character vector, the same
length as x. Out-of-range or missing values become NA.
See Also
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
nps_group(c(0, 6, 7, 8, 9, 10))
nps_group(c(3, 8, 10), labels = TRUE)
Find the order that applies to a variable
Description
Looks up the registered order for a column: an exact vars match wins,
otherwise the first matching prefixes entry. Used internally by
calc_percentage() to apply orders automatically; exposed so you can check
what would be applied.
Usage
order_for(var)
Arguments
var |
A column name. |
Value
The matching level vector, or NULL if none is registered.
See Also
register_order(), apply_order().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order("edu", c("low", "mid", "high"), prefixes = "edu_")
order_for("edu_level")
remove_order("edu")
Brand colour palette
Description
Returns the organisation's accent colours set by use_brand() (or the
brand_colors option), ready for manual scales or direct use. Without a
brand, it falls back to pal_sequential_blue so it always returns something
usable.
Usage
pal_brand(n = NULL)
Arguments
n |
Number of colours wanted. |
Details
Only the categorical brand accents live here. The semantic palettes (pal_rating, pal_nps) keep their red-amber-green vocabulary regardless of brand – recolouring "bad to good" with corporate accents would destroy the meaning the colours carry.
Value
A character vector of hex colours.
See Also
use_brand(), scale_fill_brand().
Other brand:
brand_info(),
clear_brand(),
scale_fill_brand(),
use_brand()
Examples
pal_brand() # sequential blue until a brand is set
pal_brand(2)
ezrsurvey colour palettes
Description
A small set of named, semantic palettes for survey reporting. Each is a
plain character vector of hex colours (some named) that you
can use directly or via the scale_*_rating() / scale_fill_nps() helpers.
Usage
pal_rating
pal_nps
pal_sequential_blue
pal_neutral
Format
Each palette is a character vector of hex colour strings:
pal_ratingFive-point red -> amber -> green scale for 1-5 ratings, named
"1".."5".pal_npsThree NPS-group colours, named
"-1","0","1"(detractor / passive / promoter).pal_sequential_blueFour-step sequential blue, light to dark, for ordered brand questions.
pal_neutralA single neutral grey used for unbranded single-series bars.
Details
These are the semantic colour vocabularies behind the plot helpers: red ->
amber -> green for ratings (worse to better), a matching three-colour NPS
scale, a sequential blue for ordered brand questions, and a neutral grey for
plain single-series bars. Use them directly, or via the
scale_fill_rating() / scale_fill_nps() ggplot2 scales.
pal_rating follows the same thresholds as bands_rating_3(): ratings of 1
and 2 are BAD (red), 3 is OK (amber), 4 and 5 are GOOD (green). Keeping the
two in step matters – a point coloured amber sitting inside a red band is
the kind of contradiction that quietly misleads a reader.
Value
Each palette is a character vector of hex colour strings, named by
the value it colours where that matters (pal_rating by rating "1" to
"5", pal_nps by NPS group "-1", "0", "1"), ready to pass as
values to a ggplot2 manual scale.
See Also
Other themes:
scale_fill_nps(),
scale_fill_rating(),
theme_ezrsurvey(),
theme_transparent()
Examples
pal_rating
scales::show_col(pal_rating)
Split a filename column into metadata columns
Description
Survey exports often encode metadata in the filename (e.g.
"podracing_wave1_NA_2026.csv"). This splits a filename column on a
separator into named metadata columns, dropping the file extension first.
Replaces the brittle str_split(file, "_")[[1]][n] indexing this saves you.
Usage
parse_filename(
data = NULL,
col = "file",
into,
sep = "_",
drop_ext = TRUE,
remove = FALSE
)
Arguments
data |
A data frame. |
col |
Name of the column holding the filename (string or unquoted).
Defaults to |
into |
Character vector of new column names, one per field you expect after splitting. |
sep |
Separator to split on (a fixed string, not a regex). Defaults to
|
drop_ext |
If |
remove |
If |
Details
Pairs naturally with read_folder(), whose file column carries the source
filename: split it once and you have event, wave, locale, year, etc. as real
columns to group by. The file extension is stripped first (drop_ext), the
split is on a fixed string (not a regex), and rows with fewer fields than
into are padded with NA so a stray filename never derails the parse.
Value
The data frame with the new metadata columns added.
See Also
Other import:
read_folder(),
select_prefix(),
select_suffix()
Examples
df <- tibble::tibble(file = c("podracing_wave1_NA_2026.csv"))
parse_filename(df, into = c("survey", "wave", "locale", "year"))
Bar chart of a percentage table (auto-laid-out)
Description
Plots the output of calc_percentage() (or calc_percentage_multi()) as a
labelled bar chart, with a tidy auto-scaled axis (nice_max()) and the
ezrsurvey theme. By default the layout is chosen for you: vertical columns
for a few short labels, horizontal bars for many or long ones, with long
labels wrapped, the text size stepped down as bars multiply, and the bars
ordered so the longest sits at the top (bars) or on the left (cols).
Usage
plot_bars(
data,
label = NULL,
value = pct,
orientation = c("auto", "cols", "bars"),
sort = c("auto", "none", "asc", "desc"),
wrap = NULL,
flip = NULL,
avg_line = FALSE,
axis_labels = FALSE,
unit = ezrsurvey_default("pct_axis_unit"),
max = ezrsurvey_default("pct_axis_max"),
fill = NULL,
title = NULL,
label_size = NULL
)
Arguments
data |
A data frame with a category column and a value column. |
label |
Category column (unquoted). If |
value |
Value column (unquoted). Defaults to |
orientation |
|
sort |
|
wrap |
Label wrap width in characters ( |
flip |
Deprecated back-compat shortcut: |
avg_line |
If |
axis_labels |
If |
unit |
Axis rounding step passed to |
max |
Optional fixed y-axis maximum (e.g. |
fill |
Bar fill colour. |
title |
Optional plot title. |
label_size |
Data-label text size. |
Details
Expects a summary table (from calc_percentage() and friends), not raw survey
rows. The label column is auto-detected as the first non-n, non-value column,
so a piped percentage table just works. The layout decisions all read from the
bar_* options (ezrsurvey_options()): orientation = "auto" switches to
horizontal bars once there are many or long labels, labels are wrapped to
bar_wrap_cols / bar_wrap_bars, the data-label size steps down with the
bar count, and sort = "auto" puts the longest bar at the top (bars) or on the
left (cols) – unless the label column is an ordered factor (a registered or
explicit order), which is preserved. The axis ceiling is chosen by nice_max()
/ the pct_axis_* options so data labels never collide with the panel top, and
the % axis is hidden unless axis_labels = TRUE. Add decision guidance with
annotate_bands().
Bars are drawn to a constant thickness regardless of how many there are
(bar_width / bar_ref_items, see ezrsurvey_options()), so a three-answer
chart and a ten-answer chart look like they belong in the same deck instead
of the first one's bars turning into slabs.
Value
A ggplot object.
See Also
calc_percentage(), scale_y_pct(), annotate_bands().
Other plots:
plot_gauges(),
plot_ipm(),
plot_nps(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_rating_grid(),
plot_stacked_rating()
Examples
# auto layout: few short labels -> vertical columns, largest on the left
calc_percentage(podracing_survey, demo_gender) %>% plot_bars()
# many long labels -> horizontal bars, wrapped, largest on top
calc_percentage(podracing_survey, fav_driver) %>% plot_bars()
# an ordinal scale keeps its order; force horizontal with orientation
calc_percentage(podracing_survey, demo_edu) %>%
plot_bars(orientation = "bars")
Diverging bar chart of differences
Description
Plots a column of differences (e.g. from compare_values()) as a sorted,
diverging horizontal bar chart: positives in green, negatives in amber, signed
value labels, and a zero reference line. This is the standard "what improved,
what slipped" change chart.
Usage
plot_diff(
data,
label = feature,
difference = difference,
limits = NULL,
digits = 2,
pos_colour = "#A7C23D",
neg_colour = "#FFCB3E",
title = NULL
)
Arguments
data |
A data frame with a label column and a difference column. |
label |
Category/label column (unquoted). Default |
difference |
Difference column (unquoted). Default |
limits |
Numeric length-2 y-axis limits. If |
digits |
Decimal places for the value labels. Default |
pos_colour, neg_colour |
Bar colours for positive / negative differences. |
title |
Optional plot title. |
Details
Bars are sorted by the difference and drawn horizontally (largest gain at the
top), coloured green for positive and amber for negative changes, with signed
value labels (+0.20 / -0.30) nudged to sit just outside each bar and a
zero reference line. When limits is NULL the y-axis is made symmetric
around zero from the data so gains and losses are visually comparable; pass
limits = c(-1, 1) (say) to fix it. Feed it the output of compare_values(),
or any data frame with a label column and a numeric difference column.
Value
A ggplot object.
See Also
Other compare:
compare_values()
Examples
a <- data.frame(feature = c("price", "quality", "service"),
performance = c(3.1, 4.2, 3.5))
b <- data.frame(feature = c("price", "quality", "service"),
performance = c(2.8, 4.4, 3.9))
compare_values(b, a) %>% plot_diff()
Stacked score gauges (NPS over average quality, etc.)
Description
Draws two or more scores as thin banded gauge bars stacked one above another, each on its own scale with a "you are here" marker. The headline summary slide: the Net Promoter Score on top and the average feature quality rating below it, so both key numbers sit together instead of one fat bar filling the slide.
Usage
plot_gauges(
scores,
scales = NULL,
title = NULL,
height = 0.5,
label_size = NULL
)
Arguments
scores |
A named numeric vector; each name labels a gauge and each value is placed on its scale. The first is drawn at the top. |
scales |
Which band scale each gauge uses: |
title |
Optional title. |
height |
Bar thickness in plot units (row spacing is 1). Defaults to
|
label_size |
Band-label text size. |
Details
Each gauge is normalised to its own scale, so an NPS of +23 and a quality
rating of 3.4 line up on a shared 0..1 panel with the band boundaries drawn
where each scale puts them (the NPS gauge reuses the plot_nps_gauge() bands;
the rating gauge uses bands_rating_3()). The score for each gauge is printed
beside its label, and a black marker shows where it lands. Because the bars
are thin and stacked, this is the summary-slide companion to the detailed
plot_nps() distribution and the plot_ipm() driver matrix.
Since the bars share one panel but not one scale, no axis can serve them
both. Each bar therefore carries its own band boundaries as small numbers
underneath, so an NPS bar reads -100 0 30 70 100 and a rating bar reads
1 3 4 5; without them a marker two thirds along says nothing about the
score it marks. A band too narrow to hold its name is left unlabelled rather
than having the text run over its neighbours, and those numbers are what
still place it.
Value
A ggplot object.
See Also
plot_nps_gauge(), calc_nps(), ipm_model().
Other plots:
plot_bars(),
plot_ipm(),
plot_nps(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_rating_grid(),
plot_stacked_rating()
Examples
nps <- calc_nps(podracing_survey, nps_value)$nps
quality <- 3.4
plot_gauges(c("Net Promoter Score" = nps,
"Average quality rating" = quality))
Importance / performance matrix
Description
Plots an ipm_model() table as a scatter of feature performance (x) vs.
importance (y), coloured by performance band, with decision bands across the
top: the importance / performance slide of a survey deck, in one call.
Usage
plot_ipm(model, title = NULL, repel = TRUE, bands = bands_rating_3())
Arguments
model |
An |
title |
Optional title; defaults to the average performance. |
repel |
Use |
bands |
Decision-band spec drawn across the top and used to colour the
points. Defaults to |
Details
Each feature is a point: performance on the x-axis (mean 1–5 rating, with a
reference line at the average) and importance on the y-axis (relative weight,
as a percentage). Each point takes the colour of the decision band it falls
in, so a feature averaging 2.4 is red because it sits in the BAD band – the
point and the band behind it can never disagree. Read it by quadrant –
high-importance, low-performance features (upper left) are the priorities to
fix, while high-importance, high-performance features (upper right) are
strengths to protect. Feed it an ipm_model() table; uses ggrepel for
non-overlapping labels when available.
Value
A ggplot object.
See Also
ipm_model(), compare_values().
Other plots:
plot_bars(),
plot_gauges(),
plot_nps(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_rating_grid(),
plot_stacked_rating()
Examples
ipm_model(podracing_survey, nps_value, "ratings_") %>% plot_ipm()
NPS distribution slide (0-10 scale with group labels)
Description
The canonical Net Promoter Score chart: the full 0-10 recommendation distribution as labelled bars coloured by NPS group, with the detractor / passive / promoter shares called out in coloured boxes across the top and the overall NPS in the title: the NPS slide of a survey deck, in one call.
Usage
plot_nps(data = NULL, value, title = NULL)
Arguments
data |
A data frame. If omitted, the session default ( |
value |
The 0-10 recommendation column (unquoted). Text such as
|
title |
Optional title; defaults to |
Details
Unlike plot_nps_gauge() (which takes a single score), this reads the raw
0–10 column and draws the full distribution: one labelled bar per score,
coloured red/amber/green by NPS group, with the detractor/passive/promoter
shares called out across the top and the overall score in the title. It is the
detailed companion slide to the gauge.
Value
A ggplot object.
See Also
Other plots:
plot_bars(),
plot_gauges(),
plot_ipm(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_rating_grid(),
plot_stacked_rating()
Examples
plot_nps(podracing_survey, nps_value)
Score gauge with decision bands and a value marker
Description
A horizontal gauge that places a single score (NPS or mean rating) onto a banded scale, with a "you are here" marker: the NPS and quality gauges a summary slide carries.
Usage
plot_nps_gauge(
score,
scale = c("nps", "rating"),
title = NULL,
height = 0.5,
label_size = NULL
)
Arguments
score |
The score to mark (NPS on -100..100, or a mean rating on 1..5). |
scale |
|
title |
Optional title; a sensible default is generated from |
height |
Bar thickness in plot units. Defaults to |
label_size |
Band-label text size. |
Details
Takes a single number (not a dataset) and places it on a coloured band scale
with a black marker, for the headline "where do we stand" slide. "nps" uses
a -100..100 scale banded from needs-work to excellent; "rating" uses a 1..5
scale with BAD/OK/GOOD bands. Pair it with calc_nps() for the score.
Value
A ggplot object.
See Also
Other plots:
plot_bars(),
plot_gauges(),
plot_ipm(),
plot_nps(),
plot_quotes_tree(),
plot_rating_grid(),
plot_stacked_rating()
Examples
nps <- calc_nps(podracing_survey, nps_value)$nps
plot_nps_gauge(nps)
plot_nps_gauge(3.8, scale = "rating")
Treemap of selected quotes
Description
A treemap where each tile is a comment sized by length – the quote slide of
a survey deck. Requires the suggested treemapify package.
Usage
plot_quotes_tree(data, label = comment, area = length, colour = "black")
Arguments
data |
A data frame of quotes, e.g. from |
label |
Text column (unquoted). Defaults to |
area |
Tile-size column (unquoted). Defaults to |
colour |
Tile border colour. Defaults to |
Details
Lays selected verbatims out as a treemap, each tile sized by comment length,
so a slide can show real customer voice at a glance. Pair it with
sample_comments() or sample_comments_diverse(), which produce the
comment/length columns it expects. Requires the suggested treemapify
package.
Value
A ggplot object.
See Also
sample_comments(), sample_comments_diverse().
Other plots:
plot_bars(),
plot_gauges(),
plot_ipm(),
plot_nps(),
plot_nps_gauge(),
plot_rating_grid(),
plot_stacked_rating()
Examples
sample_comments(podracing_survey, nps_com, show_com, n = 5) %>%
plot_quotes_tree()
A stacked rating chart for a whole block of questions
Description
The one-line form of plot_stacked_rating() for the common case: a block of
columns sharing a prefix, each asking the same rating question about a
different feature or brand. Tabulates the block, tidies the question names,
numbers the answers by their position on the scale and stacks the result.
Usage
plot_rating_grid(data = NULL, prefix, levels = NULL, digits = 2, ...)
Arguments
data |
A data frame. If omitted, the session default ( |
prefix |
The block's shared column prefix, e.g. |
levels |
The scale's answer wordings, worst first. |
digits |
Decimal places kept in the underlying percentages. Default |
... |
Passed to |
Details
Answers are numbered by their position in levels, which is what orders the
features by their weighted mean and colours the segments worst-to-best. A
wording that is not on the scale cannot be numbered, so it is reported rather
than being silently dropped into an unlabelled segment: check it against the
raw export, since exports often differ from a questionnaire by a typo.
Registering the block once with
register_order("likeability", levels, prefixes = "partner_likeability_")
removes the levels argument from every later call.
Value
A ggplot object.
See Also
plot_stacked_rating(), calc_percentage_batch(),
register_order().
Other plots:
plot_bars(),
plot_gauges(),
plot_ipm(),
plot_nps(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_stacked_rating()
Examples
plot_rating_grid(podracing_survey, "ratings_")
plot_rating_grid(podracing_survey, "partner_likeability_",
levels = c("Very unlikeable", "Unlikeable",
"Likeable", "Very likeable"))
Stacked rating bars with weighted-average ordering
Description
Draws a 100%-stacked bar per feature across an ordinal rating scale, labels each segment, and orders features by their weighted mean rating – the likeability, purchase and feature-rating charts a survey deck is built from.
Usage
plot_stacked_rating(
data,
feature,
level,
value = pct,
palette = NULL,
label_min = 1,
show_average = TRUE
)
Arguments
data |
Long data with one row per feature x rating level. |
feature |
Feature column (unquoted). |
level |
Ordered rating-level column (unquoted), e.g. a factor like
|
value |
Percentage column (unquoted). Defaults to |
palette |
Fill colours, named by the level labels. Defaults to |
label_min |
Hide segment labels below this percentage. Defaults to |
show_average |
Append the weighted mean to each feature label. Defaults
to |
Details
Each feature becomes a 100%-stacked bar across the rating scale, and features
are ordered by their weighted-mean rating (the leading digit of each level
is the weight), so the best-rated feature sits at the top. The weighted mean
is appended to each feature label when show_average = TRUE. Feed it a long
table with one row per feature x rating level; the partner_* likeability and
purchase questions in the source reports are the canonical use.
Value
A ggplot object.
See Also
calc_percentage(), scale_fill_rating().
Other plots:
plot_bars(),
plot_gauges(),
plot_ipm(),
plot_nps(),
plot_nps_gauge(),
plot_quotes_tree(),
plot_rating_grid()
Examples
rating_long <- podracing_survey %>%
select(starts_with("ratings_")) %>%
tidyr::pivot_longer(everything(),
names_to = "feature", values_to = "level") %>%
filter(level != "") %>%
mutate(level = paste0(recode_likert(level), " - ", level)) %>%
count(feature, level) %>%
group_by(feature) %>%
mutate(pct = n / sum(n) * 100) %>%
ungroup()
plot_stacked_rating(rating_long, feature, level)
Simulated pod-racing fan survey
Description
A fictional consumer-feedback survey from a Boonta Eve-style pod-racing
meeting – an affectionate Star Wars parody used throughout the ezrsurvey
examples and tests (the package's literal answer to starwars, but
survey-shaped). A latent enjoyment drives correlated attribute ratings and the
recommend score, the demographics use international-standard categories
(ISO/IEC 5218 sex, ISCED education, ILO labour-force status, ISIC sectors,
ISO 3166 countries), and the multi-select, sponsor and open-text columns mirror
the shapes the helpers consume. The open-text comments deliberately name many
drivers, places and races, so they exercise the text / NER helpers. Blanks and
"Prefer not to answer" responses are sprinkled in so cleaning helpers have
something to do.
Usage
podracing_survey
Format
A tibble with 1,000 rows and 32 columns:
- respondent_id
Unique respondent id (character).
- collector
Survey source: email, panel, socials or in_app.
- demo_age
Age in years (integer, 16-70).
- demo_gender
Sex/gender: Male, Female, Non-binary (ISO/IEC 5218, extended), some blank / "Prefer not to answer".
- demo_edu
Highest education level (ISCED 2011 broad categories).
- demo_country
Country of residence (ISO 3166 names).
- region
World region derived from
demo_country.- demo_job
Labour-force status (ILO categories).
- demo_sector
Industry sector (ISIC Rev.4 sections).
- race_attended
Which meeting they attended (e.g. "Boonta Eve Classic"); long labels that exercise the auto bar layout.
- fav_driver
Favourite pod-racer (e.g. "Anakin Skywalker", "Sebulba").
- nps_value
0-10 "how likely to recommend attending" rating (integer).
- satis_return
Likelihood of returning next season (Very unlikely .. Very likely).
- ratings_atmosphere, ratings_commentary, ratings_safety, ratings_speed, ratings_value, ratings_venue
Worded 1-5 attribute ratings (Very bad .. Very good).
- motivations_speed, motivations_drivers, motivations_betting, motivations_social, motivations_tradition
Multi-select reasons for attending; each holds its option text when chosen, otherwise
"".- partner_recall_PodTech, partner_recall_BanthaBrew, partner_recall_JawaJuice
Sponsor recall per brand (Sponsor / Not a sponsor / Don't know this brand).
- partner_likeability_PodTech, partner_likeability_BanthaBrew, partner_likeability_JawaJuice
Sponsor likeability (Very likeable .. Very unlikeable).
- nps_com, show_com
Open-text comments (mostly blank).
Source
Simulated. See data-raw/make_podracing_survey.R for the generator.
See Also
Other data:
country_region,
currency_rates,
shopping_survey
Examples
calc_percentage(podracing_survey, demo_gender, sort = "desc")
calc_nps(podracing_survey, nps_value)
Plain-language survey precision summary
Description
Distils a whole survey's sampling precision into a few bullet points – the narrative "Data info" paragraph from the report appendix, generated automatically. It scans the dataset, assesses the numeric (point-scale) and categorical (proportion) variables, and reports the typical sampling margins and an overall reliability verdict.
Usage
precision_summary(data = NULL, ..., z = 1.96)
Arguments
data |
A data frame. If omitted, the session default ( |
... |
Optional columns to restrict the assessment to (tidyselect). If omitted, all suitable columns are used: every numeric column, and every categorical column that is not free text or an identifier. |
z |
Confidence multiplier for the margins of error. Default |
Details
Rather than make you choose which variables to quote precision for, this picks
them: numeric columns become point estimates (margins in rating points) and
categorical columns become proportions (margins in percentage points), with
free-text and id-like columns skipped. It then reports the typical and
worst margins across each group, plus an overall verdict from the median
relative standard error via rse_rating(). For proportions it also gives the
worst-case +/- percentage-point margin at a 50/50 split, which is the widest
any percentage in the study can be. See vignette("ezrsurvey") for the
rationale behind the relative-standard-error reliability bands.
Value
An object of class ezrsurvey_precision (a list with n, the
per-variable table, overall_rse, rating and the bullets). Printing it
shows the bullet points.
See Also
Other diagnostics:
diagnose(),
margin_of_error(),
rse(),
rse_rating(),
se_mean(),
se_prop()
Examples
precision_summary(podracing_survey)
Read and stack every CSV in a folder
Description
Loads all CSV files matching pattern in path, reading each as character
(so survey codes never get silently coerced), tags every row with its source
filename, and row-binds the lot into one tibble. Generalises the
list.files() %>% map(read.csv) %>% bind_rows() opening of a survey script.
Usage
read_folder(
path,
pattern = "\\.csv$",
id = "file",
all_character = TRUE,
question_row = NULL,
locale = readr::locale(encoding = "UTF-8"),
...
)
Arguments
path |
Directory to read from. |
pattern |
Regular expression matching the files to load. Defaults to
|
id |
Name of the column in which to record each row's source filename.
Defaults to |
all_character |
If |
question_row |
What to do with a second header row of question wording.
|
locale |
A |
... |
Further arguments passed to |
Details
Every matching file is read and the results are row-bound, so a folder of
monthly or per-event exports becomes one dataset. By default every column is
read as text (all_character = TRUE); this is deliberate, because survey
exports are ragged (a column that is numeric in one file may carry "Prefer
not to answer" in another), and stacking text columns never fails. Recode the
types you need afterwards with recode_*() / ensure_numeric(). The id
column records which file each row came from – split it into metadata with
parse_filename(). For legacy encodings pass a locale, e.g.
readr::locale(encoding = "windows-1252").
Survey platforms commonly write the question wording as a second header row,
which reads back as respondent number one and quietly skews every count by
one. A file whose first row is long, spaced prose in most columns at once
and numeric in none is reported as such; question_row = TRUE drops that
row from every file, and FALSE keeps it without comment.
Value
A single tibble of all files stacked together. If
columns differ across files, missing columns are filled with NA.
See Also
select_prefix(), parse_filename().
Other import:
parse_filename(),
select_prefix(),
select_suffix()
Examples
# build a tiny folder of CSVs, then read them back
dir <- tempfile(); dir.create(dir)
readr::write_csv(head(podracing_survey, 3), file.path(dir, "a.csv"))
readr::write_csv(head(podracing_survey, 2), file.path(dir, "b.csv"))
read_folder(dir)[, c("file", "respondent_id")]
Recode age into standard survey bands
Description
Convenience wrapper over bin_numeric() using the standard survey age
bands. Also tolerates messy inputs such as "25 years" by
extracting the first run of digits.
Usage
recode_age(
x,
breaks = ezrsurvey_default("age_breaks"),
labels = ezrsurvey_default("age_labels"),
quiet = FALSE
)
Arguments
x |
A numeric or character vector of ages. |
breaks, labels |
Override the default bands if needed; the defaults come
from the |
quiet |
If |
Details
Ages are first passed through ensure_numeric(), so messy entries like
"22 years" or "age: 31" are handled, then binned with bin_numeric()
using left-closed bands. An answer with no number in it at all ("young",
"prefer not to say") becomes NA and is counted in a message, so a column
that was never numeric does not pass for a column of missing ages. The
default bands come from the age_breaks /
age_labels options, so you can set your study's standard cohorts once with
ezrsurvey_options(age_breaks = ..., age_labels = ...) (or a profile) instead
of passing them on every call. For generational cohorts (Gen Z, Millennial,
...) use recode_generation() instead.
Value
A factor of age-band labels, levels in band order.
See Also
bin_numeric(), recode_generation(), ezrsurvey_options().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_generation(),
recode_likert(),
recode_region(),
split_multi()
Examples
recode_age(c("17", "22 years", "31", "47"))
Recode age or birth year into a generational cohort
Description
Maps either an age (converted to a birth year using a reference year) or a
birth year directly onto a generational cohort such as Millennial or
Gen Z. Text input like "34 years" is salvaged with ensure_numeric().
Usage
recode_generation(x, input = c("age", "year"), year = NULL, scheme = NULL)
Arguments
x |
A numeric (or coercible) vector of ages or birth years. |
input |
What |
year |
Reference year for the age-to-birth-year conversion. If |
scheme |
Either a scheme name passed to |
Details
When input = "age", the birth year is year - age, where year defaults to
the current_year option or the system year – so set
ezrsurvey_options(current_year = 2026) to keep results stable across runs.
When input = "year", x is treated as the birth year directly. The birth
year is then bucketed into the scheme's cohorts (see generation_scheme());
birth years before the earliest cohort return NA. Use this for
generational reporting; for simple age bands use recode_age().
Value
A factor of cohort labels, levels from the oldest cohort to the
youngest; values outside the scheme's range become NA.
See Also
generation_scheme(), recode_age(), ezrsurvey_options().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_likert(),
recode_region(),
split_multi()
Examples
recode_generation(c(1990, 2001, 1968), input = "year")
# from age, with an explicit reference year
recode_generation(c(36, 25), input = "age", year = 2026)
Recode a worded rating scale to integers
Description
Maps the worded answers of an ordinal rating question (e.g. "Very bad" ...
"Very good") onto integers 1:length(levels). Matching is case-insensitive
and tolerant of common synonyms supplied via synonyms, in place of a
case_when(str_detect("Very bad") ...) recoding block.
Usage
recode_likert(
x,
levels = c("Very bad", "Bad", "Ok", "Good", "Very good"),
synonyms = NULL
)
Arguments
x |
A character (or factor) vector of worded answers. |
levels |
Character vector of the scale's answer wordings in ascending
order. The first element maps to |
synonyms |
Optional named list mapping a canonical level (one of
|
Details
Matching happens in three passes, in order: (1) an exact, case-insensitive,
trimmed match against levels; (2) a substring fallback, so prefixed exports
like "4 - Good" still resolve; (3) any synonyms you supply. This makes the
function robust to the small wording differences between survey tools (e.g.
"Dissatisfied" vs "Bad"). Turning ratings into integers is the first step of
ipm_model() and lets you average a scale with calc_summary().
The substring passes try the longest wording first, so a scale whose levels nest inside one another ("Likeable" inside "Very likeable", "Good" inside "Very good") resolves to the level the answer actually names. Without that, any answer the exact pass misses, such as one carrying an emoji or a stray character, would quietly land on the shorter level.
Value
An integer vector the same length as x; unmatched values become
NA.
See Also
nps_group(), ipm_model(), calc_summary().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_region(),
split_multi()
Examples
recode_likert(c("Very bad", "Ok", "Good", "Very good"))
# substring fallback copes with numbered labels
recode_likert("4 - Good")
# nested wordings resolve to the level the answer names, not the shorter one
recode_likert(c("\U0001F642 Very good", "\U0001F610 Good"))
# map another tool's wording onto the same scale
recode_likert(c("Dissatisfied", "Satisfied"),
synonyms = list(Bad = "Dissatisfied", Good = "Satisfied"),
levels = c("Very bad", "Bad", "Ok", "Good", "Very good"))
Look up the region or subregion for a country
Description
Vectorised lookup from country name to world region or finer subregion,
using the bundled country_region table. Matching is case-insensitive and
whitespace-tolerant, and understands the spellings people type as well as
ISO 3166-1 alpha-2 and alpha-3 codes, so "USA", "U.S.", "us" and
"United States" all resolve alike; blanks and non-answers (see
na_blank()) become NA, and unmatched countries become NA with a
one-line warning so spelling mismatches are easy to spot.
Usage
recode_region(x, which = c("region", "subregion"), quiet = FALSE)
recode_subregion(x, quiet = FALSE)
Arguments
x |
A character vector of country names. |
which |
|
quiet |
If |
Details
A country column that people typed themselves is rarely tidy: in one real
open salary survey, nine thousand respondents wrote "United States" and
eight thousand wrote "USA". So the name is folded down before it is looked
up – case, stray punctuation, accents and a leading "the" are all dropped
– and then tried against the bundled country_region table (182
countries), then against a table of the spellings people actually use.
That table carries endonyms ("Deutschland", "Brasil"), the constituent
countries of the United Kingdom, and ISO 3166-1 alpha-2 and alpha-3 codes
("US", "USA", "DE", "DEU"), so a column already coded to the
standard needs no preparation at all.
A two-letter code is only read as a code when it was typed in capitals,
because "NO" is Norway but "no" is an answer to a different question.
Blanks and non-answers are blanked with na_blank() first, and anything
still unmatched returns NA with a warning listing the offenders, so a
spelling the table does not carry is easy to spot and add. Set
quiet = TRUE inside pipelines where you have already checked the coverage.
region is the coarse level (e.g. "Europe"); subregion is finer (e.g.
"Western Europe").
Value
A character vector of regions (or subregions), NA where unmatched.
See Also
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
split_multi()
Examples
recode_region(c("Germany", "Japan", "Brazil"))
# the spellings a free-text country question actually collects
recode_region(c("USA", "U.S.", "England", "Deutschland", "Holland"))
# a column already coded to ISO 3166-1
recode_region(c("US", "GBR", "DE", "JPN"))
recode_subregion(c("Germany", "Japan"))
# unmatched -> NA (warning suppressed here)
recode_region(c("Germany", "Atlantis"), quiet = TRUE)
Register a reusable ordinal level order
Description
Survey scales (education, Likert, frequency, ...) have a natural order that is
tedious to retype as levels = c(...) every time. Register an order once,
link it to the variable names and/or column prefixes it applies to, and the
tabulating helpers (e.g. calc_percentage()) will look it up and apply it
automatically. Persist your orders in a profile with save_ezrsurvey_profile().
Usage
register_order(name, levels, vars = NULL, prefixes = NULL, overwrite = TRUE)
Arguments
name |
Short name for the order (e.g. |
levels |
Character vector of the levels in ascending order. |
vars |
Optional exact column names this order applies to (e.g.
|
prefixes |
Optional column-name prefixes this order applies to (e.g.
|
overwrite |
Overwrite an existing order of the same name. Default |
Details
An order links a set of levels to the columns it applies to, by exact name
(vars) and/or by prefix (prefixes). Once registered, calc_percentage(),
calc_percentage_multi() and crosstab() look it up automatically (via
order_for()) whenever you don't pass an explicit levels/sort, so a
question always comes out in the right order without retyping it. Register
interactively for the session, or store orders in a profile with
save_ezrsurvey_profile() so they load every session.
Value
Invisibly the order name.
See Also
order_for(), apply_order(), list_orders(),
register_order_presets().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order(
"education",
levels = c("Primary or less", "Lower secondary", "Upper secondary",
"Short-cycle tertiary", "Bachelor or equivalent",
"Master or equivalent", "Doctoral or equivalent"),
vars = "demo_edu"
)
calc_percentage(podracing_survey, demo_edu) # rows now in education order
remove_order("education")
Register a set of common ordinal scales
Description
A convenience that registers a handful of frequently used orders, linked to
sensible default variable names/prefixes, so common surveys work out of the
box. Override any of them afterwards with register_order().
Usage
register_order_presets()
Details
Registers: likert_bad_good, likert_agree, frequency, likelihood and
education_isced.
Value
Invisibly the names registered.
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order_presets()
list_orders()
Remove a registered order
Description
Remove a registered order
Usage
remove_order(name)
Arguments
name |
Order name. |
Value
Invisibly TRUE.
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
register_order("yesno", c("No", "Yes"))
remove_order("yesno")
Add a plot to a report
Description
Renders a ggplot to an image and places it in the current slide's content placeholder (pptx) or as a new figure (docx).
Usage
report_add_plot(doc, plot, width = NULL, height = NULL, dpi = 150)
Arguments
doc |
A document from |
plot |
A ggplot object (any grid grob also works, e.g. an aligned
plot from |
width, height |
Image size in inches. |
dpi |
Raster resolution. Defaults to |
Details
On slides the image is rendered at exactly the content placeholder's size, so nothing is stretched or letterboxed; when the template does not define placeholder geometry the slide size (minus margins) is used instead.
Value
The updated document.
See Also
Other reporting:
example_report(),
list_report_templates(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
p <- calc_percentage(podracing_survey, demo_gender) %>% plot_bars()
doc <- report_new("pptx") %>%
report_add_slide("Gender") %>%
report_add_plot(p)
class(doc)
Add a slide (PowerPoint) or heading (Word) to a report
Description
For a pptx document this starts a new slide and sets its title; for a
docx document it adds a heading paragraph.
Usage
report_add_slide(
doc,
title = NULL,
layout = NULL,
master = NULL,
heading_level = 1
)
Arguments
doc |
A document from |
title |
Optional slide title / heading text. |
layout, master |
PowerPoint layout and master names. |
heading_level |
Word heading level (1-3). Defaults to |
Details
Automatic selection scores every layout of the template: a title placeholder plus a single content placeholder is the ideal, and the layout's placeholders decide – not its (language-dependent) name. If the chosen layout has no title placeholder, the title is skipped with a warning rather than failing the build.
Value
The updated document.
See Also
report_new(), report_layouts().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
doc <- report_new("pptx") %>% report_add_slide("Audience")
class(doc)
Add a table to a report
Description
Adds a data frame as a flextable – in the current slide's content placeholder (pptx) or as a new table (docx).
Usage
report_add_table(doc, data, font_size = 12, autofit = TRUE)
Arguments
doc |
A document from |
data |
A data frame / tibble. |
font_size |
Cell font size in points. Defaults to |
autofit |
Word only: auto-size columns to content. Defaults to |
Details
On a slide the table is styled (a clean banded header, centred cells, a readable font) and its columns are widened to span the content placeholder – roughly in proportion to each column's contents – so it fills the slide meaningfully instead of sitting tiny in a corner. In Word it is added as a plain auto-fitted flextable.
Value
The updated document.
See Also
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
tbl <- calc_percentage(podracing_survey, demo_gender)
doc <- report_new("docx") %>% report_add_table(tbl)
class(doc)
Add a paragraph of text to a report
Description
Add a paragraph of text to a report
Usage
report_add_text(doc, text, ...)
Arguments
doc |
A document from |
text |
Text to add; a character vector becomes one paragraph (bullet) per element on slides. |
... |
Passed to |
Value
The updated document.
See Also
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
doc <- report_new("docx") %>% report_add_text("Key findings follow.")
class(doc)
Build a slide deck from a list of plots and tables in one call
Description
Turns a named list of ggplots / data frames into a titled-slide deck (or Word document) and saves it. Names become slide titles; each item lands on its own slide, sized to the template's content placeholder.
Usage
report_deck(
items,
path,
format = c("pptx", "docx"),
title = NULL,
template = NULL,
style = c("elevated", "plain")
)
Arguments
items |
A named list; names become slide titles. Each element is either a ggplot (added as a plot) or a data frame (added as a table). |
path |
Output file path. A bare file name is written to the working
directory, or into the folder set by the |
format |
|
title |
Optional title-slide / document-title text. |
template |
Optional reference document; |
style |
Built-in template to fall back on: |
Details
Every chart is rendered at the exact size of the template's content
placeholder and centred in it, and plot_bars() draws bars to a constant
thickness whatever the category count, so the deck reads consistently as you
flick through it.
For a deck built a slide at a time, with section dividers and per-slide
control over the layout, use report_new() and the report_add_*() family
instead.
Value
Invisibly path.
See Also
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
tmp <- tempfile(fileext = ".pptx")
report_deck(
list(
"Gender" = plot_bars(calc_percentage(podracing_survey, demo_gender)),
"NPS" = calc_nps(podracing_survey, nps_value)
),
path = tmp
)
file.exists(tmp)
List the slide layouts of a PowerPoint template
Description
Shows what a template offers the report builders: every layout, its master,
and the placeholders it carries. Useful to decide which layout to name in
report_add_slide(), or to sanity-check an organisation template before
building a deck against it.
Usage
report_layouts(template = NULL, style = c("elevated", "plain"))
Arguments
template |
Path to a |
style |
Built-in template to inspect when no |
Details
The report builders pick layouts automatically by inspecting placeholders,
so most decks never need this – but when a corporate template offers
several content layouts, report_layouts() plus an explicit
report_add_slide(layout = ...) gives you full control. Requires the
suggested officer package.
Value
A tibble with one row per layout: layout,
master, has_title, n_body, body_width, body_height (inches of
the first body placeholder, NA when the layout has none).
See Also
report_new(), report_add_slide(), use_brand().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
report_layouts()
Start a new PowerPoint or Word report
Description
Opens an officer document you can build up with the report_add_*()
helpers and write out with report_save(). This is the "build slides/Word
directly from R" path; for a Quarto-based workflow see scaffold_report().
Usage
report_new(
format = c("pptx", "docx"),
template = NULL,
style = c("elevated", "plain"),
slide_numbers = TRUE,
keep_slides = TRUE
)
Arguments
format |
|
template |
Optional path to a |
style |
Which built-in template to fall back on when no |
slide_numbers |
If |
keep_slides |
PowerPoint only. If |
Details
This is the "build it from R" path: you get an officer document and
add to it slide by slide (pptx) or section by section (docx) with the
report_add_*() helpers, then write it out with report_save(). Slide
layouts are chosen by inspecting the template's placeholders, so any
organisation template works – see report_layouts() for what yours
contains. For a quick deck from a list of charts and tables, report_deck()
does the whole thing in one call; for a document-driven workflow,
scaffold_report() gives you a Quarto template instead. Requires the
suggested officer package.
Value
An officer document object (rpptx or rdocx).
See Also
report_add_slide(), report_add_plot(), report_add_table(),
report_save(), report_deck(), report_layouts(), use_brand().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_save(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
doc <- report_new("pptx")
class(doc)
# any .pptx of your own replaces the built-in template
own <- system.file("templates", "ezrsurvey-16x9-plain.pptx",
package = "ezrsurvey")
doc <- report_new("pptx", template = own)
Save a report to disk
Description
Writes a deck or document built with report_new() and the report_* verbs,
and returns the path it used, so a build pipeline can carry on from it.
Usage
report_save(doc, path)
Arguments
doc |
A document from |
path |
Output file path ( |
Details
The format follows the document, not the file name: a deck is written as
PowerPoint and a Word document as Word, so give path the matching .pptx
or .docx extension.
Value
Invisibly path.
See Also
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_section(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
tmp <- tempfile(fileext = ".pptx")
report_new("pptx") %>% report_add_slide("Hi") %>% report_save(tmp)
file.exists(tmp)
Add a section-divider slide
Description
A one-line section break: a slide on the template's "Section Header" layout
(falling back to a plain titled slide when the template has none). Use a
short, single-word label – "DEMOGRAPHICS", "RATINGS", "APPENDIX" – to
chapter a deck.
Usage
report_section(doc, title, layout = "Section Header", master = NULL)
Arguments
doc |
A document from |
title |
Section label. |
layout |
Section layout name. Defaults to |
master |
Optional master name. |
Value
The updated document.
See Also
report_slide(), report_title_slide().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_slide(),
report_title_slide(),
scaffold_report()
Examples
doc <- report_new("pptx") %>% report_section("DEMOGRAPHICS")
class(doc)
Add a whole slide in one call (title plus its content)
Description
The one-line-per-slide wrapper: starts a new slide, sets its title, and
places content on it in a single call, so a deck script reads as one line
per slide. content is dispatched by type – a ggplot becomes a chart, a
data frame a table, a character vector a bulleted text box.
Usage
report_slide(
doc,
title = NULL,
content = NULL,
layout = NULL,
master = NULL,
...
)
Arguments
doc |
A document from |
title |
Slide title (typically the survey question the slide answers). |
content |
A ggplot, a data frame / tibble, or a character vector. |
layout, master |
Passed to |
... |
Passed on to |
Details
Equivalent to report_add_slide() followed by the matching report_add_*()
call, but as one pipe-friendly step so calc -> plot -> add collapses onto a
single line:
report_slide("How likely to recommend?", plot_nps(nps_value)).
Value
The updated document.
See Also
report_section(), report_title_slide(), report_add_slide().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_title_slide(),
scaffold_report()
Examples
doc <- report_new("pptx") %>%
report_slide("Who follows pod racing?",
plot_bars(calc_percentage(podracing_survey, demo_gender)))
class(doc)
Add the opening title slide
Description
A one-line title slide, placed on the template's title layout (the one with a centre-title placeholder).
Usage
report_title_slide(doc, title, subtitle = NULL, layout = NULL, master = NULL)
Arguments
doc |
A document from |
title |
Deck title. |
subtitle |
Optional strapline placed in the layout's subtitle
placeholder – the respondent base and fieldwork period, say. |
layout, master |
Optional overrides; |
Value
The updated document.
See Also
report_slide(), report_section().
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
scaffold_report()
Examples
doc <- report_new("pptx") %>%
report_title_slide("Pod-Racing Fan Survey",
subtitle = "1,000 fans | Fieldwork 2026")
class(doc)
Move a band specification onto another scale
Description
The band presets are written on the scales survey work uses most: 1-5 for a
rating, 0-10 for the Net Promoter answer, -100 to 100 for the score. Plenty
of real questionnaires do not use those. Satisfaction is often collected on
0-100, and a seven-point agreement scale is common. rescale_bands()
stretches a band specification onto the scale the chart is actually drawn on,
so the thresholds can stay where they are instead of the data being divided
to meet them.
Usage
rescale_bands(bands, to, from = NULL)
Arguments
bands |
A band specification: one of |
to |
Length-2 numeric: the scale the chart uses, as |
from |
Length-2 numeric: the scale |
Details
The mapping is linear and proportional: a band covering the top fifth of its own scale covers the top fifth of the new one. Rescale rather than divide the data, so the axis a reader sees is still the scale the question was asked on.
Value
bands with from and to moved onto the new scale. Labels and
colours are untouched.
See Also
Other decisions:
annotate_bands(),
bands_rating_3(),
mark_value()
Examples
# satisfaction collected 0-100, thresholds still where they belong
bands_rating_3() %>% rescale_bands(to = c(0, 100))
# a seven-point agreement scale
bands_rating_3() %>% rescale_bands(to = c(1, 7))
Reset all ezrsurvey options to their built-in defaults
Description
Reset all ezrsurvey options to their built-in defaults
Usage
reset_ezrsurvey_options()
Value
Invisibly TRUE.
See Also
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
save_ezrsurvey_profile(),
use_dataset(),
use_ezrsurvey_profile()
Examples
ezrsurvey_options(pct_axis_max = 100)
reset_ezrsurvey_options()
ezrsurvey_options()$pct_axis_max # NULL again
Relative standard error
Description
The standard error expressed as a percentage of the estimate,
se / estimate * 100. A common rule of thumb treats an RSE below ~5% as very
good precision.
Usage
rse(estimate, se)
Arguments
estimate |
The point estimate (mean or proportion). |
se |
Its standard error, on the same scale as |
Details
Dividing the standard error by the estimate makes precision comparable across
measures on different scales (a 1–5 rating vs a percentage). A common
rule of thumb treats an RSE under ~5% as very good precision, which is the
threshold diagnose() uses for its precision flag.
Value
The relative standard error, in percent.
See Also
se_mean(), se_prop(), margin_of_error(), diagnose().
Other diagnostics:
diagnose(),
margin_of_error(),
precision_summary(),
rse_rating(),
se_mean(),
se_prop()
Examples
rse(estimate = 4.1, se = se_mean(c(4, 5, 3, 4, 5)))
Rate precision from a relative standard error
Description
Turns a relative standard error (RSE, in percent) into a plain-language reliability rating, using a five-band scheme.
Usage
rse_rating(rse)
Arguments
rse |
Relative standard error(s), in percent (see |
Details
The bands are: under 5% "high precision", under 10% "precise", under 15%
"satisfactory", under 25% "use with caution", and 25% or more "likely
reliability issues". Rating estimates by their relative standard error is how
national statistical agencies signal whether a survey number is solid enough
to publish: the Australian Bureau of Statistics treats an RSE of 25% or more
as "not reliable for most purposes", flags 25–50% with an asterisk as
estimates to use with caution, and suppresses anything above 50%. The 25%
boundary here is that same one. The tighter bands below it are specific to
consumer-survey work, where the question is usually which of several
adequately precise numbers to lead a report with. This drives the precision
column of diagnose() and the overall verdict of precision_summary().
Value
A character vector of ratings.
See Also
rse(), diagnose(), precision_summary().
Other diagnostics:
diagnose(),
margin_of_error(),
precision_summary(),
rse(),
se_mean(),
se_prop()
Examples
rse_rating(c(3, 8, 12, 20, 40))
Pick a random sample of open-text comments
Description
Pulls a tidy, presentation-ready sample of comments out of one or more
free-text columns, applying the usual clean-ups: drop blanks and very short
answers, optionally exclude comments matching unwanted terms, and truncate to
a maximum length. The result feeds straight into plot_quotes_tree().
Usage
sample_comments(
data = NULL,
...,
n = 8,
min_chars = 30,
max_chars = 400,
exclude = NULL,
by_column = TRUE,
by = NULL,
seed = NULL
)
Arguments
data |
A data frame. |
... |
One or more comment columns, using tidyselect (e.g. |
n |
Number of comments to sample. With |
min_chars |
Drop comments with this many characters or fewer. Default
|
max_chars |
Truncate longer comments to this length. Default |
exclude |
Optional character vector of (case-insensitive) regex terms;
comments matching any are dropped (e.g. |
by_column |
If |
by |
Optional grouping column (unquoted), e.g. an NPS group. Sampling
then takes |
seed |
Optional integer for reproducible sampling (the RNG state is restored afterwards). |
Details
Verbatims need clean-up before they go on a slide: this drops blanks and very
short answers, optionally removes comments matching unwanted terms (exclude),
and truncates the long ones. With by_column = TRUE you get n from each
source column (e.g. an even split across nps_com and show_com); with
FALSE, n from the pooled set. The result feeds plot_quotes_tree(). For a
set that is varied rather than uniformly random, use sample_comments_diverse().
Value
A tibble with source, comment and length,
plus the by column when one is given.
See Also
sample_comments_diverse() for a diversity-aware sample,
plot_quotes_tree().
Other comments:
sample_comments_diverse()
Examples
sample_comments(podracing_survey, nps_com, show_com, n = 3)
# three quotes per NPS group, with the group kept as a column
podracing_survey %>%
mutate(group = nps_group(nps_value, labels = TRUE)) %>%
filter(!is.na(group)) %>%
sample_comments(nps_com, n = 3, by = group)
Pick a diverse, information-rich sample of comments
Description
A smarter alternative to sample_comments(): instead of sampling uniformly,
it scores each comment and selects a set that is both informative and
varied, so a quote slide isn't five ways of saying the same thing. Scoring
is lexical – comments are turned into TF-IDF vectors, an information score is
computed (Shannon entropy of the word distribution, or TF-IDF mass), and a
randomised maximal-marginal-relevance pass trades off informativeness against
similarity to already-picked comments.
Usage
sample_comments_diverse(
data = NULL,
...,
n = 8,
min_chars = 30,
max_chars = 400,
exclude = NULL,
lambda = 0.6,
method = c("mmr", "entropy"),
score = c("entropy", "tfidf"),
stopwords = NULL,
max_candidates = 500,
seed = NULL
)
Arguments
data |
A data frame. |
... |
One or more comment columns, using tidyselect (e.g. |
n |
Number of comments to sample. With |
min_chars |
Drop comments with this many characters or fewer. Default
|
max_chars |
Truncate longer comments to this length. Default |
exclude |
Optional character vector of (case-insensitive) regex terms;
comments matching any are dropped (e.g. |
lambda |
Diversity/informativeness trade-off in |
method |
|
score |
By which to measure information: |
stopwords |
Stop-word handling: |
max_candidates |
Largest number of comments compared with one another
(default |
seed |
Optional integer for reproducible sampling (the RNG state is restored afterwards). |
Value
A tibble with source, comment, length and the
info score, ordered by selection.
See Also
sample_comments(), plot_quotes_tree().
Other comments:
sample_comments()
Examples
sample_comments_diverse(podracing_survey, nps_com, show_com, n = 5, seed = 1)
Quick-save a table to CSV, TSV or XLSX
Description
A pipe-friendly one-liner for dropping a summary table to disk. The format is
taken from the file extension. For .xlsx, pass a single data frame for one
sheet, or a named list of data frames to write one sheet per element.
Returns its input invisibly so it can sit mid-pipeline.
Usage
save_data(data, path, na = "", ...)
Arguments
data |
A data frame / tibble, or (for |
path |
Output path; the extension sets the format ( |
na |
String to write for missing values. Default |
... |
Passed to the underlying writer ( |
Details
The format follows the file extension: .csv/.tsv via readr, .xlsx
via the suggested writexl package. For an Excel workbook, pass one data
frame for a single sheet, or a named list of data frames for one sheet each.
Returns its input invisibly so it can sit mid-pipeline. To send several
separate calls to their own tabs in one line, see export_xlsx().
Value
data, invisibly.
See Also
save_plot(), save_output(), export_xlsx().
Other save:
export_summary_xlsx(),
export_xlsx(),
save_output(),
save_plot()
Examples
tab <- calc_percentage(podracing_survey, demo_gender)
tmp <- tempfile(fileext = ".csv")
save_data(tab, tmp)
file.exists(tmp)
Save current options and orders to a profile
Description
Writes your current non-default ezrsurvey_options() and all registered
orders (see register_order()) to a YAML profile, so they persist across
sessions. Requires the suggested yaml package.
Usage
save_ezrsurvey_profile(
path = NULL,
include_options = TRUE,
include_orders = TRUE
)
Arguments
path |
Destination path. If |
include_options |
Write changed options. Default |
include_orders |
Write registered orders. Default |
Value
Invisibly the path written.
See Also
load_ezrsurvey_profile(), edit_ezrsurvey_profile(),
register_order().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
use_dataset(),
use_ezrsurvey_profile()
Examples
ezrsurvey_options(pct_axis_max = 100)
tmp <- tempfile(fileext = ".yml")
save_ezrsurvey_profile(tmp, include_orders = FALSE)
readLines(tmp)
reset_ezrsurvey_options()
Quick-save any ezrsurvey output (plot or table)
Description
Convenience dispatcher: routes ggplots to save_plot() and data frames /
lists to save_data(), choosing by the object type. Handy at the end of a
pipe when you do not want to think about which saver to call.
Usage
save_output(x, path, ...)
Arguments
x |
A ggplot, a data frame, or a (named) list of data frames. |
path |
Output path; the extension picks the format. A bare file name is
written to the working directory, or into the folder set by the
|
... |
Passed to |
Value
x, invisibly.
See Also
Other save:
export_summary_xlsx(),
export_xlsx(),
save_data(),
save_plot()
Examples
tmp_csv <- tempfile(fileext = ".csv")
calc_percentage(podracing_survey, demo_gender) %>% save_output(tmp_csv)
tmp_png <- tempfile(fileext = ".png")
plot_bars(calc_percentage(podracing_survey, demo_gender)) %>% save_output(tmp_png)
Quick-save a plot to PNG, SVG or PDF
Description
A thin, pipe-friendly wrapper around ggplot2::ggsave() that picks the device
from the file extension and uses presentation-friendly defaults (transparent
background, generous size). Returns the plot invisibly, so it drops into a
pipeline without breaking it.
Usage
save_plot(
plot,
path,
width = 8,
height = 4.5,
dpi = 300,
bg = "transparent",
...
)
Arguments
plot |
A ggplot object. |
path |
Output path; the extension sets the format ( |
width, height |
Size in inches. Default |
dpi |
Raster resolution for PNG/JPG/TIFF. Default |
bg |
Background fill. Default |
... |
Passed to |
Details
The device is chosen from the file extension, and the plot is returned
invisibly so the call slots into a pipeline without breaking it
(p %>% save_plot("p.png") %>% print()). Defaults suit slides: a transparent
background (matching the ezrsurvey themes) and a generous size; pass
bg = "white" for a solid background. SVG output needs the suggested
svglite package.
Value
The plot, invisibly.
See Also
Other save:
export_summary_xlsx(),
export_xlsx(),
save_data(),
save_output()
Examples
p <- plot_bars(calc_percentage(podracing_survey, demo_gender))
tmp <- tempfile(fileext = ".png")
save_plot(p, tmp)
file.exists(tmp)
Scaffold a Quarto survey-report template
Description
Copies a ready-to-render Quarto report skeleton into your project, wired up
with ezrsurvey helpers against the bundled podracing_survey data: an
executive summary, per-question sections with placeholder narrative, and a
methodology appendix built from the
precision diagnostics. Swap in your own data via the data parameter (or
at the top of the file) and render with Quarto. This is the document-driven
counterpart to the report_new() / report_deck() officer builders.
Usage
scaffold_report(
format = c("pptx", "html", "pdf", "docx"),
path,
title = "Survey Report",
author = NULL,
reference_doc = NULL,
overwrite = FALSE
)
Arguments
format |
Output format: one of |
path |
Destination |
title |
Title inserted into the template's YAML header. |
author |
Author name for the YAML header. |
reference_doc |
Path to a PowerPoint / Word template used as the
Quarto |
overwrite |
Overwrite |
Details
Each scaffold declares one Quarto parameter: data, the path to a CSV of
your survey; empty means the bundled example data.
Corporate templates: Quarto/Pandoc fills a reference-doc by looking
for the standard layout names ("Title Slide", "Title and Content", "Two
Content", ...). A corporate template whose layouts keep those names works
directly; one with renamed layouts will render broken or blank slides here
– build the deck with report_deck() instead, which inspects placeholders
and works with any template.
Value
Invisibly the path written.
See Also
report_deck() for building decks directly without Quarto;
use_brand() to register a default reference document.
Other reporting:
example_report(),
list_report_templates(),
report_add_plot(),
report_add_slide(),
report_add_table(),
report_add_text(),
report_deck(),
report_layouts(),
report_new(),
report_save(),
report_section(),
report_slide(),
report_title_slide()
Examples
tmp <- tempfile(fileext = ".qmd")
scaffold_report("html", path = tmp, title = "Q2 Customer Survey")
file.exists(tmp)
Brand fill and colour scales
Description
Discrete ggplot2 scales using the brand accent palette from pal_brand().
scale_color_brand() is an alias of scale_colour_brand().
Usage
scale_fill_brand(...)
scale_colour_brand(...)
scale_color_brand(...)
Arguments
... |
Passed to |
Details
The palette function interpolates when a plot needs more colours than the
brand defines, so the scale never runs out. Without a brand set, the scales
fall back to the pal_sequential_blue defaults via pal_brand().
Value
A ggplot2 scale.
See Also
Other brand:
brand_info(),
clear_brand(),
pal_brand(),
use_brand()
Examples
df <- calc_percentage(podracing_survey, demo_gender)
ggplot(df, aes(demo_gender, pct, fill = demo_gender)) +
geom_col() +
scale_fill_brand()
NPS group fill scale
Description
Manual fill scale mapping the NPS-group coding ("-1" / "0" / "1") onto the
pal_nps palette.
Usage
scale_fill_nps(...)
Arguments
... |
Passed to |
Details
Maps the NPS-group coding from nps_group() ("-1" detractor, "0" passive,
"1" promoter) onto the pal_nps red/amber/green palette, so the colours
carry their usual meaning. Used by plot_nps().
Value
A ggplot2 scale.
See Also
pal_nps, nps_group(), plot_nps().
Other themes:
pal_rating,
scale_fill_rating(),
theme_ezrsurvey(),
theme_transparent()
Examples
df <- data.frame(score = 0:2, pct = c(20, 30, 50), group = c(-1, 0, 1))
ggplot(df, aes(score, pct, fill = factor(group))) +
geom_col() +
scale_fill_nps()
Rating colour and fill scales
Description
Manual ggplot2 scales mapping a 1-5 rating (as a factor or its character
codes "1".."5") onto the pal_rating red-amber-green palette.
Usage
scale_fill_rating(distinct = FALSE, ...)
scale_colour_rating(distinct = FALSE, ...)
scale_color_rating(distinct = FALSE, ...)
Arguments
distinct |
If |
... |
Passed to |
Details
Maps the rating codes "1".."5" onto pal_rating, which uses the
bands_rating_3() thresholds (1-2 bad, 3 ok, 4-5 good). Set
distinct = TRUE for a fully distinct 5-colour ramp, which reads better on
stacked bars where adjacent segments must be separable.
scale_color_rating() is an alias of scale_colour_rating().
Value
A ggplot2 scale.
See Also
Other themes:
pal_rating,
scale_fill_nps(),
theme_ezrsurvey(),
theme_transparent()
Examples
df <- data.frame(feature = c("a", "b"), pct = c(60, 40), rating = c(4, 2))
ggplot(df, aes(feature, pct, fill = factor(rating))) +
geom_col() +
scale_fill_rating()
Continuous y-scale capped at a nice maximum with optional percent labels
Description
A thin wrapper around ggplot2::scale_y_continuous() that sets the upper
limit with nice_max() and, by default, formats the axis as percentages.
Designed for the percentage bar charts produced by calc_percentage().
Usage
scale_y_pct(values = NULL, unit = 25, pad = 0, max = NULL, labels = TRUE, ...)
Arguments
values |
Numeric vector used to determine the axis ceiling, typically
the column being plotted. If |
unit, pad |
Passed to |
max |
Optional fixed upper limit. If supplied (e.g. |
labels |
One of:
|
... |
Further arguments passed to |
Details
The upper limit is chosen in one of three ways, in order of precedence: a
fixed max if you supply one; otherwise nice_max() of values; otherwise
left to ggplot2. Labels default to whole-percent strings via label_pct().
plot_bars() calls this for you, reading its unit and max from the
pct_axis_unit / pct_axis_max options (see ezrsurvey_options()), so you
rarely add it by hand – but it is exported for custom charts.
Value
A ggplot2 scale you can add to a plot with +.
See Also
nice_max(), label_pct(), plot_bars().
Other scales:
label_pct(),
nice_max()
Examples
df <- calc_percentage(podracing_survey, demo_gender)
ggplot(df, aes(demo_gender, pct)) +
geom_col() +
scale_y_pct(df$pct) # axis capped at a tidy multiple, "%" labels
Standard error of a mean (point estimate)
Description
sd(x) / sqrt(n), the sampling error of a mean such as an average 1-5
rating. Packages the inline sem calculation from the report appendix.
Usage
se_mean(x)
Arguments
x |
A numeric vector. |
Details
The standard error of the mean is the sample standard deviation divided by the
square root of the (non-missing) sample size, sd(x) / sqrt(n). It shrinks as
the sample grows, and is the basis of the margin of error you quote for an
average rating. Fewer than two values gives NA (no spread to estimate).
Value
A single numeric standard error, or NA if fewer than two non-missing
values are present.
See Also
se_prop(), rse(), margin_of_error(), diagnose().
Other diagnostics:
diagnose(),
margin_of_error(),
precision_summary(),
rse(),
rse_rating(),
se_prop()
Examples
se_mean(c(4, 5, 3, 4, 5, 2, 4))
Standard error of a proportion
Description
sqrt(p * (1 - p) / n), the sampling error of a percentage. Packages the
inline proportion-error calculation from the report appendix.
Usage
se_prop(p, n, pctp = FALSE)
Arguments
p |
The proportion, either as a fraction in |
n |
The sample size (number of respondents). |
pctp |
Return the answer in percentage points instead of on the |
Details
For a percentage from a survey, the sampling error is sqrt(p * (1 - p) / n).
It is largest when p = 0.5 (a 50/50 split is the hardest to pin down) and
shrinks towards the extremes. The result is on the same 0–1 scale as a
fractional p; pass pctp = TRUE for percentage points, the form used in
report footnotes and the one margin_of_error() needs if you want the margin
in points. Inputs above 1 are treated as percentages and divided by 100, so
se_prop(33, n) and se_prop(0.33, n) agree.
Value
The standard error of the proportion, on the same [0, 1] scale as a
fractional p, or in percentage points when pctp = TRUE.
See Also
se_mean(), rse(), margin_of_error(), diagnose().
Other diagnostics:
diagnose(),
margin_of_error(),
precision_summary(),
rse(),
rse_rating(),
se_mean()
Examples
se_prop(0.33, 1184)
se_prop(0.33, 1184, pctp = TRUE)
Select identifier and prefixed columns
Description
Keeps a handful of id columns plus every column sharing a prefix – the
select(id, starts_with("demo_")) idiom – in one tidy call.
Usage
select_prefix(data = NULL, prefix, keep = NULL)
Arguments
data |
A data frame. If omitted, the session default ( |
prefix |
One or more column-name prefixes to keep (e.g. |
keep |
Optional character vector of additional column names to retain in front of the prefixed block (e.g. an id column). |
Details
Survey questionnaires are usually organised by prefix (demo_, ratings_,
partner_, ...), so this is a quick way to grab one block plus a couple of id
columns without naming every variable. Order is keep first, then the
prefix-matching columns in their original order.
Value
A data frame with keep columns followed by all prefix-matching
columns.
See Also
read_folder(), calc_percentage_multi().
Other import:
parse_filename(),
read_folder(),
select_suffix()
Examples
select_prefix(podracing_survey, "demo_", keep = "respondent_id")
select_prefix(podracing_survey, c("ratings_", "partner_"))
Select identifier and suffixed columns
Description
The mirror of select_prefix(): keeps a handful of id columns plus every
column sharing a suffix – the select(id, ends_with("_com")) idiom – in
one tidy call.
Usage
select_suffix(data = NULL, suffix, keep = NULL)
Arguments
data |
A data frame. If omitted, the session default ( |
suffix |
One or more column-name suffixes to keep (e.g. |
keep |
Optional character vector of additional column names to retain in front of the suffixed block (e.g. an id column). |
Details
Some questionnaire blocks are marked by a trailing tag rather than a leading
one (_com open-text follow-ups, _score derived columns), so this grabs
one such block plus a couple of id columns without naming every variable.
Order is keep first, then the suffix-matching columns in their original
order.
Value
A data frame with keep columns followed by all suffix-matching
columns.
See Also
select_prefix(), read_folder().
Other import:
parse_filename(),
read_folder(),
select_prefix()
Examples
select_suffix(podracing_survey, "_com", keep = "respondent_id")
Set a survey weighting scheme for the session
Description
Defines target shares for one or more categorical variables (e.g. a known
population split by gender or region). Once set, the summary helpers
(calc_percentage(), calc_nps(), calc_summary(), crosstab()) weight
their results automatically, so the weighted margins match your targets. Pass
weights = FALSE to any of them to opt out for a single call.
Usage
set_weights(...)
Arguments
... |
One scheme per variable. Two forms are accepted:
|
Details
With a single variable the weights are exact post-stratification:
target_share / sample_share for each category. With several variables the
weights are found by raking (iterative proportional fitting) so every variable's
weighted margin matches its targets. Weights are normalised to mean 1 (so the
weighted base equals the sample size), and respondents whose weighting value is
blank / a non-answer (see na_blank()) are left unadjusted. A category that
appears in the data but is missing from your targets is an error – give every
observed category a share. If a default dataset is set, this prints the Kish
design effect and the effective sample size so you can see the precision cost.
Value
Invisibly, the parsed scheme (a named list of normalised targets).
See Also
clear_weights(), get_weights(), weight_vector(),
calc_percentage().
Other weighting:
clear_weights_cache(),
get_weights(),
weight_vector()
Examples
set_weights(c(variable = "demo_gender",
"Male" = 0.49, "Female" = 0.50,
"Non-binary" = 0.01))
calc_percentage(podracing_survey, satis_return) # gains a wpct column
clear_weights()
Simulated historical shopping-behaviour survey
Description
A fictional survey of patrons of a turn-of-the-century (c. 1905) general emporium, written in an Edwardian register for colour. It behaves like a real survey export – a latent satisfaction drives the worded attribute ratings and the recommend score together, demographics use standard sex/country categories alongside period social-class and occupation items, and the multi-select and open-text columns mirror the shapes the helpers consume. A companion to podracing_survey for examples that want a second, very different theme.
Usage
shopping_survey
Format
A tibble with 800 rows and 25 columns:
- patron_id
Unique patron id (character).
- demo_age
Age in years (integer, 18-80).
- demo_gender
Sex (Female / Male, some "Prefer not to answer").
- demo_country
Country of residence (ISO 3166 names).
- region
World region derived from
demo_country.- social_class
Edwardian social class (Upper class .. Poor).
- occupation
Period occupation (Clerk, Domestic servant, ...).
- household_size
Number in the household (integer).
- weekly_spend
Weekly spend at the emporium, in shillings (numeric).
- payment
How they pay: Cash, On account or Barter.
- transport
How they travel to the shop (On foot, Horse and cart, ...).
- visit_frequency
How often they visit (Never .. Always).
- recommend
0-10 "would recommend to a neighbour" rating (integer).
- ratings_goods, ratings_service, ratings_credit, ratings_delivery, ratings_value
Worded 1-5 attribute ratings (Very bad .. Very good).
- reasons_price, reasons_quality, reasons_credit, reasons_proximity, reasons_variety, reasons_service
Multi-select reasons for patronage; each holds its option text when chosen, otherwise
"".- comment
Open-text comment (mostly blank).
Source
Simulated. See data-raw/make_shopping_survey.R for the generator.
See Also
Other data:
country_region,
currency_rates,
podracing_survey
Examples
calc_percentage(shopping_survey, social_class, sort = "desc")
calc_summary(shopping_survey, weekly_spend, by = payment)
Split a packed multi-select column into one column per answer
Description
Turns the single cell a spreadsheet export gives a "tick all that apply"
question ("Speed; Drivers; Betting") into the one-column-per-option layout
the rest of the package expects, so calc_percentage_multi(), crosstab()
and the plots all work on it.
Usage
split_multi(data = NULL, column, split = "auto", prefix = NULL)
Arguments
data |
A data frame. If omitted, the session default ( |
column |
The packed column (unquoted). |
split |
The delimiter between answers inside a cell. |
prefix |
Prefix for the new column names. Defaults to the column's own
name followed by an underscore, e.g. |
Details
Google Forms, Google Sheets and most survey platforms export a multi-select question as one cell per respondent holding every answer they ticked, joined by a delimiter. That shape cannot be counted directly, because a respondent who ticked three options is one row, not three. This function unpacks it into the indicator layout the package's own datasets use.
The new columns are named prefix plus the answer text verbatim, which keeps
the labels readable all the way through to a chart: calc_percentage_multi()
strips the prefix back off and uses what remains as the option label. Answer
text is rarely a syntactic R name, so refer to the new columns with backticks
if you need them individually. Surrounding whitespace is trimmed and empty
answers are dropped, so "Speed; ; Drivers" yields two options. When no cell
contains the delimiter, each cell is treated as a single answer, which is the
right answer for a multi-select question everyone happened to answer once.
If you only want the percentages, skip this step: calc_percentage_multi()
detects a packed column and splits it for you.
Value
The data frame with one new column per distinct answer, each holding
the answer text for respondents who chose it and "" for those who did
not, ordered most-chosen first. The packed column is kept.
See Also
calc_percentage_multi(), na_blank().
Other recode:
add_region(),
bin_numeric(),
clean_label(),
drop_items(),
ensure_numeric(),
generation_scheme(),
na_blank(),
nps_group(),
recode_age(),
recode_generation(),
recode_likert(),
recode_region()
Examples
packed <- data.frame(
respondent = 1:4,
motivations = c("Speed; Drivers", "Speed", "", "Betting; Speed")
)
split_multi(packed, motivations)
split_multi(packed, motivations) %>%
calc_percentage_multi("motivations_", id = respondent, sort = "desc")
ezrsurvey ggplot2 themes
Description
A clean, presentation-oriented theme family for survey reporting. The base
theme strips chart junk – no ticks,
no gridlines, centred bold titles – which suits labelled bar charts that
carry their own data labels. The _x / _y / _xy variants add back faint
major gridlines on the named axes.
Usage
theme_ezrsurvey(base_size = 11, base_family = NULL, transparent = FALSE)
theme_ezrsurvey_x(base_size = 11, base_family = NULL, transparent = FALSE)
theme_ezrsurvey_y(base_size = 11, base_family = NULL, transparent = FALSE)
theme_ezrsurvey_xy(base_size = 11, base_family = NULL, transparent = FALSE)
Arguments
base_size |
Base font size in points. Defaults to |
base_family |
Base font family. |
transparent |
If |
Details
A clean, presentation-first look: no axis ticks, no chart junk, bold centred
titles, and faint gridlines only where you ask for them. The base
theme_ezrsurvey() strips gridlines entirely (best for bar charts that carry
their own data labels); the _x / _y / _xy variants add back faint major
gridlines on the named axes. transparent = TRUE makes the backgrounds
transparent for slides. All the plot_*() helpers apply one of these for you.
Value
A ggplot2::theme() object to add to a plot with +.
See Also
Other themes:
pal_rating,
scale_fill_nps(),
scale_fill_rating(),
theme_transparent()
Examples
df <- calc_percentage(podracing_survey, demo_gender)
ggplot(df, aes(demo_gender, pct)) + geom_col() + theme_ezrsurvey()
ggplot(df, aes(demo_gender, pct)) + geom_col() + theme_ezrsurvey_y()
Transparent-background theme fragment
Description
A small ggplot2::theme() fragment that makes the plot, panel and legend
backgrounds transparent. Add it to any theme for slide-friendly exports; the
transparent argument of theme_ezrsurvey() applies it for you.
Usage
theme_transparent()
Value
A ggplot2::theme() object.
See Also
Other themes:
pal_rating,
scale_fill_nps(),
scale_fill_rating(),
theme_ezrsurvey()
Examples
p <- calc_percentage(podracing_survey, demo_gender) %>% plot_bars()
p + theme_transparent()
Adopt an organisation brand from a PowerPoint or Word template
Description
Reads the colour and font theme out of your organisation's .pptx / .docx
template and makes it the session default for everything ezrsurvey produces:
charts pick up the brand accent colours and body font, and the template file
itself becomes the default reference document for report_new(),
report_deck() and scaffold_report(). One call, and analysis output is
on-brand.
Usage
use_brand(template = NULL, colors = NULL, fonts = NULL, quiet = FALSE)
Arguments
template |
Path to a |
colors |
Optional character vector of hex colours overriding the extracted accents. A single colour sets only the primary; a vector sets the full accent palette (first entry = primary). Invalid entries are dropped with a warning. |
fonts |
Optional character vector overriding the extracted typefaces:
either a single body font, or |
quiet |
If |
Details
Extraction reads theme1.xml inside the template (requires the suggested
xml2 package): accent colours 1-6 become brand_colors (first accent =
brand_color_primary, the default fill of plot_bars()), and the minor
(body) typeface becomes the default base_family of theme_ezrsurvey() –
but only when that font is actually installed on this machine, so charts
never render with substituted glyph boxes. Set
ezrsurvey_options(brand_fonts_enabled = FALSE) to keep brand colours but
ignore brand fonts.
A brand font also needs a graphics device that reads the machine's fonts.
The pdf and postscript devices do not: they carry their own short list of
families, and a chart printed to one fails with "invalid font type". That is
the default device in a plain Rscript run, so use_brand() says so when it
sets a font there. Charts written with save_plot() are unaffected, because
it saves through a device that does read system fonts.
Everything lands in ordinary ezrsurvey_options() (brand_* keys), so you
can equally set the values by hand or persist them in a YAML profile; a
later use_brand() call simply overwrites them. Semantic palettes
(pal_rating, pal_nps) deliberately keep their meaning-carrying colours
and are not rebranded. Use clear_brand() to return to the neutral look.
Value
Invisibly a ezrsurvey_brand list (see brand_info()).
See Also
brand_info(), clear_brand(), pal_brand(),
scale_fill_brand(), report_new(), scaffold_report().
Other brand:
brand_info(),
clear_brand(),
pal_brand(),
scale_fill_brand()
Examples
tmp <- tempfile(fileext = ".pptx")
print(officer::read_pptx(), target = tmp)
use_brand(tmp, quiet = TRUE)
brand_info()
clear_brand()
# Or set brand values directly, no template needed:
use_brand(colors = c("#0B5394", "#E69138"), fonts = "Georgia", quiet = TRUE)
clear_brand()
Set a default dataset for the session
Description
Registers a data frame as the session's default, so the analysis helpers can
be called without repeating data every time. Set it once at the top of a
script or Quarto document and then omit data (or pass it by pipe).
Usage
use_dataset(data)
Arguments
data |
A data frame to use as the default. |
Details
With a default set you can drop data entirely and name the column
positionally, the way you would in the tidyverse:
-
calc_percentage(demo_gender)– data taken from the default; -
podracing_survey %>% calc_percentage(demo_gender)– explicit pipe; -
calc_percentage(other_survey, demo_gender)– an explicit data frame always wins over the default.
The helpers tell a column from a data frame by looking at the first argument:
a data frame is used as the data; anything else (a bare column name) is taken
as the first column and the data comes from the default. Helpers that select
several columns through ... (e.g. diagnose(), calc_percentage_batch())
work the same way – diagnose(starts_with("ratings_")) needs no data.
The default applies to the analysis helpers that read a raw survey
(calc_percentage(), calc_summary(), calc_nps(), diagnose(),
crosstab(), ipm_model(), sample_comments(), ...). It does not apply
to plot/report helpers that consume an already-summarised table. The setting
lives only in the current R session; clear it with clear_dataset().
Value
data, invisibly (so it can sit in a pipe).
See Also
get_dataset(), clear_dataset(), has_dataset().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_ezrsurvey_profile()
Examples
use_dataset(podracing_survey)
calc_percentage(demo_gender) # data taken from the default
calc_nps(nps_value)
clear_dataset()
Create a starter ezrsurvey profile
Description
Writes a commented YAML profile (pre-filled with the current defaults) you can
edit to set persistent options. By default it is written to the per-user
config directory (tools::R_user_dir()), which is where ezrsurvey looks first.
Usage
use_ezrsurvey_profile(path = NULL, overwrite = FALSE)
Arguments
path |
Destination path. If |
overwrite |
Overwrite an existing file. Defaults to |
Value
Invisibly the path written.
See Also
load_ezrsurvey_profile(), ezrsurvey_options().
Other config:
apply_order(),
edit_ezrsurvey_profile(),
ezrsurvey_options(),
ezrsurvey_profile_paths(),
get_dataset(),
get_order(),
list_orders(),
load_ezrsurvey_profile(),
order_for(),
register_order(),
register_order_presets(),
remove_order(),
reset_ezrsurvey_options(),
save_ezrsurvey_profile(),
use_dataset()
Examples
tmp <- tempfile(fileext = ".yml")
use_ezrsurvey_profile(tmp)
head(readLines(tmp))
Compute the per-respondent survey weights
Description
Returns the weight vector a scheme implies for a dataset – the same numbers the summary helpers use internally – so you can inspect them, attach them as a column, or feed them to another tool.
Usage
weight_vector(data = NULL, weights = NULL)
Arguments
data |
A data frame. If omitted, the session default ( |
weights |
A weighting scheme (any form accepted by |
Details
This is the function behind the automatic weighting: each respondent's weight is
target_share / sample_share for their category (raked across variables when
there are several), normalised so the weighted base equals the unweighted one.
Pair it with set_weights()'s reported design effect to judge how much
precision the weighting costs.
Value
A numeric vector of length nrow(data), normalised to mean 1.
See Also
set_weights(), calc_percentage().
Other weighting:
clear_weights_cache(),
get_weights(),
set_weights()
Examples
target <- c(variable = "demo_gender",
"Male" = 0.49, "Female" = 0.50, "Non-binary" = 0.01)
w <- weight_vector(podracing_survey, target)
# The sample under-represents women, so their weights are above 1 and the
# weighted share moves towards the target. Categories the target does not
# mention keep a weight of 1, which is why their shares do not move.
podracing_survey %>%
mutate(weight = w) %>%
group_by(demo_gender) %>%
summarise(
unweighted_pct = round(n() / nrow(podracing_survey) * 100, 1),
weighted_pct = round(sum(weight) / nrow(podracing_survey) * 100, 1)
)