PhysioAppKit is a small, domain-neutral engine for single-case (N-of-1) analysis. It works on plain numeric vectors and generic “group A vs group B” contrasts; a domain application layer (rehabilitation, sport, psychophysiology, …) supplies the ontology, thresholds and reporting and calls these functions. This vignette walks the two things the engine does: a single-case effect-size + verdict, and ordinal-to-interval Rasch measurement. Everything runs offline on tiny synthetic data.
Suppose a baseline phase (A) of repeated observations is followed by
an intervention phase (B), and a change of threshold units
is the smallest that matters (an MCID in rehab, an SWC in sport, a SESOI
in psychophysiology).
baseline <- c(10, 11, 9, 10, 10)
intervention <- c(12, 13, 14, 15)
res <- nonoverlap_analyze(baseline, intervention, threshold = 2,
direction = "increase")
c(nap = res$nap, interpretation = res$interpretation,
beyond_threshold = res$beyond_threshold)
#> nap interpretation beyond_threshold
#> "1" "大きい効果" "TRUE"nap() is the Nonoverlap of All Pairs effect size (0.5 =
complete overlap / no effect, 1 = every B point beats every A point),
and interpret_nap() bands it:
A phase plot shows the two phases against the baseline decision band and the threshold line:
y <- c(baseline, intervention)
phase_plot(x = seq_along(y), y = y,
a_idx = seq_along(baseline),
b_idx = length(baseline) + seq_along(intervention),
center = res$baseline_mean, lo = res$band_lo, hi = res$band_hi,
thr = res$baseline_mean + res$threshold, thr_lab = "threshold",
ylab = "outcome", main = "Single-case phase plot",
a_lab = "Baseline", b_lab = "Intervention")When several outcomes are each judged separately,
combine_verdicts() reduces them to one honest overall label
(all supported, some supported, or none):
A raw sum of ordinal items is not an interval scale: equal raw gains mean different real gains at different score levels. The dichotomous Rasch model calibrates item difficulties and places each person on a linear (logit) scale.
set.seed(1)
ability <- rnorm(40)
difficulty <- c(-1.5, -0.5, 0, 0.5, 1.5)
responses <- sapply(difficulty, function(d) rbinom(40, 1, plogis(ability - d)))
fit <- rasch_measure(responses)
round(fit$delta, 2) # calibrated item difficulties (centred logits)
#> [1] -3.83 -0.99 0.47 1.11 3.24The raw-score-to-measure table exposes the non-linear ogive — equal raw-score steps are unequal logit steps, largest near the floor and ceiling:
For ordered-category (polytomous) scales — ICF qualifiers, Likert,
the Barthel Index — use pcm_measure() (Partial Credit /
Rating Scale models) and poly_raw_measure();
pcm_stack() calibrates repeated measures onto one common
scale. See ?PhysioAppKit for the full map.