Simulates enrollment times from a Poisson process with a piecewise-constant rate.
enrollment(lambda = 1, N_total, lambda_time = NULL)A non-decreasing numeric vector of N_total continuous enrollment
times, measured from first patient in and expressed in the same time unit
used for lambda_time. The first value is zero.
A numeric vector of finite, positive enrollment rates per unit
of calendar time. Supply one rate for each interval defined by
lambda_time, so length(lambda) must equal length(lambda_time) + 1.
The default is 1.
A required positive integer giving the total sample size.
NULL (the default), or a numeric vector of finite,
positive, strictly increasing interior times at which the enrollment rate
changes. The initial boundary at time zero is implicit and must not be
supplied. Use NULL for a constant enrollment rate.
Major behavior change from goldilocks 0.5.0 and earlier.
Versions through 0.5.0 generated Poisson counts in unit-time bins.
enrollment() returned rebased integer bin times, after which
sim_comp_data() added independent uniform jitter and sorted the result.
From version 0.6.0, enrollment times are drawn directly from the exact
continuous-time piecewise-constant Poisson process. Consequently:
seeded simulations do not reproduce enrollment or downstream trial results obtained with version 0.5.0 or earlier;
enrollment times and operating-characteristic estimates can change, particularly when rates are low or a rate change is not an integer time;
the lambda_time argument now contains internal change times only: change
lambda_time = 0 to lambda_time = NULL for a constant rate, and change
lambda_time = c(0, t1, t2) to lambda_time = c(t1, t2) for a piecewise
rate.
enrollment() treats time zero as first patient in, matching the time
origin used throughout goldilocks. The first returned enrollment time is
therefore fixed at zero. The remaining N_total - 1 arrivals form a
continuous-time non-homogeneous Poisson process whose rate is constant
between the supplied internal knots. Thus, lambda is measured in
enrollments per unit of lambda_time; for example, when time is measured in
months, lambda = 5 means five enrollments per month on average.
Write the internal knots as \(0 < \tau_1 < \cdots < \tau_K\), with \(\tau_0 = 0\) implicit. The enrollment intensity is
$$ \lambda(t) = \lambda_j, \qquad \tau_{j-1} \le t < \tau_j, $$
for \(j = 1, \ldots, K\), and \(\lambda(t) = \lambda_{K+1}\) after the
final knot. The final rate therefore continues for as long as needed to reach
N_total; there is no finite accrual horizon in this function. The value of
the intensity at an isolated knot does not change the Poisson process. When
assigning a realized enrollment time to an interval, goldilocks follows the
survival counting-process convention: intervals are open on the left and
closed on the right, so an arrival exactly at \(\tau_j\) belongs to the
interval ending at \(\tau_j\). The first patient at time zero is a fixed
origin and is handled separately.
Arrivals are generated exactly by the time-rescaling theorem. If \(E_2, \ldots, E_N\) are independent unit-rate exponential variables and \(S_i = \sum_{k=2}^i E_k\), then the enrollment times after first patient in are
$$T_1 = 0, \qquad T_i = \Lambda^{-1}(S_i),$$
where \(\Lambda(t) = \int_0^t \lambda(u)\,du\) is the cumulative enrollment
intensity. This construction gives independent Poisson counts on disjoint
calendar intervals, with expected count \(\int_a^b \lambda(u)\,du\) over
\((a,b]\). For a constant rate, successive enrollment gaps are independent
Exponential(lambda) variables.
The rate-change times are measured from first patient in, not from an earlier site-opening or trial-activation date. If operational delays before first patient in are important, they must be modelled separately before using the returned relative times.
For example, lambda = c(0.3, 0.7, 0.9, 1.2) with
lambda_time = c(5, 10, 15) specifies average enrollment rates of 0.3 over
positive times in \((0,5]\), 0.7 over \((5,10]\), 0.9 over \((10,15]\),
and 1.2 after time 15. Fractional knots such as lambda_time = 2.5 are
handled exactly; no unit-time binning or post-hoc jitter is used.
# Constant enrollment: first patient at zero, then exponential gaps.
enrollment(lambda = 0.7, N_total = 10)
# Three internal rate changes define four enrollment intervals.
enrollment(
lambda = c(0.3, 0.7, 0.9, 1.2),
N_total = 50,
lambda_time = c(5, 10, 15)
)
# Fractional change times are supported exactly.
enrollment(
lambda = c(0.25, 1),
N_total = 20,
lambda_time = 2.5
)
Run the code above in your browser using DataLab