
surveyframe is a research-design-first survey package
for R. Most survey tools collect answers and return counts.
surveyframe begins at the research design and carries it
through to a written results report.
The unit of work is the instrument, a typed sframe
object that stores three things together:
Because the plan and the model live inside the instrument, the link between a question, the variable it produces, and the test that variable feeds is fixed at design time. When responses come back, the plan runs in one pass and returns results already formatted for reporting, with effect sizes, a writing prompt for each finding, and the reference that supports each test.
The package works offline during examples, tests, vignettes, and
checks. Browser and Shiny entry points use open = FALSE or
explicit launch functions, so automated checks do not open a
browser.
Install from CRAN:
install.packages("surveyframe")To get unreleased changes from the development version:
remotes::install_github("MohammedAliSharafuddin/surveyframe")Optional packages are only needed for selected features:
install.packages(c("shiny", "psych", "googlesheets4", "digest", "MASS", "nnet"))Syntax generation works without installing lavaan or
seminr. Install those packages when you want to fit the
generated CFA, CB-SEM, or PLS-SEM models.
If you have collected responses in a CSV or Google Sheet and want to start from the analysis step, build a minimal instrument that matches your column names and load the data directly:
library(surveyframe)
# 1. Describe the items you already collected
cs <- sf_choices("agree5", 1:5,
c("Strongly disagree", "Disagree", "Neutral", "Agree", "Strongly agree"))
i1 <- sf_item("q1", "Item 1", type = "likert", choice_set = "agree5", scale_id = "S")
i2 <- sf_item("q2", "Item 2", type = "likert", choice_set = "agree5", scale_id = "S")
sc <- sf_scale("S", "My scale", items = c("q1", "q2"))
instr <- sf_instrument("My study", components = list(cs, i1, i2, sc))
# 2. Load your CSV
responses <- read_responses("my_data.csv", instr, strict = FALSE)
# 3. Score and analyse
scored <- score_scales(responses, instr)
results <- run_analysis_plan(scored, instr)Start with:
Read all six vignettes inside R with:
browseVignettes("surveyframe")library(surveyframe)
agree5 <- sf_choices(
"agree5",
values = 1:5,
labels = c("Strongly disagree", "Disagree", "Neutral", "Agree", "Strongly agree")
)
visitor_type_choices <- sf_choices(
"visitor_type",
values = c("first_time", "repeat"),
labels = c("First-time visitor", "Repeat visitor")
)
sat_1 <- sf_item("sat_1", "The service was reliable.",
type = "likert", choice_set = "agree5", scale_id = "sat")
sat_2 <- sf_item("sat_2", "The service was responsive.",
type = "likert", choice_set = "agree5", scale_id = "sat")
sat_3 <- sf_item("sat_3", "I would recommend the service.",
type = "likert", choice_set = "agree5", scale_id = "sat")
visitor_type <- sf_item("visitor_type", "Visitor type", type = "single_choice",
choice_set = "visitor_type")
sat <- sf_scale("sat", "Satisfaction", items = c("sat_1", "sat_2", "sat_3"))
instr <- sf_instrument(
"Service Survey",
components = list(
agree5, visitor_type_choices, sat_1, sat_2, sat_3, visitor_type, sat
),
analysis_plan = list(
list(
id = "RQ1",
research_question = "Do first-time and repeat visitors differ in satisfaction?",
family = "group_comparison",
method = "mann_whitney",
roles = list(group = "visitor_type", outcome = "sat"),
options = list(alpha = 0.05)
)
)
)
instr <- validate_sframe(instr)
write_sframe(instr, tempfile(fileext = ".sframe"))write_sframe() validates the instrument and writes the
validated object, including the validation flag, the analysis plan, and
any saved model specifications.
responses <- data.frame(
respondent_id = paste0("R", 1:5),
sat_1 = c(4, 5, 3, 4, NA),
sat_2 = c(5, 4, 3, 4, 5),
sat_3 = c(4, 5, 2, 4, 4),
visitor_type = c("first_time", "repeat", "first_time", "repeat", "first_time")
)
resp <- read_responses(responses, instr, respondent_id = "respondent_id", strict = FALSE)
score_scales(resp, instr)
missing_data_report(resp, instr)Each block binds a research question to a technique and to the
variables that fill each role. run_analysis_plan() runs
every block and returns one result per question. Earlier
.sframe files using variables and
test fields remain compatible.
results <- run_analysis_plan(resp, instr)
resultsSupported method IDs include descriptives, missing data, quality checks, reliability, EFA readiness and solutions, CFA, CB-SEM, and PLS-SEM syntax, chi-square, Fisher’s exact test, McNemar, Cochran’s Q, t-tests, Mann-Whitney, Wilcoxon, one- and two-way ANOVA, ANCOVA, repeated-measures ANOVA, Kruskal-Wallis, Friedman, Pearson, Spearman, and Kendall correlations, partial correlations, linear and logistic regression, mediation, and moderation. Each technique reports an APA statistic, an effect size where it applies, a writing prompt, and the reference that supports it.
render_results(results, instr, output_file = tempfile(fileext = ".html"))The report holds one section per research question, with the APA result, the writing prompt, a space for the interpretation, and a reference list compiled from the techniques used.
if (requireNamespace("psych", quietly = TRUE)) {
reliability_report(resp, instr, omega = FALSE)
efa_report(resp, instr)
}
cfa_syntax(instr)
cfa_lavaan_syntax(instr, ordered = TRUE)model <- sf_model(
"model_1",
"Satisfaction model",
type = "cb_sem",
constructs = list(
sf_construct("SAT", "Satisfaction", c("sat_1", "sat_2", "sat_3"))
)
)
instr <- add_model(instr, model)
model_json(model)
sem_lavaan_syntax(model, instr)pls_model <- sf_model(
"pls_1",
"Satisfaction and loyalty PLS model",
type = "pls_sem",
constructs = list(
sf_construct("SAT", "Satisfaction", c("sat_1", "sat_2"), mode = "composite"),
sf_construct("LOY", "Loyalty", "sat_3", mode = "single_item")
),
paths = list(sf_path("SAT", "LOY")),
options = list(bootstrap = 5000)
)
seminr_syntax(pls_model)render_report(
instr,
data = resp,
output_file = tempfile(fileext = ".html"),
include_codebook = TRUE,
include_quality = TRUE,
include_missing = TRUE,
include_descriptives = TRUE,
include_analysis = TRUE,
include_models = TRUE
)The built-in HTML fallback does not require Quarto. If the Quarto CLI
is available locally, render_report() can use the bundled
template.
launch_builder(open = FALSE)
export_static_survey(instr, open = FALSE)Use launch_builder() to author the questionnaire, the
plan, and the model and to export the .sframe file and
model syntax; it runs no statistics. launch_studio()
uploads responses, runs the plan on its Analysis Plan screen, and
renders the report on its Export screen. launch_dashboard()
is a read-only response explorer. Demo launchers are available for
training:
launch_builder_demo(open = FALSE)
# launch_studio_demo()
# launch_dashboard_demo()Interactive functions such as
launch_builder(open = TRUE), launch_studio(),
render_survey(), and launch_dashboard() are
available for manual use. Tests and examples avoid opening browsers.
MCDM and DEMATEL fall outside v0.3 scope. These methods are scheduled for v0.4.
citation("surveyframe")MIT. See LICENSE.