The analysis in surveyframe is driven by the plan stored in the
instrument. Once responses are imported, scored, and checked,
run_analysis_plan() runs every research question in one
pass and returns results formatted for reporting.
The worked-study vignette uses a published study whose data is private. This vignette uses the bundled tourism demo, a synthetic dataset shaped around the same digital marketing and tourism constructs, so the analysis runs end to end without internet access or private data.
Response data uses instrument item IDs as column names. Metadata
columns are declared explicitly. Use strict = TRUE to keep
only known columns.
missing_data_report(responses, instr)
#> $method
#> [1] "missing_data"
#>
#> $item_missing
#> variable missing_n missing_pct valid_n
#> visit_type visit_type 0 0 120
#> dm_1 dm_1 0 0 120
#> dm_2 dm_2 0 0 120
#> dm_3 dm_3 0 0 120
#> sq_1 sq_1 0 0 120
#> sq_2 sq_2 0 0 120
#> sq_3 sq_3 0 0 120
#> sus_1 sus_1 0 0 120
#> sus_2 sus_2 0 0 120
#> sat_1 sat_1 0 0 120
#> sat_2 sat_2 0 0 120
#> bi_1 bi_1 0 0 120
#> bi_2 bi_2 0 0 120
#> attention attention 0 0 120
#> comments comments 0 0 120
#>
#> $respondent_missing
#> row missing_n missing_pct
#> 1 1 0 0
#> 2 2 0 0
#> 3 3 0 0
#> 4 4 0 0
#> 5 5 0 0
#> 6 6 0 0
#> 7 7 0 0
#> 8 8 0 0
#> 9 9 0 0
#> 10 10 0 0
#> 11 11 0 0
#> 12 12 0 0
#> 13 13 0 0
#> 14 14 0 0
#> 15 15 0 0
#> 16 16 0 0
#> 17 17 0 0
#> 18 18 0 0
#> 19 19 0 0
#> 20 20 0 0
#> 21 21 0 0
#> 22 22 0 0
#> 23 23 0 0
#> 24 24 0 0
#> 25 25 0 0
#> 26 26 0 0
#> 27 27 0 0
#> 28 28 0 0
#> 29 29 0 0
#> 30 30 0 0
#> 31 31 0 0
#> 32 32 0 0
#> 33 33 0 0
#> 34 34 0 0
#> 35 35 0 0
#> 36 36 0 0
#> 37 37 0 0
#> 38 38 0 0
#> 39 39 0 0
#> 40 40 0 0
#> 41 41 0 0
#> 42 42 0 0
#> 43 43 0 0
#> 44 44 0 0
#> 45 45 0 0
#> 46 46 0 0
#> 47 47 0 0
#> 48 48 0 0
#> 49 49 0 0
#> 50 50 0 0
#> 51 51 0 0
#> 52 52 0 0
#> 53 53 0 0
#> 54 54 0 0
#> 55 55 0 0
#> 56 56 0 0
#> 57 57 0 0
#> 58 58 0 0
#> 59 59 0 0
#> 60 60 0 0
#> 61 61 0 0
#> 62 62 0 0
#> 63 63 0 0
#> 64 64 0 0
#> 65 65 0 0
#> 66 66 0 0
#> 67 67 0 0
#> 68 68 0 0
#> 69 69 0 0
#> 70 70 0 0
#> 71 71 0 0
#> 72 72 0 0
#> 73 73 0 0
#> 74 74 0 0
#> 75 75 0 0
#> 76 76 0 0
#> 77 77 0 0
#> 78 78 0 0
#> 79 79 0 0
#> 80 80 0 0
#> 81 81 0 0
#> 82 82 0 0
#> 83 83 0 0
#> 84 84 0 0
#> 85 85 0 0
#> 86 86 0 0
#> 87 87 0 0
#> 88 88 0 0
#> 89 89 0 0
#> 90 90 0 0
#> 91 91 0 0
#> 92 92 0 0
#> 93 93 0 0
#> 94 94 0 0
#> 95 95 0 0
#> 96 96 0 0
#> 97 97 0 0
#> 98 98 0 0
#> 99 99 0 0
#> 100 100 0 0
#> 101 101 0 0
#> 102 102 0 0
#> 103 103 0 0
#> 104 104 0 0
#> 105 105 0 0
#> 106 106 0 0
#> 107 107 0 0
#> 108 108 0 0
#> 109 109 0 0
#> 110 110 0 0
#> 111 111 0 0
#> 112 112 0 0
#> 113 113 0 0
#> 114 114 0 0
#> 115 115 0 0
#> 116 116 0 0
#> 117 117 0 0
#> 118 118 0 0
#> 119 119 0 0
#> 120 120 0 0
#>
#> $patterns
#> pattern n percent
#> 1 000000000000000 120 1
#>
#> $deletion
#> $deletion$listwise_n
#> [1] 120
#>
#> $deletion$pairwise_n
#> $deletion$pairwise_n$visit_type
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$dm_1
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$dm_2
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$dm_3
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sq_1
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sq_2
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sq_3
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sus_1
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sus_2
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sat_1
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$sat_2
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$bi_1
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$bi_2
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$attention
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#> $deletion$pairwise_n$comments
#> visit_type dm_1 dm_2 dm_3 sq_1 sq_2 sq_3
#> 120 120 120 120 120 120 120
#> sus_1 sus_2 sat_1 sat_2 bi_1 bi_2 attention
#> 120 120 120 120 120 120 120
#> comments
#> 120
#>
#>
#>
#> $scale_missing_rules
#> scale_id n_items min_valid
#> 1 digital_marketing 3 3
#> 2 service_quality 3 3
#> 3 sustainability 2 2
#> 4 satisfaction 2 2
#> 5 behavioural_intention 2 2
#> missing_rule
#> 1 Score when at least 3 item(s) are valid.
#> 2 Score when at least 3 item(s) are valid.
#> 3 Score when at least 2 item(s) are valid.
#> 4 Score when at least 2 item(s) are valid.
#> 5 Score when at least 2 item(s) are valid.
#>
#> $mcar
#> $mcar$available
#> [1] FALSE
#>
#> $mcar$warning
#> [1] "Little's MCAR test requires an optional package and was not run."
#>
#>
#> $apa
#> [1] "Missing-data diagnostics were computed for 15 variable(s)."
#>
#> $prompt
#> [1] "Report item and respondent missingness, the missing-data pattern, and the deletion rule used for each analysis."
#>
#> attr(,"class")
#> [1] "sframe_missing_data_report"
quality_report(
responses, instr,
respondent_id = "respondent_id",
submitted_at = "submitted_at",
started_at = "started_at"
)
#> Survey Data Quality Report
#> Respondents: 120
#> Items: 15
#> Flagged: 109 (90.8%)
#>
#> Attention checks:
#> attention_agree pass 95% fail 6
#>
#> Timing:
#> Median completion time: 966.0 seconds
#>
#> Missingness: 0.0% of respondents exceed 20% thresholdrun_analysis_plan() scores the scales for you, but
scoring once up front lets you inspect the construct scores and run the
assumption checks below.
scored <- score_scales(responses, instr, keep_items = TRUE, keep_meta = TRUE)
scale_ids <- vapply(instr$scales, function(x) x$id, character(1))
head(scored[, intersect(scale_ids, names(scored)), drop = FALSE])
#> digital_marketing service_quality sustainability satisfaction
#> 1 2.666667 3.666667 5.0 3.5
#> 2 3.000000 2.666667 3.0 1.5
#> 3 4.666667 3.333333 3.5 4.5
#> 4 4.333333 4.000000 5.0 4.5
#> 5 3.000000 3.666667 4.0 3.0
#> 6 3.666667 3.666667 2.5 3.5
#> behavioural_intention
#> 1 4.5
#> 2 2.5
#> 3 2.5
#> 4 5.0
#> 5 3.5
#> 6 3.0assumption_report() reports the checks a technique
relies on, such as residual normality, variance inflation, and influence
for a regression.
assumption_report(
scored,
predictors = c("digital_marketing", "service_quality", "sustainability"),
outcome = "satisfaction"
)
#> $method
#> [1] "assumptions"
#>
#> $normality
#> data frame with 0 columns and 0 rows
#>
#> $homogeneity
#> data frame with 0 columns and 0 rows
#>
#> $regression
#> $regression$n
#> [1] 120
#>
#> $regression$residual_shapiro_w
#> [1] 0.9941063
#>
#> $regression$residual_shapiro_p
#> [1] 0.8980753
#>
#> $regression$vif
#> digital_marketing service_quality sustainability
#> 1.212656 1.200070 1.012163
#>
#> $regression$cooks_distance
#> 1 2 3 4 5 6
#> 1.184326e-04 9.147336e-03 1.482864e-03 3.583748e-07 2.883541e-03 1.731349e-04
#> 7 8 9 10 11 12
#> 1.323697e-02 4.460344e-03 4.542716e-05 4.287879e-02 2.143130e-02 1.509419e-03
#> 13 14 15 16 17 18
#> 5.088239e-02 5.722577e-03 2.174172e-07 1.127457e-02 8.743696e-03 2.593670e-03
#> 19 20 21 22 23 24
#> 7.553824e-03 2.109049e-02 1.932134e-05 2.370723e-03 3.851322e-04 5.461064e-03
#> 25 26 27 28 29 30
#> 1.872377e-04 4.489098e-07 1.706497e-02 2.752537e-06 1.434770e-04 3.195816e-03
#> 31 32 33 34 35 36
#> 6.905977e-02 1.536396e-02 1.260801e-02 1.534755e-03 1.380360e-02 6.848461e-03
#> 37 38 39 40 41 42
#> 1.700720e-06 3.793174e-04 2.134337e-03 2.287672e-02 1.001287e-02 4.071700e-03
#> 43 44 45 46 47 48
#> 5.471299e-03 5.270891e-02 3.433051e-02 2.975180e-03 3.167244e-03 9.174703e-04
#> 49 50 51 52 53 54
#> 1.170983e-02 8.648779e-04 1.116591e-03 8.230930e-03 1.381027e-02 3.504105e-02
#> 55 56 57 58 59 60
#> 1.571502e-04 2.905749e-03 1.402942e-03 5.808575e-03 2.019476e-03 6.948885e-06
#> 61 62 63 64 65 66
#> 1.170618e-03 3.652109e-03 2.922443e-02 9.678057e-03 3.620026e-06 3.218468e-03
#> 67 68 69 70 71 72
#> 1.378174e-03 5.716292e-03 3.730149e-03 9.087202e-03 8.357802e-03 1.187750e-02
#> 73 74 75 76 77 78
#> 2.430428e-02 3.348263e-04 9.538221e-03 1.257656e-03 1.433252e-03 1.356868e-03
#> 79 80 81 82 83 84
#> 2.563597e-05 1.801658e-03 1.835160e-03 5.784606e-04 2.366539e-02 8.884675e-04
#> 85 86 87 88 89 90
#> 3.063566e-04 9.322376e-03 1.300065e-02 5.103375e-03 6.710071e-04 3.902158e-03
#> 91 92 93 94 95 96
#> 3.851322e-04 3.045158e-03 4.482863e-04 3.504325e-03 3.537797e-03 4.644052e-04
#> 97 98 99 100 101 102
#> 1.386934e-02 4.444185e-03 5.864202e-03 9.236185e-03 2.563387e-02 3.445601e-04
#> 103 104 105 106 107 108
#> 1.467024e-03 1.170618e-03 9.051071e-04 7.373574e-03 2.295924e-05 6.910949e-04
#> 109 110 111 112 113 114
#> 3.504325e-03 2.274586e-04 9.266580e-05 4.857092e-03 4.700977e-08 2.921484e-03
#> 115 116 117 118 119 120
#> 4.090240e-03 1.105467e-02 7.365409e-04 1.938023e-02 1.012910e-03 1.535916e-02
#>
#> $regression$standardised_residuals
#> 1 2 3 4 5 6
#> -0.082923698 -1.870645918 0.395846500 0.004591293 -0.692174489 -0.185004873
#> 7 8 9 10 11 12
#> 1.084968504 0.780147050 0.110776991 -2.638742712 -1.795997774 0.319306483
#> 13 14 15 16 17 18
#> 1.954971640 -1.219815183 0.004191993 1.118225981 1.039309006 0.527129425
#> 19 20 21 22 23 24
#> -0.961835047 0.980099373 0.063225377 0.551354644 0.278271787 -0.647978136
#> 25 26 27 28 29 30
#> 0.227581315 0.004986299 -1.172216599 0.021868776 -0.095706217 -0.782623908
#> 31 32 33 34 35 36
#> -2.309384417 -1.374470793 0.932880267 -0.690640105 1.255066667 0.671314169
#> 37 38 39 40 41 42
#> 0.012570683 0.352662125 0.374079633 1.867781077 -1.228052989 0.606343018
#> 43 44 45 46 47 48
#> -0.617848955 -1.662835019 2.074446939 0.978590982 -0.793286443 0.252351509
#> 49 50 51 52 53 54
#> 1.156356561 -0.449473176 -0.363323806 1.152172372 -1.440809735 -1.866773520
#> 55 56 57 58 59 60
#> 0.189559954 -0.858506945 -0.309992596 -1.198889104 0.696726010 -0.035497078
#> 61 62 63 64 65 66
#> -0.594649744 0.646085118 1.892162918 1.346958028 0.012140769 -1.050312804
#> 67 68 69 70 71 72
#> 0.598618566 -1.508218399 -0.521321175 -0.874142231 1.497519709 1.032511438
#> 73 74 75 76 77 78
#> 2.208163710 0.178475846 1.021361391 0.616360158 -0.448239907 -0.298894184
#> 79 80 81 82 83 84
#> -0.041513884 0.484623799 -0.711839662 -0.445277725 2.271897566 0.424028147
#> 85 86 87 88 89 90
#> 0.236369610 1.923468863 -1.537113657 -0.910885755 0.287247717 0.885761213
#> 91 92 93 94 95 96
#> 0.278271787 -1.099326747 -0.299846917 -0.670336465 1.075297214 0.241274096
#> 97 98 99 100 101 102
#> 1.521915286 0.863717913 0.560137775 -0.839407809 -1.485896784 -0.173199125
#> 103 104 105 106 107 108
#> -0.230361700 -0.594649744 0.499913855 -1.172602644 -0.046456880 -0.397268813
#> 109 110 111 112 113 114
#> -0.670336465 0.181786019 -0.202323795 -0.825310891 0.001891811 -0.577856052
#> 115 116 117 118 119 120
#> -0.520419080 1.827370061 -0.348396466 -1.215115771 0.250475472 0.752951062
#>
#>
#> $expected_counts
#> NULL
#>
#> $apa
#> [1] "Assumption checks were computed."
#>
#> $prompt
#> [1] "Report assumption checks before interpreting inferential models, especially sparse cells, non-normal residuals, and high VIF values."
#>
#> attr(,"class")
#> [1] "sframe_assumption_report"Each block binds a research question to a technique and to the
variables that fill each role. A correlation expects x and
y. A regression expects predictors and a
dependent variable. A group comparison expects a
group and an outcome.
instr$analysis_plan <- list(
list(id = "RQ1",
research_question = "Is digital marketing perception associated with satisfaction?",
family = "association", method = "correlation_pearson",
roles = list(x = "digital_marketing", y = "satisfaction"),
options = list(alpha = 0.05)),
list(id = "RQ2",
research_question = "Do the three perception scales predict satisfaction?",
family = "regression", method = "regression_linear",
roles = list(predictors = c("digital_marketing", "service_quality", "sustainability"),
dependent = "satisfaction"),
options = list(alpha = 0.05)),
list(id = "RQ3",
research_question = "Do first-time and repeat visitors differ in behavioural intention?",
family = "group_comparison", method = "mann_whitney",
roles = list(group = "visit_type", outcome = "behavioural_intention"),
options = list(alpha = 0.05))
)results <- run_analysis_plan(responses, instr)
results
#> Analysis Results: 3 research question(s)
#>
#> RQ 1: Is digital marketing perception associated with satisfaction?
#> Test: correlation_pearson
#> APA: r(118) = 0.54, p < .001
#>
#> RQ 2: Do the three perception scales predict satisfaction?
#> Test: regression_linear
#> APA: R² = 0.383, F(3, 116) = 23.95, p < .001
#>
#> RQ 3: Do first-time and repeat visitors differ in behavioural intention?
#> Test: mann_whitney
#> APA: U = 1576, z = -0.98, p = 0.327, r = 0.09Each result holds more than the printed line. It carries the APA statistic, the effect-size label where the technique reports one, a writing prompt, and the references that support the technique.
rq1 <- results[[1]]
rq1$apa
#> [1] "r(118) = 0.54, p < .001"
rq1$effect_label
#> [1] "large"
rq1$prompt
#> [1] "There was a positive, large significant correlation between digital_marketing and satisfaction, r(118) = 0.54, p < .001. Explain what this means for your research question."
unlist(rq1$citations)
#> field_2018
#> "Field, A. (2018). *Discovering statistics using IBM SPSS statistics* (5th ed.). SAGE."
#> cohen_1988
#> "Cohen, J. (1988). *Statistical power analysis for the behavioral sciences* (2nd ed.). Lawrence Erlbaum."
#> r_core
#> "R Core Team. (2026). *R: A language and environment for statistical computing*. R Foundation for Statistical Computing."
#> surveyframe
#> "Sharafuddin, M. A. (2026). *surveyframe: A survey instrument workflow for R* (Version 0.3.0) [Computer software]. https://github.com/MohammedAliSharafuddin/surveyframe"render_results() writes a self-contained HTML report
with one section per research question, each holding the APA result, the
writing prompt, a space for the interpretation, and a reference list
compiled from the techniques used.
SurveyStudio runs the same plan. Open it on the analysis screen, upload the responses, and the Analysis Plan screen runs the saved plan and shows a table of each question with its method and APA result. The full report is produced on the Export screen.