--- title: "A strict synthetic paired study" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{A strict synthetic paired study} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} resource_files: - figures/logo.svg - figures/logo-dark.svg --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` This example estimates the mean within-pair change between two occasions. The recipe matches observations by identifier, fixes the direction as after minus before and performs a two-sided t test on the differences. It accepts synthetic data only. A before-after contrast does not identify a treatment effect. ## Generate complete pairs These are newly simulated values, not measurements from patients. The English column names identify the pair, occasion and measurement. Each pair has two correlated measurements, while pairs are independently generated. ```{r paired-data} data <- withr::with_seed(20261017, { pair_id <- sprintf("example_%03d", seq_len(24)) baseline <- stats::rnorm(24, mean = 120, sd = 12) difference <- stats::rnorm(24, mean = -3, sd = 5) values <- rbind( data.frame(pair_id = pair_id, visit = "baseline", pressure = baseline), data.frame(pair_id = pair_id, visit = "followup", pressure = baseline + difference) ) values[sample(seq_len(nrow(values))), , drop = FALSE] }) units <- c(pressure = "mmHg") spec <- cttiR::study_paired_spec( study_id = "synthetic_paired_change", name = "Synthetic paired pressure example", question = "What is the mean followup-minus-baseline pressure change?", population = "Twenty-four independently generated synthetic pairs", pair_id = "pair_id", occasion = "visit", outcome = list(name = "pressure", type = "continuous", unit = "mmHg"), before = "baseline", after = "followup", independent_pairs = TRUE, research = list(domain = "clinical", data_origin = "primary", design = "observational") ) cttiR::study_validate(spec, data, units) ``` The shuffled row order is intentional: matching uses `pair_id`, not adjacent rows. A real study would require scientific justification for independent pairs; the explicit declaration is not a test or proof of independence. Shared household or centre effects may require a different design and model. The strict contract requires exactly the three declared columns, one measurement per pair at each occasion, finite measurements and matching units. Incomplete pairs, additional visits and duplicate pair-occasion records are rejected. There is no silent exclusion, imputation or automatic switch of statistical test. ## Inspect the estimate ```{r paired-preview} result <- cttiR::study_analyze(spec, data, units) result$coefficients c(pairs = result$n_pairs, rows = result$n, degrees_of_freedom = result$df_residual) ``` The estimate and confidence interval use followup minus baseline in mmHg. The two-sided null is a population mean difference of zero. The data-generating mean of -3 is known for this simulation; an individual sample need not reproduce it exactly. The t inference requires an appropriate distribution of independent within-pair differences. Inspect the difference distribution and its normal quantile plot, and retain scientific review as pending. These checks do not establish clinical importance or a causal effect. ## Create the reproducible project The following explicit steps are not executed during vignette builds. Provision an installed library with cttiR, reflowR, workflowr and their dependencies first. The dependency lock records installed versions; it does not install packages. ```{r paired-project, eval=FALSE} directory <- tempfile("paired-study-", tmpdir = normalizePath(tempdir())) compiled <- cttiR::study_project( directory, spec, data, cttiR::study_dependency_lock(), author = "Research group", units = units, seed = 20261017L ) analyzed <- cttiR::study_run(compiled$directory, compiled$declaration) reported <- cttiR::study_render(analyzed$directory, analyzed$declaration) validation <- cttiR::study_validate_project( reported$directory, reported$declaration, require_render = TRUE ) stopifnot(validation$valid, !validation$scientific_approval) ``` Keep each returned declaration outside the project in a trusted location. The new project has its own Git repository; only the generated analysis Rmd files are staged, and no commit is created. Reports identify these files as uncommitted. Raw values remain read-only, separate from derived results. Rendering presents the recorded analysis without refitting it, and rejects stale input or output. The profile fixes eleven stage locations plus the index. Nine stages apply to this recipe; sensitivity and exploratory work are explicitly inapplicable. The clinical domain uses red `#C8102E`; primary describes the new data origin, and observational describes the design. The diagnostics plot sorts pair IDs; that index is not a time axis. Inspect `docs/index.html` and the stage reports. Preserve the original project, receipts and read-only file modes; create a new project for a changed analysis. Successful validation does not approve a real study or extend the model's qualified planning scope.