crosstab_banner() no longer stops with
“Element … doesn’t exist” when the same binary-encoded columns (an
option label or blank) are named in both rows and
cols. The multi-select block reshaped its own member column
away before grouping by it. Each block is now tabulated from its own
columns, which also keeps an unrelated column that happens to share the
prefix out of it.crosstab_banner() chooses its own variables, whatever
max_levels is. Each gives one column of the respondents who
ticked it, and the columns of a multi-select block share one spanner
named after the block. A lone binary column is used across the top only;
as a stub every cell would read 100.save_plot(), save_data(),
save_output(), export_xlsx(),
export_summary_xlsx(), report_save(),
report_deck(), scaffold_report(), and
dir in example_report().output_dir option defaults to
".", so a bare file name is written in the working
directory as named. Set it to a folder, in a session or in your profile,
to collect bare names there as before.sample_comments() and
sample_comments_diverse() set their seed
through withr, which is now imported, and no longer touch the global
environment.crosstab() and
crosstab_banner() no longer break on a question
called value or n. Both used those names for
their own counting, so such a column came back as a table of the wrong
shape without a word: percentages for headings, a list-column, a banner
group of zeros. The counting now runs under names no survey uses. The
long form of crosstab() still puts its cells in a column
called value, so it refuses a question of that name and
says so; the wide form and the banner handle it.calc_percentage() and crosstab()
keep a factor’s own level order. Without a registered order, a
factor came back as text in alphabetical order, so PISA’s “Strongly
disagree” to “Strongly agree” read Agree, Disagree, Strongly agree,
Strongly disagree. A registered order or levels = still
wins; a factor’s levels now come next, and only then data order.crosstab() puts its columns in level
order whenever the column variable has one. tidyr names new
columns by first appearance, so a registered order could still come out
scrambled when the first row lacked the first answer.bin_numeric(), recode_age() and
recode_generation() return factors whose levels
follow the bands, where they used to return text. Text sorted “100-150k”
before “40-70k” in every table built from it. Code comparing the result
to a string is unaffected; wrap it in as.character() where
plain text is needed.checkpoint = TRUE made;
a path you chose is kept, as the help page already said.Free-text country questions do not come back tidy. In one real open
salary survey of 26,232 people, nine thousand wrote “United States” and
eight thousand wrote “USA”; the bundled table matched the first and
missed the second, so recode_region() resolved 49% of the
column.
recode_region(),
recode_subregion() and add_region()
now fold the answer down before looking it up (case, punctuation,
accents and a leading “the” are dropped) and then try a table of the
spellings people actually use. It carries endonyms
("Deutschland", "Brasil",
"Espana"), the constituent countries of the United Kingdom,
and ISO 3166-1 alpha-2 and alpha-3 codes, so a column already coded to
the standard needs no preparation. On that same survey the three
functions now resolve 99.3%, and what remains are real typos worth
seeing."NO" is
Norway and "no" stays unmatched. Unambiguous codes match
either way.country_region gains iso2
and iso3 columns, so a region breakdown can be reported
against ISO 3166-1 rather than against country names. Every country
carries both except Kosovo, which has no code of its own. Namibia’s
alpha-2 code is the two letters "NA", which is worth
knowing before filtering on the column."Ise of Man", "America Samoa"
and "Kazakstan". Bermuda was missing altogether. All four
are fixed, and the duplicate rows the corrections exposed are gone,
which takes the table from 182 rows to 180.Satisfaction is often collected on 0 to 100, and seven-point agreement scales are common. The band presets are written on 1-5, 0-10 and -100..100, so until now a chart on any other scale meant dividing the data to meet the thresholds, which left the axis showing a scale nobody had been asked about.
rescale_bands() stretches any band
specification onto the scale the chart actually uses:
bands_rating_3() %>% rescale_bands(to = c(0, 100)). The
mapping is proportional, and labels and colours are untouched. It works
on a hand-built band data frame as well as on the presets.register_order() set the levels of the answer column and
stopped there. The levels are what a chart reads, so charts were right;
a table printed to the console or written to CSV carries no levels with
it, so every number anybody actually read came back in alphabetical
order. On a recency scale that puts “In the past month” above “In the
past week”.
calc_percentage() sorts its rows into
the registered order. A by = breakdown keeps its groups
together and orders within each one.crosstab() does the same on both
margins. Column order was affected too, because tidyr names new columns
in order of first appearance rather than by factor level.plot_ipm() pinned its performance axis
to 1-5 whatever bands it was given. A study rated on 0-100 or on a
seven-point scale came back as an empty panel with the bands still drawn
across it, and ggplot2’s only complaint was that some rows had been
removed. The axis now runs over whatever scale the bands describe, and a
feature that really does fall outside them is named in a message rather
than dropped in silence.Three separate faults kept recode_region() from matching
countries that were spelled perfectly. On the Stack Overflow Developer
Survey, whose country column is coded to ISO 3166-1, 3,126 of 87,973
answers came back NA. They now resolve to 99.93%, and the
only thing left unmatched is the answer “Nomadic”.
"Timor-Leste",
"Guinea-Bissau", "Cote d'Ivoire",
"Korea, North", "Gambia, The" and some thirty
more.country_region held 180 of the 249 entries in
ISO 3166-1. What was missing was not obscure: Ghana, Ethiopia,
Senegal, Rwanda, Yemen, Benin, Botswana, Haiti, Mali, Sierra Leone and
South Sudan all returned NA. The table is now complete at
255 rows, grouped the way the package groups countries rather than the
way the UN does, so no answer already built on it changes."Viet Nam", "Syrian Arab Republic",
"Lao People's Democratic Republic",
"Brunei Darussalam", "Cabo Verde",
"Eswatini", "North Macedonia" and the rest are
what a questionnaire built on the standard shows a respondent. They
match now, in ISO’s inverted order ("Moldova, Republic of")
and in the order the name is actually said
("Republic of Moldova").Matching a country meant stripping its accents, and that was left to
iconv(to = "ASCII//TRANSLIT"), which three platforms turned
out to do differently. Windows writes a German sharp s as
?; macOS leaves a circumflex where it found one, so
"Cote d'Ivoire" typed with its accent matched on Linux and
came back NA on a Mac. A published figure changed with the
machine that produced it.
recode_region(),
recode_subregion() and add_region()
now fold the eighty-eight accented letters and four ligatures a country
name can carry by hand, and reach iconv only for anything
outside that range. The answer is the same on every platform."Estados Unidos",
"Etats-Unis", "Vereinigte Staaten",
"Stati Uniti", "Reino Unido" and
"Royaume-Uni" now match.use_brand() says so when it sets a
typeface in a session whose default device is pdf, which is
what a plain Rscript run gets. That device carries its own
short list of font families and fails at drawing time with “invalid font
type” rather than substituting. Charts written with
save_plot() were never affected.calc_percentage(d, gendr) reported
replacement has 0 rows, data has 3, which describes an
assignment the caller never made; it now says
Column `gendr` not found in the data. Did you mean `gender`?.
The same applies to calc_summary(),
calc_nps(), crosstab(),
plot_nps() and split_multi().calc_nps() works on a frame filtered
down to no rows instead of failing with
replacement has 1 row, data has 0. Filtering to a segment
nobody fell into is ordinary, and the answer is a zero count, not an
error.crosstab_banner() refuses a frame with
no rows in a sentence that says a filter is the usual cause, rather than
reporting the same internal mismatch.plot_stacked_rating() names the
argument the caller actually omitted. Leaving out level
reported a missing level_sym, which is not an argument it
has.plot_rating_grid() reports two answers
that land on the same rank. recode_likert() falls back to
matching on a substring, and “Neither agree nor disagree” contains
“disagree”, so a five-point scale handed only four levels drew two
segments both numbered 2. The chart looked plausible and was wrong; now
it says which level is missing.plot_quotes_tree() says which column
it cannot find. Its defaults are the comment and
length columns sample_comments() produces, and
handed anything else it failed at drawing time with a ggplot error about
an object of type <function>, because
length had resolved to the base function.read_folder() notices when the first
row of a file is question wording rather than an answer, which is how
survey platforms export the question text, and says so. Read as data it
becomes respondent number one and shifts every count by one. The new
question_row argument drops that row from every file
(TRUE), keeps it silently (FALSE), or keeps it
and warns (NULL, the default).recode_age() reports answers that held
no number at all. "young" and
"prefer not to say" became NA in silence,
which made a column that was never numeric look like a column of missing
ages. New quiet argument.README.md had
pointed at man/figures/logo.png since the first release
without that file ever existing, so the front page of the README and of
the documentation site both opened with a broken image.Google Forms and most spreadsheet exports put every answer a respondent ticked into a single cell, joined by a delimiter. That shape could not be counted before, because a respondent who ticked three options is one row, not three.
calc_percentage_multi() now detects a
packed column and unpacks it. When the prefix matches exactly one column
and a ";", "|" or "," is found
inside it, the answers are separated and the answer text becomes the
option label. split = "," forces a delimiter and
split = FALSE turns the detection off. A block of
one-column-per-option behaves exactly as before.split_multi() is the new recode helper
for the same shape, widening a packed column into one column per answer
so that crosstab(), the plots and everything else can use
it too.calc_nps()
shows how the score was reachedpct_detractors,
pct_passives and pct_promoters, with the
counts behind them in detractors, passives and
promoters. A single NPS hides its own composition: +20 from
40% promoters and 20% detractors is a different picture from +20 with
25% and 5%. Counts are unweighted; the shares follow nps
and so are weighted when a scheme is active.calc_importance()
offers a second and third opinionmethod argument.
"rwa" (relative weights analysis) remains the default and
is unchanged. "forest" adds random-forest permutation
importance, which sees non-linear effects and interactions that relative
weights cannot, so a feature ranking high there and low under
"rwa" is a signal worth chasing. "correlation"
needs no suggested package at all.plot_ipm(). ipm_model(method = ) passes the
choice through.plot_gauges()
says what its bars are measuring-100 0 30 70 100 and a quality bar reads
1 3 4 5. The bars share one panel but not one scale, so no
axis could serve them both and they carried no scale at all: a marker
two thirds along the bar said nothing about the score it marked."EXCELLENT" in the 30-point band at the top of the NPS
scale was printed as "EXCELLEN".se_prop(pctp = TRUE) returns the
standard error in percentage points, the form report footnotes use,
instead of leaving you to multiply by 100.plot_nps() is centred over the
promoter bars, like the detractor and passive callouts beside it. It had
been pinned to the right edge of the panel, which left
"Very likely" hanging off to one side of the
"% PROMOTER" line above it.rse_rating() now
say exactly what the Australian Bureau of Statistics does and where
ezrsurvey departs from it.library(ezrsurvey) still puts dplyr, ggplot2, tidyr,
tibble, readr, stringr and purrr on your search path, so nothing changes
in a script. The package now names those seven in Depends
rather than depending on the tidyverse meta-package, which
had tied it to every package in that tree.crosstab_banner(checkpoint = TRUE) now deletes
its checkpoint once the table is built. A finished run has
nothing left to resume from, so the file it kept under
tools::R_user_dir() is removed instead of
accumulating.clear_checkpoints() empties that
folder, for runs that were interrupted and never repeated.checkpoint = "my-run.rds") is your file: it is left
exactly where it is, and clear_checkpoints() never touches
it.scaffold_report() now follows the same
rule as every other writer: a bare name lands in
ezrsurvey-outputs/, so the .qmd sits where its
rendered output will. Pass a path naming a directory to put it somewhere
else.recode_likert() now tries the longest
answer wording first. A scale whose levels nest inside one another
(“Good” inside “Very good”, “Likeable” inside “Very likeable”)
previously resolved any answer the exact pass missed to the
shorter level, so an answer carrying an emoji or a
stray character was quietly downgraded. If your data has such a scale
and any untidy answers, ratings, feature averages and
ipm_model() performance scores will change, and the new
numbers are the correct ones. Supplied synonyms follow the
same longest-first rule.bin_numeric() reports values that fell
outside breaks instead of turning them into NA
in silence, and takes quiet = TRUE to suppress that. A
closed top band under an open-ended label (35 to
40.5 labelled “35 to 40+”) silently drops everyone above
it; Inf is what that label means.NA rather than letting them appear as
an unlabelled bar.crosstab_banner(), export_summary_xlsx(),
report_deck(), read_folder(),
diagnose() – now report the question, file or slide they
are on, with a measured estimate of the time remaining. A full
every-variable banner is one cross-tab per question per grouping
variable, so it takes minutes on a wide survey and used to give no sign
of life at all.progress option
(ezrsurvey_options(progress = )): "auto"
(default) reports in an interactive session and stays silent in scripts,
vignettes and R CMD check; TRUE /
FALSE force it either way.ezrsurvey-outputs/, created on demand:
save_plot(p, "nps.png") writes
ezrsurvey-outputs/nps.png, and the same holds for
save_data(), save_output(),
export_xlsx(), export_summary_xlsx(),
report_save() and report_deck(). Previously
only the path = NULL default used that folder, so any
script that named its files scattered them through the working
directory."./nps.png" for the
working directory, "charts/nps.png" for a folder of your
own, or any absolute path (so tempfile() is
unaffected).output_dir option (default
"ezrsurvey-outputs") renames that folder for a project, or
set it to "." to put bare names back in the working
directory.crosstab_banner() and
export_summary_xlsx() choose their own variables when none
are named, and that choice decides everything they produce. Both now
print the questions kept, the grouping variables and the columns
skipped, and wait for a yes before a run that takes minutes. Naming
rows / cols (or the variables to summarise) is
your own choice and is never questioned.confirm option and argument:
"auto" (default) asks in an interactive session and never
asks in a script, so an unattended run cannot stall on a prompt;
TRUE / FALSE force it either way. Answering no
computes nothing and returns NULL.crosstab_banner(checkpoint = ) saves
each question as it finishes, so re-running the identical call after a
crash or an interrupt continues instead of starting over. A checkpoint
written from different data or different arguments is reported and
discarded, never blended into the new run. Use TRUE to have
the file managed under tools::R_user_dir(), or name a path
to choose the ___location. Nothing is written unless you ask.clear_weights_cache() empties the cache;
clear_weights() does it too.sample_comments_diverse(max_candidates = )
narrows a large corpus to a random shortlist (default 500) before
comparing every comment with every other, which is what made it slow and
memory-hungry on a big survey.plot_rating_grid() builds a stacked
rating chart for a whole block of prefix-sharing columns in one call:
tabulate, tidy the question names, number the answers by their place on
the scale, stack. It replaces an eight-line block per question block,
and it reports answers that are not on the scale instead of
leaving them as an unranked segment.clean_label() is now exported. It is
the tidying calc_percentage_multi() and
ipm_model() already applied to their own output, so a
hand-built table can be made to match them: labels that disagree will
not join, which is what silently empties a comparison chart.calc_percentage_batch(clean_names = , prefix = )
applies that same tidying to its variable column.bands_nps_score() exposes the Net
Promoter Score band set (needs work / good / great / excellent over
-100..100) that was previously locked inside
plot_nps_gauge(). Note bands_nps() is the 0-10
answer scale and is a different thing.from /
to to trim themselves to the part of the scale a
chart actually shows, e.g. bands_rating_3(from = 2) on a
2-5 panel.report_new(keep_slides = FALSE) starts
from an empty deck, dropping any boilerplate slides the template
carries.sample_comments(by = ) samples
n comments per group and keeps the group as a column,
replacing a hand-rolled loop over the groups.ezrintelligence
package: ai_chat(), ai_summarise(),
ai_report_sections(), ai_context(), the
prompt-template registry (list_prompts(),
get_prompt(), register_prompt()) and key
management (set_llm_key(), get_llm_key(),
has_llm_key(), delete_llm_key(),
list_llm_keys()). Install it alongside ezrsurvey and pass
it any summary table ezrsurvey produces. ellmer and
keyring are no longer suggested dependencies.report_deck() loses its
ai, ai_titles, chat,
provider, model and context
arguments. For AI slide text, call
ezrintelligence::ai_slide_text() on the table behind a
slide and place the title and bullets it returns yourself.ai parameter and the eval-gated AI chunks; they render with
placeholder narrative and their data parameter as
before.export_summary_xlsx() no longer fails
with “Failed to save workbook” when R_ZIPCMD names a zip
tool that is not installed. openxlsx2 reaches for an external zip
whenever that variable is set, and R sets it to a bare zip
on Windows under R CMD whether or not a
zip.exe exists; the workbook is now written with
openxlsx2’s own zipping code whenever the named tool cannot be
found.crosstab_banner() example that crosses every
variable against every other moves to \donttest, where its
runtime belongs. # ezrsurvey 0.4.0crosstab_banner() builds the
market-research banner table: a stack of question variables down the
side (rows) and one or more grouping variables across the
top (cols), plus a whole-sample Overall
column. Categorical questions become column-percentage blocks (each
column sums to ~100 within a block); numeric questions turn into a
mean/median/sd/quartile block automatically. cell = "diff"
shows each cell’s distance from the Overall column,
long = TRUE returns the tidy form, and
flextable = TRUE renders the two-row spanning header for a
slide or Word report. It generalises crosstab() from a
single pair to a whole table. Pass only the data frame
to cross every variable against every variable; identifier and free-text
columns are skipped, and check-all-that-apply blocks
(e.g. motivations_*) are folded into a single multi-select
stub question with the correct question-level base.export_summary_xlsx() writes a tabbed
Excel workbook with one worksheet per question, each holding that
question’s summary table and its chart (percentages and a bar chart for
categorical questions, a calc_summary() table and a
histogram for numeric ones, a calc_percentage_multi() table
for a check-all-that-apply block). Called with just the data
frame it writes every question at once, one multi-select block
to a single sheet, skipping identifier and free-text columns. The Excel
counterpart of the slide/Word report_deck(). Needs the
suggested openxlsx2 package.ezrsurvey-outputs/ (was
outputs/). save_plot(),
save_data(), save_output(),
export_xlsx(), report_save() and
report_deck() write straight into it with no per-type
subfolders when no path is given; explicit paths behave as
before.library(ezrsurvey) brings
dplyr, ggplot2, tidyr,
stringr and the rest with it, so scripts and reports never
need to load the packages ezrsurvey wraps.use_dataset() finally saves the typing it
promised. With a default set, columns can be passed
positionally with no data and no column =:
calc_percentage(demo_gender),
calc_nps(nps_value),
crosstab(demo_gender, region),
diagnose(starts_with("ratings_")). The helpers tell a data
frame from a column by looking at the first argument, so an explicit
data frame or a pipe still wins. Previously only the much longer
calc_percentage(column = demo_gender) worked, which saved
nothing over just passing the data.plot_gauges() draws several scores as
thin banded gauge bars stacked one above another – the summary-slide
staple of the Net Promoter Score over the average feature quality
rating, each on its own scale with a marker, instead of one fat single
bar. plot_nps_gauge() remains for a single score.bands_rating_3(). [plot_ipm()] now
colours every point by the band it actually falls in, and
pal_rating uses the same thresholds (1-2 bad, 3 ok, 4-5
good). plot_ipm() gains a bands argument.use_brand() adopts an organisation
brand from a .pptx / .docx template: theme
accent colours and typefaces are extracted from the file’s OOXML theme
and become the session defaults (plot_bars() fill,
theme_ezrsurvey() font when installed locally), and the
template is registered as the default reference document for
report_new(), report_deck() and
scaffold_report(). Colours/fonts can also be set directly
(use_brand(colors =, fonts =)) or persisted in the YAML
profile (brand_* options). brand_info() shows
and clear_brand() resets the active brand.pal_brand() and
scale_fill_brand() /
scale_colour_brand() expose the brand accents to any plot;
semantic palettes (pal_rating, pal_nps)
deliberately keep their red-amber-green meaning.One line per slide. New wrappers collapse
calc -> plot -> add onto a single pipe step so a deck
script reads as one line per slide:
report_slide(title, content) starts a titled slide and
places its content (a ggplot becomes a chart, a data frame a table, a
character vector a bullet list);
report_section("DEMOGRAPHICS") drops a single-word divider;
and report_title_slide(title, subtitle) opens the deck. The
rewritten example_report() deck is built this way as a full
agency read-out – cover, chaptered sections and every question block in
the questionnaire (recommendation, the six experience ratings and their
drivers, motivations, the three sponsor brands, the whole respondent
profile, favourite drivers, open-text comments and a methods appendix) –
with each slide title the survey question it answers.
Slide tables fill the slide.
report_add_table() now styles the table (banded header,
centred cells, a readable 12pt font) and widens its columns to span the
content placeholder, so a summary table fills the slide instead of
sitting tiny in a corner.
Headlines and bullets no longer overflow. The bundled templates bring the master title/body font sizes down to deck-appropriate values and give every text placeholder shrink-to-fit, so a descriptive question headline or a long bullet list is scaled to its box rather than spilling out of it.
Decks are 16:9 by default, and properly
designed. Without a brand template, report_new(),
report_deck() and the Quarto pptx scaffold use a built-in
widescreen template with a coherent navy/gold identity in place of the
dated default Office colours: a full-bleed navy cover with a large
left-aligned title, gold accent rule and a subtitle strapline;
full-bleed navy section dividers carrying a single large section word;
and content slides with a navy 24pt title over one slim rule (no stray
hairlines) and a live slide number in the corner.
report_title_slide() gains a subtitle argument
for the cover strapline. Pass style = "plain" for the same
palette with no decoration, or slide_numbers = FALSE to
drop the numbering. Both templates keep the standard PowerPoint layout
names (plus “Content with Caption”), so Quarto renders against either
without falling back to Pandoc’s own template.
Bars are a constant thickness across charts.
geom_col() widths are a fraction of a category slot, so a
three-answer chart used to draw bars over twice as thick as a ten-answer
one and a deck looked incoherent as you flicked through it.
[plot_bars()] now scales the fraction with the bar count so the drawn
thickness is the same everywhere (bar_width /
bar_ref_items, see
ezrsurvey_options()).
example_report() copies a complete
worked report into your project: a full narrative report over the
bundled podracing_survey and the matching deck script. Both
are written the way a real readout is – a story that runs headline, then
cause, then segment, then evidence; slide titles that state the finding
rather than name the chart; and every figure in the prose computed from
the data rather than typed in, so the narrative cannot drift.
The officer builders now work with any corporate
template: slide layouts are chosen by inspecting placeholder
types (not locale-dependent layout names), slide titles are skipped with
a warning when a layout has none, and plots/tables are rendered at the
exact size of the content placeholder with sensible fallbacks.
report_layouts() lists what a template
offers.
report_deck(ai = TRUE) drafts 3-4
takeaway bullets per slide (and, with ai_titles = TRUE,
headline titles) from the data behind each item, reusing one chat across
the deck; bullets land in a two-content layout when the template has
one, else in the speaker notes. AI failures degrade to plain
slides.
Quarto scaffolds rewritten as four distinct
report skeletons (pptx / html / docx / pdf) with data and
ai parameters, placeholder narrative, executive summary and
a precision appendix; scaffold_report() gains
author and reference_doc (defaulting to the
brand template).
README documents the Google Slides workflow:
build the branded .pptx and import it (File > Import
slides); what survives and what to watch.
slide_bullets, thematic_analysis,
segment_comparison, methodology and
full_report.ai_context() bundles sample size,
question wording, base, fieldwork and precision notes (auto-derived from
the raw survey) into every prompt via the new context
argument of ai_summarise() /
ai_report_sections() / report_deck().register_prompt() gains an output_contract
field pinning the answer’s format; ai_report_sections()
gains chat for connection reuse.outputs/ folder in the working directory
instead of requiring a path: save_plot()
(outputs/plot.png), save_data()
(outputs/data.csv), export_xlsx()
(outputs/tables.xlsx), report_save() /
report_deck() (outputs/report.pptx /
.docx). Missing directories are created; explicit paths
behave as before.annotate_bands() band labels no longer
sit on top of the marker line: label_offset defaults to 4%
of the opposite-axis range and labels are justified into the panel, so
nothing clips at the panel edge. text_size now defaults to
the theme’s base font size (11 pt) instead of a fixed geom size, and
multi-line band labels get a tighter line height.mark_value() labels are justified
inside the panel next to the marker line instead of being half-clipped
at the Inf edge.plot_nps() detractor/passive/promoter
callouts no longer clip at the panel top or overlap each other; the
promoter callout right-aligns to the panel edge.plot_nps_gauge() gains a
label_size argument; band labels default to the theme’s
base font size.sample_comments() gains a
seed argument (matching
sample_comments_diverse()), so quote selections can be
reproduced; the RNG state is restored afterwards.calc_percentage(long = TRUE) no longer triggers the
deprecated tidyselect external-vector warning.plot_bars() now lays itself out.
orientation = "auto" (the default) draws vertical columns
for a few short labels and horizontal bars for many or long ones, wraps
long labels with str_wrap(), steps the data-label size down
as bars multiply, and orders bars so the longest sits at the top (bars)
or on the left (cols). An intentional ordinal scale (an ordered factor
from a registered order) keeps its order. orientation /
sort / wrap / label_size and the
new bar_* options (see ezrsurvey_options())
override the automatics; the old flip argument still
works.drop_items() plus a
drop = argument on
calc_percentage(), calc_percentage_multi(),
calc_percentage_batch() and crosstab() remove
unwanted answers (e.g. "Other", "Don't know")
before counting, so the kept answers re-base to ~100%. Set a session
default with ezrsurvey_options(drop_answers = ...).podracing_survey (renamed from
consumer_survey): a Star Wars pod-racing fan survey with
international-standard demographics (ISO/IEC 5218 sex, ISCED education,
ILO labour-force status, ISIC sectors, ISO 3166 countries) and diverse,
entity-rich open-text comments for the text / NER helpers.shopping_survey: a
turn-of-the-century (Edwardian) shopping-behaviour survey – a second,
very different theme for examples.register_order_presets() now ships an
education_isced order (was education_us).set_weights() defines a
post-stratification / raking scheme from target shares,
e.g. set_weights(c(variable = "demo_gender", Male = 0.49, Female = 0.50, "Non-binary" = 0.01)),
and multiple variables at once. With one variable it is exact
post-stratification; with several it rakes (iterative proportional
fitting) so every margin matches.calc_percentage() (and
calc_percentage_batch()) gain a wpct column
beside n/pct, while
calc_nps(),
calc_summary() and
crosstab() default to weighted values.
Pass weights = FALSE to any of them to opt out, or
weights = <spec> to weight a single call ad hoc.clear_weights(), get_weights(),
has_weights() manage the scheme;
weight_vector() returns the per-respondent weights (and
set_weights() reports the Kish design effect and effective
sample size).First release. A single-line-helper toolkit for everyday consumer-survey analysis, aimed at research and insights professionals.
read_folder(),
select_prefix(), select_suffix(),
parse_filename().na_blank(),
ensure_numeric(), bin_numeric(),
recode_age(), recode_generation(),
recode_likert(), nps_group(),
recode_region() / add_region().calc_percentage(),
calc_percentage_multi(),
calc_percentage_batch(), calc_summary(),
crosstab().calc_nps(),
calc_importance(), ipm_model().compare_values(),
plot_diff().se_mean(),
se_prop(), rse(),
margin_of_error(), diagnose().sample_comments(),
sample_comments_diverse().convert_currency(),
add_currency(), list_currencies().plot_bars(),
plot_stacked_rating(), plot_nps(),
plot_nps_gauge(), plot_ipm(),
plot_quotes_tree(), with the
theme_ezrsurvey*() family, semantic palettes and
annotate_bands().save_plot(),
save_data(), save_output(),
export_xlsx(), the report_*() officer builders
and scaffold_report().ai_chat(),
ai_summarise(), ai_report_sections() with
keyring-backed key management and a prompt-template registry.ezrsurvey_options(),
reusable level orders (register_order()), YAML profiles
(use_ezrsurvey_profile()).podracing_survey,
country_region, currency_rates.