Getting Started
getting-started.RmdThis vignette walks through a complete rxsim simulation from start to finish: defining a trial scenario, building arm populations, registering an analysis trigger, running replicates, and collecting results. By the end you will have seen the full rxsim workflow in one place and will be ready to adapt it to your own design. For deeper explanations of each building block, see the Core Concepts vignette.
Step 1 — Define the scenario
The scenario tibble captures the design parameters you
want to track in your results — sample size, allocation ratios, or any
other factors you might vary across simulation runs. Wrapping them in
tidyr::expand_grid() produces a one-row data frame that
gets embedded in every analysis result. When you later stack results
across many scenarios or sensitivity analyses, this metadata keeps each
row traceable back to its design.
sample_size <- 30
arms <- c("control", "treatment")
allocation <- c(1, 1)
true_delta <- 0.5
scenario <- tidyr::expand_grid(
sample_size = sample_size,
allocation = list(allocation),
true_delta = true_delta
)Step 2 — Define arm populations
Each trial arm is represented by a generator
function — a plain R function that takes n (the
number of subjects planned for that arm) and returns a data frame of
subject-level endpoint data. rxsim calls these functions once per
replicate to draw a fresh population, so every replicate gets
independent data.
The data frame must contain at least three columns:
-
id— a unique integer identifier per subject -
readout_time— the time (in trial-time units) after enrollment when the endpoint is observed (use0for baseline or immediately-available data) - at least one endpoint column
vector_to_dataframe() is a convenience helper that wraps
a numeric vector into this standard format with id,
data, and readout_time = 0.
Here we simulate a simple continuous endpoint: the control arm is
standard-normal, the treatment arm has a mean shift of
true_delta.
population_generators <- list(
control = function(n) vector_to_dataframe(rnorm(n)),
treatment = function(n) vector_to_dataframe(rnorm(n, mean = true_delta))
)Step 3 — Define enrollment and dropout
Enrollment and dropout are modelled as random processes. Each
function takes n and returns a vector of
inter-event times — the waiting times between
successive enrollments (or dropouts). These times are drawn
independently for every replicate, giving each trial its own enrollment
trajectory.
rexp(n, rate = 1) generates exponentially-distributed
inter-arrival times with a mean gap of 1 time unit between enrolments —
a common approximation for Poisson arrivals. A lower dropout rate
(0.05) reflects a trial where most subjects complete the
study.
Step 4 — Define analysis triggers
Analysis triggers are the heart of rxsim. Each trigger pairs a condition (when to fire) with an analysis function (what to compute when it fires).
The condition is written as a dplyr-style boolean
expression inside rlang::exprs(). It is evaluated against a
snapshot of all currently enrolled subjects at each timepoint. Here the
condition fires once full enrollment is reached, i.e.,
sample_size subjects have accumulated a non-NA
enroll_time.
The !! operator (pronounced “bang-bang”) injects
the current value of sample_size into the
expression at definition time, rather than looking it up at evaluation
time. This is necessary because the expression is stored and evaluated
later inside the simulation loop.
When the condition is met, rxsim calls the analysis function with two arguments:
-
df: a data frame snapshot of all enrolled subjects at the triggering timepoint, with columns from the population data plusenroll_time,drop_time, andarm -
time: the current trial clock time at which the trigger fired
The function should return a data frame (one row per trigger event is the conventional pattern).
analysis_generators <- list(
final = list(
trigger = rlang::exprs(
sum(!is.na(enroll_time)) >= !!sample_size
),
analysis = function(df, timer) {
enrolled <- subset(df, !is.na(enroll_time))
data.frame(
scenario,
n_enrolled = nrow(enrolled),
mean_ctrl = mean(enrolled$data[enrolled$arm == "control"]),
mean_trt = mean(enrolled$data[enrolled$arm == "treatment"]),
stringsAsFactors = FALSE
)
}
)
)Step 5 — Create replicates and run
replicate_trial() generates n fully
independent Trial objects. For each replicate it:
- Samples a fresh enrollment/dropout timeline from your functions
- Calls each population generator to draw new subject-level data
- Registers your analysis triggers on the trial’s internal timer
run_trials() then executes every replicate’s simulation
loop in sequence.
set.seed(42)
trials <- replicate_trial(
trial_name = "getting_started",
sample_size = sample_size,
arms = arms,
allocation = allocation,
enrollment = enrollment,
dropout = dropout,
analysis_generators = analysis_generators,
population_generators = population_generators,
n = 5
)
run_trials(trials)
#> [[1]]
#> <Trial>
#> Public:
#> clone: function (deep = FALSE)
#> initialize: function (name, seed = NULL, timer = NULL, population = list(),
#> locked_data: list
#> name: getting_started_1
#> population: list
#> results: list
#> run: function ()
#> seed: NULL
#> timer: Timer, R6
#>
#> [[2]]
#> <Trial>
#> Public:
#> clone: function (deep = FALSE)
#> initialize: function (name, seed = NULL, timer = NULL, population = list(),
#> locked_data: list
#> name: getting_started_2
#> population: list
#> results: list
#> run: function ()
#> seed: NULL
#> timer: Timer, R6
#>
#> [[3]]
#> <Trial>
#> Public:
#> clone: function (deep = FALSE)
#> initialize: function (name, seed = NULL, timer = NULL, population = list(),
#> locked_data: list
#> name: getting_started_3
#> population: list
#> results: list
#> run: function ()
#> seed: NULL
#> timer: Timer, R6
#>
#> [[4]]
#> <Trial>
#> Public:
#> clone: function (deep = FALSE)
#> initialize: function (name, seed = NULL, timer = NULL, population = list(),
#> locked_data: list
#> name: getting_started_4
#> population: list
#> results: list
#> run: function ()
#> seed: NULL
#> timer: Timer, R6
#>
#> [[5]]
#> <Trial>
#> Public:
#> clone: function (deep = FALSE)
#> initialize: function (name, seed = NULL, timer = NULL, population = list(),
#> locked_data: list
#> name: getting_started_5
#> population: list
#> results: list
#> run: function ()
#> seed: NULL
#> timer: Timer, R6Step 6 — Collect and interpret results
Analysis results
After running, each Trial object exposes a
results list. It is indexed first by the
timepoint at which an analysis fired (e.g.,
"time_30.4"), then by the analysis name
you gave it (here "final"). The value is whatever your
analysis function returned.
The collect_results() helper gathers every analysis from
every timepoint across all replicates into one tidy data frame:
replicate_results <- collect_results(trials)
replicate_results
#> replicate timepoint analysis sample_size allocation true_delta n_enrolled
#> 1 1 29.71727 final 30 1, 1 0.5 30
#> 2 1 71.75884 final 30 1, 1 0.5 30
#> 3 1 81.71066 final 30 1, 1 0.5 30
#> 4 1 88.80173 final 30 1, 1 0.5 30
#> 5 1 123.92991 final 30 1, 1 0.5 30
#> 6 1 138.67989 final 30 1, 1 0.5 30
#> 7 1 139.25641 final 30 1, 1 0.5 30
#> 8 1 146.28070 final 30 1, 1 0.5 30
#> 9 1 154.13389 final 30 1, 1 0.5 30
#> 10 1 192.17561 final 30 1, 1 0.5 30
#> 11 1 207.74148 final 30 1, 1 0.5 30
#> 12 1 220.86782 final 30 1, 1 0.5 30
#> 13 1 228.59602 final 30 1, 1 0.5 30
#> 14 1 256.91786 final 30 1, 1 0.5 30
#> 15 1 287.38043 final 30 1, 1 0.5 30
#> 16 1 296.15466 final 30 1, 1 0.5 30
#> 17 1 379.51726 final 30 1, 1 0.5 30
#> 18 1 403.41940 final 30 1, 1 0.5 30
#> 19 1 403.99571 final 30 1, 1 0.5 30
#> 20 1 540.92715 final 30 1, 1 0.5 30
#> 21 1 544.19131 final 30 1, 1 0.5 30
#> 22 1 577.18203 final 30 1, 1 0.5 30
#> 23 1 599.76724 final 30 1, 1 0.5 30
#> 24 1 605.59251 final 30 1, 1 0.5 30
#> 25 1 616.62545 final 30 1, 1 0.5 30
#> 26 1 619.17132 final 30 1, 1 0.5 30
#> 27 1 648.08404 final 30 1, 1 0.5 30
#> 28 1 666.36446 final 30 1, 1 0.5 30
#> 29 1 673.06152 final 30 1, 1 0.5 30
#> 30 1 842.30823 final 30 1, 1 0.5 30
#> 31 2 27.31408 final 30 1, 1 0.5 30
#> 32 2 48.00359 final 30 1, 1 0.5 30
#> 33 2 109.71186 final 30 1, 1 0.5 30
#> 34 2 131.84283 final 30 1, 1 0.5 30
#> 35 2 133.73988 final 30 1, 1 0.5 30
#> 36 2 136.11920 final 30 1, 1 0.5 30
#> 37 2 137.84044 final 30 1, 1 0.5 30
#> 38 2 142.18902 final 30 1, 1 0.5 30
#> 39 2 160.61632 final 30 1, 1 0.5 30
#> 40 2 198.01478 final 30 1, 1 0.5 30
#> 41 2 264.40849 final 30 1, 1 0.5 30
#> 42 2 294.33890 final 30 1, 1 0.5 30
#> 43 2 366.11547 final 30 1, 1 0.5 30
#> 44 2 367.31573 final 30 1, 1 0.5 30
#> 45 2 394.88895 final 30 1, 1 0.5 30
#> 46 2 438.12156 final 30 1, 1 0.5 30
#> 47 2 440.57908 final 30 1, 1 0.5 30
#> 48 2 484.79892 final 30 1, 1 0.5 30
#> 49 2 526.34752 final 30 1, 1 0.5 30
#> 50 2 528.33233 final 30 1, 1 0.5 30
#> 51 2 544.26888 final 30 1, 1 0.5 30
#> 52 2 560.74408 final 30 1, 1 0.5 30
#> 53 2 561.97384 final 30 1, 1 0.5 30
#> 54 2 638.74485 final 30 1, 1 0.5 30
#> 55 2 650.69527 final 30 1, 1 0.5 30
#> 56 2 699.76729 final 30 1, 1 0.5 30
#> 57 2 704.52535 final 30 1, 1 0.5 30
#> 58 3 35.29848 final 30 1, 1 0.5 30
#> 59 3 69.62658 final 30 1, 1 0.5 30
#> 60 3 70.81995 final 30 1, 1 0.5 30
#> 61 3 78.09509 final 30 1, 1 0.5 30
#> 62 3 112.62422 final 30 1, 1 0.5 30
#> 63 3 120.26618 final 30 1, 1 0.5 30
#> 64 3 166.04672 final 30 1, 1 0.5 30
#> 65 3 244.41745 final 30 1, 1 0.5 30
#> 66 3 244.94703 final 30 1, 1 0.5 30
#> 67 3 250.17608 final 30 1, 1 0.5 30
#> 68 3 277.54075 final 30 1, 1 0.5 30
#> 69 3 279.03777 final 30 1, 1 0.5 30
#> 70 3 294.09805 final 30 1, 1 0.5 30
#> 71 3 342.65569 final 30 1, 1 0.5 30
#> 72 3 367.39120 final 30 1, 1 0.5 30
#> 73 3 411.00304 final 30 1, 1 0.5 30
#> 74 3 443.18313 final 30 1, 1 0.5 30
#> 75 3 457.78388 final 30 1, 1 0.5 30
#> 76 3 468.89933 final 30 1, 1 0.5 30
#> 77 3 483.59472 final 30 1, 1 0.5 30
#> 78 3 508.70768 final 30 1, 1 0.5 30
#> 79 3 510.42419 final 30 1, 1 0.5 30
#> 80 3 555.17049 final 30 1, 1 0.5 30
#> 81 3 573.74553 final 30 1, 1 0.5 30
#> 82 3 574.31182 final 30 1, 1 0.5 30
#> 83 3 574.90874 final 30 1, 1 0.5 30
#> 84 3 576.72932 final 30 1, 1 0.5 30
#> 85 3 591.75515 final 30 1, 1 0.5 30
#> 86 3 662.12355 final 30 1, 1 0.5 30
#> 87 4 23.61616 final 30 1, 1 0.5 30
#> 88 4 29.72873 final 30 1, 1 0.5 30
#> 89 4 72.60486 final 30 1, 1 0.5 30
#> 90 4 88.63264 final 30 1, 1 0.5 30
#> 91 4 99.34682 final 30 1, 1 0.5 30
#> 92 4 139.98048 final 30 1, 1 0.5 30
#> 93 4 206.27598 final 30 1, 1 0.5 30
#> 94 4 266.56996 final 30 1, 1 0.5 30
#> 95 4 283.19883 final 30 1, 1 0.5 30
#> 96 4 304.96656 final 30 1, 1 0.5 30
#> 97 4 314.46469 final 30 1, 1 0.5 30
#> 98 4 328.46072 final 30 1, 1 0.5 30
#> 99 4 329.15820 final 30 1, 1 0.5 30
#> 100 4 339.53599 final 30 1, 1 0.5 30
#> 101 4 344.97937 final 30 1, 1 0.5 30
#> 102 4 385.33577 final 30 1, 1 0.5 30
#> 103 4 385.34138 final 30 1, 1 0.5 30
#> 104 4 456.78964 final 30 1, 1 0.5 30
#> 105 4 534.01374 final 30 1, 1 0.5 30
#> 106 4 570.68747 final 30 1, 1 0.5 30
#> 107 4 611.73903 final 30 1, 1 0.5 30
#> 108 4 639.27803 final 30 1, 1 0.5 30
#> 109 4 657.52944 final 30 1, 1 0.5 30
#> 110 4 670.87695 final 30 1, 1 0.5 30
#> 111 4 695.91081 final 30 1, 1 0.5 30
#> 112 4 710.49484 final 30 1, 1 0.5 30
#> 113 4 728.27773 final 30 1, 1 0.5 30
#> 114 4 739.33553 final 30 1, 1 0.5 30
#> 115 4 757.50669 final 30 1, 1 0.5 30
#> 116 4 758.12874 final 30 1, 1 0.5 30
#> 117 4 774.26422 final 30 1, 1 0.5 30
#> 118 5 25.83584 final 30 1, 1 0.5 30
#> 119 5 42.69936 final 30 1, 1 0.5 30
#> 120 5 55.30675 final 30 1, 1 0.5 30
#> 121 5 78.63514 final 30 1, 1 0.5 30
#> 122 5 98.58472 final 30 1, 1 0.5 30
#> 123 5 124.76022 final 30 1, 1 0.5 30
#> 124 5 137.43827 final 30 1, 1 0.5 30
#> 125 5 185.54669 final 30 1, 1 0.5 30
#> 126 5 204.11105 final 30 1, 1 0.5 30
#> 127 5 209.57048 final 30 1, 1 0.5 30
#> 128 5 217.52736 final 30 1, 1 0.5 30
#> 129 5 218.93812 final 30 1, 1 0.5 30
#> 130 5 224.62617 final 30 1, 1 0.5 30
#> 131 5 292.09763 final 30 1, 1 0.5 30
#> 132 5 303.22840 final 30 1, 1 0.5 30
#> 133 5 306.62372 final 30 1, 1 0.5 30
#> 134 5 356.25605 final 30 1, 1 0.5 30
#> 135 5 381.40767 final 30 1, 1 0.5 30
#> 136 5 418.34338 final 30 1, 1 0.5 30
#> 137 5 447.44924 final 30 1, 1 0.5 30
#> 138 5 461.90921 final 30 1, 1 0.5 30
#> 139 5 464.03910 final 30 1, 1 0.5 30
#> 140 5 495.45607 final 30 1, 1 0.5 30
#> 141 5 508.54993 final 30 1, 1 0.5 30
#> 142 5 516.79836 final 30 1, 1 0.5 30
#> 143 5 547.04878 final 30 1, 1 0.5 30
#> 144 5 633.22196 final 30 1, 1 0.5 30
#> 145 5 640.68178 final 30 1, 1 0.5 30
#> 146 5 647.93051 final 30 1, 1 0.5 30
#> 147 5 653.59243 final 30 1, 1 0.5 30
#> mean_ctrl mean_trt
#> 1 -0.1657292 0.61748974
#> 2 -0.1657292 0.61748974
#> 3 -0.1657292 0.61748974
#> 4 -0.1657292 0.61748974
#> 5 -0.1657292 0.61748974
#> 6 -0.1657292 0.61748974
#> 7 -0.1657292 0.61748974
#> 8 -0.1657292 0.61748974
#> 9 -0.1657292 0.61748974
#> 10 -0.1657292 0.61748974
#> 11 -0.1657292 0.61748974
#> 12 -0.1657292 0.61748974
#> 13 -0.1657292 0.61748974
#> 14 -0.1657292 0.61748974
#> 15 -0.1657292 0.61748974
#> 16 -0.1657292 0.61748974
#> 17 -0.1657292 0.61748974
#> 18 -0.1657292 0.61748974
#> 19 -0.1657292 0.61748974
#> 20 -0.1657292 0.61748974
#> 21 -0.1657292 0.61748974
#> 22 -0.1657292 0.61748974
#> 23 -0.1657292 0.61748974
#> 24 -0.1657292 0.61748974
#> 25 -0.1657292 0.61748974
#> 26 -0.1657292 0.61748974
#> 27 -0.1657292 0.61748974
#> 28 -0.1657292 0.61748974
#> 29 -0.1657292 0.61748974
#> 30 -0.1657292 0.61748974
#> 31 -0.0978443 0.64303730
#> 32 -0.0978443 0.64303730
#> 33 -0.0978443 0.64303730
#> 34 -0.0978443 0.64303730
#> 35 -0.0978443 0.64303730
#> 36 -0.0978443 0.64303730
#> 37 -0.0978443 0.64303730
#> 38 -0.0978443 0.64303730
#> 39 -0.0978443 0.64303730
#> 40 -0.0978443 0.64303730
#> 41 -0.0978443 0.64303730
#> 42 -0.0978443 0.64303730
#> 43 -0.0978443 0.64303730
#> 44 -0.0978443 0.64303730
#> 45 -0.0978443 0.64303730
#> 46 -0.0978443 0.64303730
#> 47 -0.0978443 0.64303730
#> 48 -0.0978443 0.64303730
#> 49 -0.0978443 0.64303730
#> 50 -0.0978443 0.64303730
#> 51 -0.0978443 0.64303730
#> 52 -0.0978443 0.64303730
#> 53 -0.0978443 0.64303730
#> 54 -0.0978443 0.64303730
#> 55 -0.0978443 0.64303730
#> 56 -0.0978443 0.64303730
#> 57 -0.0978443 0.64303730
#> 58 -0.2573593 0.07050019
#> 59 -0.2573593 0.07050019
#> 60 -0.2573593 0.07050019
#> 61 -0.2573593 0.07050019
#> 62 -0.2573593 0.07050019
#> 63 -0.2573593 0.07050019
#> 64 -0.2573593 0.07050019
#> 65 -0.2573593 0.07050019
#> 66 -0.2573593 0.07050019
#> 67 -0.2573593 0.07050019
#> 68 -0.2573593 0.07050019
#> 69 -0.2573593 0.07050019
#> 70 -0.2573593 0.07050019
#> 71 -0.2573593 0.07050019
#> 72 -0.2573593 0.07050019
#> 73 -0.2573593 0.07050019
#> 74 -0.2573593 0.07050019
#> 75 -0.2573593 0.07050019
#> 76 -0.2573593 0.07050019
#> 77 -0.2573593 0.07050019
#> 78 -0.2573593 0.07050019
#> 79 -0.2573593 0.07050019
#> 80 -0.2573593 0.07050019
#> 81 -0.2573593 0.07050019
#> 82 -0.2573593 0.07050019
#> 83 -0.2573593 0.07050019
#> 84 -0.2573593 0.07050019
#> 85 -0.2573593 0.07050019
#> 86 -0.2573593 0.07050019
#> 87 -0.4199802 0.25120329
#> 88 -0.4199802 0.25120329
#> 89 -0.4199802 0.25120329
#> 90 -0.4199802 0.25120329
#> 91 -0.4199802 0.25120329
#> 92 -0.4199802 0.25120329
#> 93 -0.4199802 0.25120329
#> 94 -0.4199802 0.25120329
#> 95 -0.4199802 0.25120329
#> 96 -0.4199802 0.25120329
#> 97 -0.4199802 0.25120329
#> 98 -0.4199802 0.25120329
#> 99 -0.4199802 0.25120329
#> 100 -0.4199802 0.25120329
#> 101 -0.4199802 0.25120329
#> 102 -0.4199802 0.25120329
#> 103 -0.4199802 0.25120329
#> 104 -0.4199802 0.25120329
#> 105 -0.4199802 0.25120329
#> 106 -0.4199802 0.25120329
#> 107 -0.4199802 0.25120329
#> 108 -0.4199802 0.25120329
#> 109 -0.4199802 0.25120329
#> 110 -0.4199802 0.25120329
#> 111 -0.4199802 0.25120329
#> 112 -0.4199802 0.25120329
#> 113 -0.4199802 0.25120329
#> 114 -0.4199802 0.25120329
#> 115 -0.4199802 0.25120329
#> 116 -0.4199802 0.25120329
#> 117 -0.4199802 0.25120329
#> 118 -0.4170091 0.59879107
#> 119 -0.4170091 0.59879107
#> 120 -0.4170091 0.59879107
#> 121 -0.4170091 0.59879107
#> 122 -0.4170091 0.59879107
#> 123 -0.4170091 0.59879107
#> 124 -0.4170091 0.59879107
#> 125 -0.4170091 0.59879107
#> 126 -0.4170091 0.59879107
#> 127 -0.4170091 0.59879107
#> 128 -0.4170091 0.59879107
#> 129 -0.4170091 0.59879107
#> 130 -0.4170091 0.59879107
#> 131 -0.4170091 0.59879107
#> 132 -0.4170091 0.59879107
#> 133 -0.4170091 0.59879107
#> 134 -0.4170091 0.59879107
#> 135 -0.4170091 0.59879107
#> 136 -0.4170091 0.59879107
#> 137 -0.4170091 0.59879107
#> 138 -0.4170091 0.59879107
#> 139 -0.4170091 0.59879107
#> 140 -0.4170091 0.59879107
#> 141 -0.4170091 0.59879107
#> 142 -0.4170091 0.59879107
#> 143 -0.4170091 0.59879107
#> 144 -0.4170091 0.59879107
#> 145 -0.4170091 0.59879107
#> 146 -0.4170091 0.59879107
#> 147 -0.4170091 0.59879107Each row is one replicate. The mean_ctrl and
mean_trt columns show the arm-level sample means at the
moment the final analysis fired. The timepoint and
analysis columns identify when and which analysis produced
each row — essential when a trial has both interim and final analyses.
Variation across replicates reflects both the stochastic endpoint data
and the randomness in enrollment timing; exactly what operating
characteristic simulations are designed to characterise.
Locked data snapshots
Every time an analysis fires, rxsim also saves a locked data snapshot, the full subject-level data frame at that timepoint. You can inspect it directly to debug your analysis function, audit which subjects were enrolled, or compute additional statistics post-hoc.
# One snapshot per timepoint that fired in replicate 1
names(trials[[1]]$locked_data)
#> [1] "time_29.7172711929598" "time_71.7588397920052" "time_81.7106552388439"
#> [4] "time_88.8017284464011" "time_123.929908531333" "time_138.679889248391"
#> [7] "time_139.256406634753" "time_146.280697615524" "time_154.133894694986"
#> [10] "time_192.175611581853" "time_207.741484369442" "time_220.867823778942"
#> [13] "time_228.5960165945" "time_256.917855072035" "time_287.380430737777"
#> [16] "time_296.154664244769" "time_379.517257070982" "time_403.419397851426"
#> [19] "time_403.995706183809" "time_540.927149055388" "time_544.191309155759"
#> [22] "time_577.182029686913" "time_599.767237766782" "time_605.592512902939"
#> [25] "time_616.625447408432" "time_619.171321070889" "time_648.084043521793"
#> [28] "time_666.364456690367" "time_673.061517277252" "time_842.308234163735"
# First six rows of the snapshot
head(trials[[1]]$locked_data[[1]])
#> id data readout_time arm enroll_time drop_time subject_id
#> 1 1 -2.6882473 0 control 0.8592321 NA 1
#> 2 2 0.8666502 0 control 11.6939492 NA 2
#> 3 3 0.1687397 0 control 26.6106187 NA 3
#> 4 4 -1.0908241 0 control 1.6540916 NA 4
#> 5 5 -0.3803481 0 control 9.5016932 NA 5
#> 6 6 -0.9480918 0 control 13.9319792 NA 6
#> measurement_time time
#> 1 0.8592321 29.71727
#> 2 11.6939492 29.71727
#> 3 26.6106187 29.71727
#> 4 1.6540916 29.71727
#> 5 9.5016932 29.71727
#> 6 13.9319792 29.71727The locked data contains the population columns (id,
data, arm, readout_time) plus
three columns added by rxsim:
| Column | Meaning |
|---|---|
enroll_time |
Calendar time the subject was enrolled (NA if not yet
enrolled) |
drop_time |
Calendar time the subject dropped out (NA if still
active) |
time |
The trial clock time at which this snapshot was taken |
Next steps
Now that you have seen the full workflow, here is where to go next:
-
Core Concepts —
understand how
Population,Timer, andTrialcompose, and how to write more advanced trigger expressions -
Enrollment & Dropout
Modeling — choose between stochastic
(
gen_plan) and piecewise-constant (gen_timepoints) schedules - Example 1 through Example 7 — progressively complex designs: correlated endpoints, time-to-event, multi-arm dose-finding, subgroup analyses, and Bayesian Go/No-Go rules