-
Notifications
You must be signed in to change notification settings - Fork 0
Cookbook
Short recipes for common tasks. Within a section, later snippets may reuse variables defined just above; each recipe assumes:
import siamang as sgFor the underlying concepts, follow the cross-links; for a full narrative walkthrough see Tutorial Full Pipeline.
See Visibility and Branching for the full Expression DSL.
age = sg.Variable("age", scale="ratio")
income = sg.Variable("income", scale="ratio")
q_income = sg.NumericInput("Household income?", var=income, show_if=age.ge(18))Option accepts its own show_if / hide_if:
gender = sg.Variable("gender", scale="nominal", labels={1: "Male", 2: "Female"})
fav = sg.Variable("fav_color", scale="nominal",
labels={1: "Red", 2: "Blue", 3: "Pink", 4: "Green"})
q_color = sg.SingleChoice(
"Pick a colour", var=fav,
choices=[
sg.Option(1, "Red"),
sg.Option(2, "Blue"),
sg.Option(3, "Pink", hide_if=gender.eq(1)), # hide for men
sg.Option(4, "Green", show_if=sg.AND(age.ge(18), gender.eq(2))),
],
)region = sg.Variable("region", scale="nominal", labels={1: "Capital", 2: "North"})
party = sg.Variable("party", scale="nominal")
gate = sg.AND(
age.ge(18),
sg.OR(region.eq(1), region.eq(2)),
sg.NOT(party.eq(99)),
)
sg.Page(name="political", items=[...], show_if=gate)The same gate works on a Page, Block, Question, or Option. When both
show_if and hide_if are set, the element renders iff show_if is true and
hide_if is false.
See Quotas. A Quota caps responses for a particular variable value; pass a list
to deploy(...) as the quota option. When a submission matches a filled cell the
backend returns {"status": "quota_full"} and the frontend shows the closed screen.
from siamang import Quota
quotas = [
Quota("gender", target_value=1, limit=200),
Quota("gender", target_value=2, limit=200),
Quota("region", target_value=1, limit=400), # cap on the Capital region
]
survey.deploy(backend="supabase", frontend="vercel", quota=quotas)Updating a limit is just a code change followed by another deploy — but note that
each deploy provisions a new survey instance with fresh quota counters.
Media attaches an image, audio, or video to a question or an option. See
Question Types.
sg.SingleChoice(
"Which logo do you prefer?", var=logo,
media=sg.Media("https://cdn.example.com/intro.png", caption="Compare side by side"),
)sg.OpenText(
"What do you see in these images?", var=description, multiline=True,
media=[
sg.Media("https://cdn.example.com/a.jpg", alt="Image A"),
sg.Media("https://cdn.example.com/b.jpg", alt="Image B"),
],
)sg.SingleChoice(
"Which jingle do you like better?",
var=sg.Variable("jingle", scale="nominal", labels={1: "First", 2: "Second"}),
choices=[
sg.Option(1, "First", media=sg.Media("https://cdn.example.com/j1.mp3")),
sg.Option(2, "Second", media=sg.Media("https://cdn.example.com/j2.mp3")),
],
)sg.NumericInput(
"How long is the clip in seconds?", var=duration,
media=sg.Media("https://cdn.example.com/intro.mp4",
autoplay=True, loop=False, controls=True),
)By default a Page shows all its items together. To render one question at a time
(a common mobile pattern), set the one_question_per_page deploy option — it maps to
SurveyJS's questionsOnPageMode: "questionPerPage". See
Frontend and Theming.
survey.deploy(
backend="supabase", frontend="vercel",
one_question_per_page=True,
)The same option is accepted by survey.compile(one_question_per_page=True) if you
build the bundle manually. Other compile-level options forwarded the same way include
language, show_progress, and allow_back.
See Scripts. A Script binds inline JavaScript to one of seven triggers
(onInit, onPageEnter, onPageExit, onQuestionShow, onAnswer, onSubmit,
onRandomize). Factory helpers cover the common cases:
shuffle = sg.Script.randomize_options("q_party")
timer = sg.Script.timed_question("q_party", seconds=30)
match = sg.Script.validate_fields_match("email_1", "email_2",
message="The two email addresses don't match.")
survey = sg.Questionnaire(title="…", pages=[...], scripts=[shuffle, timer, match])A custom snippet sees answers, utils (shuffle, sample, clamp, now, formatDate,
debounce), api (get, post), and context — the static dict you set on the
Script itself (the runtime injects nothing else into it):
log_exit = sg.Script(
name="log_exit",
trigger="onPageExit",
context={"survey_id": "trust-2026", "endpoint": "/diagnostics"},
code="""
api.post(context.endpoint, {
survey_id: context.survey_id,
left_at: utils.now(),
});
""",
)
survey = sg.Questionnaire(title="…", pages=[...], scripts=[log_exit])See Analysis. with_weight(col) returns a view whose analysis accessor
honours the weight (pass weighted=True per call); the declarative data.report.*
tables are unweighted. simulate() does not generate a weight column, so attach
one to the frame first:
import numpy as np
data = survey.simulate(n=1000, seed=42)
frame = data.frame.assign(
weight=np.random.default_rng(0).uniform(0.5, 1.5, len(data.frame))
)
data = data.with_frame(frame).with_weight("weight")
# Weighted statistics (analysis accessor)
data.analysis.mean("trust", weighted=True)
data.analysis.frequencies("trust", labels=True, weighted=True, normalize=True)
data.analysis.grouped_mean("trust", by="gender", weighted=True)
data.analysis.proportion_ci("trust", value=5, confidence=0.95, weighted=True)
data.analysis.effective_sample_size() # ESS ≤ N
# Declarative tables remain unweighted
print(data.report.freq("trust").to_markdown())data.scale_alpha(["trust_govt", "trust_courts", "trust_press"]) # Cronbach's α
data = data.create_index(
"trust_index",
items=["trust_govt", "trust_courts", "trust_press"],
method="mean", label="General trust",
)banner = data.tables.banner(rows=["trust", "trust_local"],
columns=["gender", "region"], labels=True)
banner.export_xlsx("results.xlsx")See Banner Tables.
See Data Import and Export. SurveyData.export(fmt, path)
is the high-level helper; the siamang.io writers give finer control. SPSS and Stata
round-trip variable labels, value labels, and missing-value codes (Stata accepts
only single-letter .a–.z missing codes; numeric codes are dropped on write).
# High-level
data.export("spss", path="out.sav")
data.export("stata", path="out.dta")
data.export("r", path="out_R/")
data.export_dictionary("dict.json")import pandas as pd
from siamang.io import read_spss, SPSSWriter
data = read_spss("input.sav") # full metadata recovered
# Treat -1 as missing (recode_values would write to a new column instead):
data = data.with_frame(data.frame.replace({"age": {-1: pd.NA}})).apply_missing_values()
SPSSWriter().write(data, "output.sav") # opens in SPSS untouchedfrom siamang.io import RScriptWriter
RScriptWriter().write(data, path="political_trust_R/")
# Writes import_survey.csv, import_survey_dictionary.json, import_survey.R. Then in R:
# source("political_trust_R/import_survey.R") # builds the `survey_data` data frameCSV carries no metadata, so pair it with a JSON codebook:
from siamang.io import CSVWriter, DictionaryWriter, CSVReader, DictionaryReader
CSVWriter().write(data, "responses.csv")
DictionaryWriter().write(data.variables, "dict.json")
# later …
restored = CSVReader().read("responses.csv")
restored = restored.__class__(frame=restored.frame,
variables=DictionaryReader().read("dict.json"))The deploy registry is driven by entry points, so a plugin only declares the entry point and implements the abstract base. See Deployment for the adapter contracts.
# pyproject.toml of `my-siamang-plugin`
[project.entry-points."siamang.backends"]
mybackend = "my_pkg.backend:MyBackend"
[project.entry-points."siamang.frontends"]
mycdn = "my_pkg.frontend:MyCDNFrontend"import siamang as sg
sg.Questionnaire(...).deploy(backend="mybackend", frontend="mycdn")See also: Tutorial Full Pipeline · Visibility and Branching · Quotas · Scripts · Analysis · Data Import and Export · Deployment · API Reference Index
siamang · siamang_cloud · Free for noncommercial use · Commercial licensing · Wiki source: wiki/
Getting started
Survey design
- Variables and Measurement
- Question Types
- Pages Blocks and Structure
- Visibility and Branching
- Quotas
- Scripts
Validate & simulate
Data & analysis
Reporting
Frontend & deploy
Tooling
More
Get started
Account & team
Build & deploy
Data & analysis
Author & configure
Reference