--- title: "Getting started with ezrsurvey" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with ezrsurvey} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4 ) ``` `ezrsurvey` turns the things consumer-survey analysts do over and over into single-line helpers. This vignette walks through a typical analysis of the bundled `podracing_survey` dataset: from raw answers to percentages, models, diagnostics and a chart you could drop on a slide. ```{r setup} library(ezrsurvey) ``` ## The data `podracing_survey` is 1,000 simulated respondents with demographics, a 0--10 NPS question, worded feature ratings, multi-select motivations, brand questions and open-text comments. ```{r} podracing_survey[, c("respondent_id", "demo_gender", "demo_age", "nps_value")] ``` ## Percentages without the `count`/`mutate`/`pivot_wider` dance `calc_percentage()` is the workhorse: counts, percentages and ordering in one call. ```{r} calc_percentage(podracing_survey, demo_gender, sort = "desc") ``` Group with `by`, and pivot to a wide cross-tab with `wide = TRUE`: ```{r} calc_percentage(podracing_survey, satis_return, by = region, wide = TRUE) ``` Check-all-that-apply questions live in a block of columns sharing a prefix; `calc_percentage_multi()` handles the per-respondent denominator for you: ```{r} calc_percentage_multi(podracing_survey, "motivations_", id = respondent_id, sort = "desc") ``` Spreadsheet exports, Google Forms among them, instead pack every answer a respondent ticked into a single cell. The same function recognises that shape and separates the answers, so you do not have to reshape anything first: ```{r} packed <- data.frame( respondent = 1:4, motivations = c("Speed; Drivers", "Speed", "", "Betting; Speed") ) calc_percentage_multi(packed, "motivations", id = respondent, sort = "desc") ``` Note the denominator: three respondents ticked something, so "Speed" is 3 of 3. When you need those answers as columns rather than as a table, for a crosstab or a filter, `split_multi()` widens them: ```{r} split_multi(packed, motivations) ``` ## Reusable level orders Rather than retyping `levels = c(...)`, register an order once and link it to a variable; `calc_percentage()` then applies it automatically. ```{r} 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) ``` ## Net Promoter Score ```{r} calc_nps(podracing_survey, nps_value) ``` ```{r} plot_nps(podracing_survey, nps_value) ``` ## Importance / performance `ipm_model()` combines driver importance (by default, relative weights against the NPS score) with feature performance; `plot_ipm()` draws the matrix. Pass `method = "forest"` for a random-forest cross-check, which sees non-linear effects that relative weights cannot. ```{r} model <- ipm_model(podracing_survey, nps_value, "ratings_") model ``` ## Comparing two events For event surveys you often compare this wave with the last. `compare_values()` computes the differences and `plot_diff()` draws the change chart. ```{r} previous <- transform(model, performance = performance - c(.3, -.1, .2, 0, .1)) compare_values(model, previous) %>% plot_diff() ``` ## How precise is it? `diagnose()` reports the standard error, relative standard error and margin of error for any column -- numeric (point) or categorical (proportion). ```{r} diagnose(podracing_survey, demo_gender, nps_value) ``` For a one-shot, plain-language read on the whole study, `precision_summary()` picks the point-scale and proportion variables for you and writes the bullet points you would otherwise hand-craft for a report appendix: ```{r} precision_summary(podracing_survey) ``` ### Why relative standard error? A standard error on its own is hard to judge -- is `±0.05` good? It depends on the scale. The **relative standard error** (RSE) divides the standard error by the estimate, so precision becomes comparable across a 1--5 rating and a percentage alike. Rating estimates by their RSE is the approach national statistical agencies use to decide whether a number is solid enough to publish. The [Australian Bureau of Statistics](https://www.abs.gov.au/statistics/microdata-tablebuilder/tablebuilder/confidentiality-and-relative-standard-error), for example, treats an RSE of 25% or more as not reliable for most purposes, marks estimates between 25% and 50% with an asterisk as ones to use with caution, and suppresses anything above 50%. ezrsurvey keeps that 25% boundary and adds tighter bands below it, because in consumer-survey work the question is usually which of several adequately precise numbers to lead with: | RSE | Rating | |---|---| | under 5% | high precision | | under 10% | precise | | under 15% | satisfactory | | under 25% | use with caution | | 25% or more | likely reliability issues | For proportions, the margin of error is widest at a 50/50 split (`sqrt(0.5 * 0.5 / n)`), so a single worst-case `±` percentage-point figure at your achieved sample size bounds every percentage in the study -- which is why `precision_summary()` reports it. ## Saving and exporting Every table and plot has a one-line, pipe-friendly save that writes the file you name. A path with a folder in it (`"tables/gender.xlsx"`) creates the folder; `ezrsurvey_options(output_dir = "outputs")` collects bare names in one folder. ```{r, eval = FALSE} calc_percentage(podracing_survey, demo_gender) %>% save_data("gender.xlsx") plot_nps(podracing_survey, nps_value) %>% save_plot("nps.png") # several tables, one tab each export_xlsx( gender = calc_percentage(podracing_survey, demo_gender), job = calc_percentage(podracing_survey, demo_job), path = "summary.xlsx" ) ``` ## Where to next * Set persistent defaults with `ezrsurvey_options()` and a profile (`use_ezrsurvey_profile()`). * Build a deck with `report_deck()` or scaffold a Quarto report with `scaffold_report()`. * Draft the narrative around the tables with the companion `ezrintelligence` package. ```{r, include = FALSE} remove_order("education") ```