Schema and parameters from Shin and Park (2024) — multiple-baseline
across three participants, fraction multiplication word problems via a
tablet math application, two question types per session, counts correct
(0-5). See web_based_data.csv at OSF F9832.
Data
library(scdbayes)
make_case <- function(case_id, n_a, baseline_acc, gain) {
n_b <- 24 - n_a
qt <- rep(c("visualization", "solving"), each = 24)
ses <- rep(seq_len(24), times = 2)
ph <- rep(c(rep("A", n_a), rep("B", n_b)), times = 2)
outcome <- pmax(0L, pmin(5L, round(
baseline_acc + gain * as.integer(ph == "B") + rnorm(length(ph), 0, 0.6)
)))
data.frame(case = case_id, time = ses, question_type = qt,
phase = ph, outcome = outcome)
}
fractions <- rbind(
make_case("C1", 6, 1.4, 2.8),
make_case("C2", 9, 1.0, 3.0),
make_case("C3", 12, 1.6, 2.4)
)
head(fractions, 4)
#> case time question_type phase outcome
#> 1 C1 1 visualization A 2
#> 2 C1 2 visualization A 1
#> 3 C1 3 visualization A 1
#> 4 C1 4 visualization A 1Columns
scdbayes uses your columns by name — there is no detection step to
run. This dataset has case (participant),
phase ("A" baseline, "B"
treatment), time (session), outcome, and
question_type (a within-case nesting variable). Pass these
names directly to the functions below.
Design type and hierarchy
detect_design_type(fractions)
#> [1] "multiple_baseline"
detect_hierarchy_levels(fractions)[c("structure", "n_level1", "n_level2")]
#> $structure
#> [1] "two_level"
#>
#> $n_level1
#> [1] 144
#>
#> $n_level2
#> [1] 3Phase (piecewise) coding
fractions_p <- process_scd_phases(fractions, structure = list(),
scd_type = "multiple_baseline")
head(fractions_p[, c("case", "time", "phase", "level_AB",
"time_A", "trend_AB", "outcome")], 4)
#> # A tibble: 4 × 7
#> case time phase level_AB time_A trend_AB outcome
#> <chr> <int> <chr> <int> <dbl> <dbl> <dbl>
#> 1 C1 1 A 0 0 0 2
#> 2 C1 1 A 0 0 0 1
#> 3 C2 1 A 0 0 0 1
#> 4 C2 1 A 0 0 0 2Per-case descriptive features
compute_case_features(fractions)[, c("case", "mean_A", "mean_B",
"NAP", "PND",
"autocor_A", "autocor_B")]
#> case mean_A mean_B NAP PND autocor_A autocor_B
#> times C1 1.4166667 4.194444 0.9965278 0.9166667 0.2279116 -0.1201936
#> times1 C2 0.7777778 3.933333 1.0000000 1.0000000 -0.5225694 -0.2565826
#> times2 C3 1.7500000 3.875000 0.9817708 0.7083333 0.3273810 0.1750000Phase descriptives
summarize_phase_descriptives(fractions_p, phase_var = "phase",
outcome_var = "outcome")[c("raw_difference",
"phase_a_mean",
"phase_b_mean")]
#> $raw_difference
#> [1] 2.67037
#>
#> $phase_a_mean
#> [1] 1.351852
#>
#> $phase_b_mean
#> [1] 4.022222Random-effects structure
build_default_random_effects(fractions_p, scd_type = "ab",
case_var = "case",
nest_var = "question_type")
#> [1] "(1 + level_AB | case) + (1 + level_AB | case:question_type)"Priors
adaptive <- generate_adaptive_priors(fractions_p, structure = list(),
model_type = "gaussian")
adaptive$intercept$description
#> [1] "student_t(3, 3.02, 1.48)"
adaptive$treatment$description
#> [1] "normal(0, 0.74)"
adaptive$recommendations$overall
#> [1] "Prior strength: moderate (scale factor: 1.00)"Fitting the Bayesian model
opts <- list(
formula = outcome ~ time_A + level_AB + trend_AB +
(level_AB | case/question_type),
family = "cumulative",
prior_type = "default",
intervention_goal = "increase"
)
if (interactive()) {
result <- run_scd_analysis(fractions_p, options = opts)
result$diagnostics$converged
summarize_fixed_effect_decisions(result$model)
}Per-case decisions
The app’s Per Case tab reports each case’s own posterior (population
term plus case-level deviation) for every coefficient that varies by
case. The same table comes from
summarize_per_case_effects().
if (interactive()) {
summarize_per_case_effects(result$model,
intervention_goal = "increase")
}Source study
- Shin, M., & Park, J. (2024). Technology-assisted instruction with teacher prompts on fraction multiplication word problems: A single-case design with visual analysis and Bayesian multilevel modeling. Assistive Technology. https://doi.org/10.1080/10400435.2024.2415366
