vignettes/quickstart.Rmd
quickstart.Rmd
The purpose of this vignette is to explain the use of
getClinicalTrials()
, the core function of this package.
getClinicalTrials()
can be used to simulate a large number
of clinical trials with endpoints progression-free survival (PFS) and
overall survival (OS). The underlying model is a survival multistate
model with an initial state, an intermediate progression
state and an absorbing death
state. The multistate model
approach has the advantage of naturally accounting for the correlation
between the PFS and OS endpoints (Meller,
Beyersmann, and Rufibach 2019). OS is defined as the time to
reach the absorbing state death and PFS is defined as the time to reach
the absorbing state death
or the intermediate state
progression
, whichever occurs first. Figure 1 shows the
multistate model with the corresponding transition hazards. To get
started quickly, we show a simple and quick example of a clinical trial
simulation.
getClinicalTrials()
simulates trials with an arbitrary
number of treatment arms. In general, the argument specifications were
tried to be similar to the R-package Rpact (Wassmer and Pahlke 2021) in order to be more
user-friendly. For illustration, we consider a trial with two arms. The
number of patients per trial must be specified. In our example
simulation there are 30 patients in the first treatment arm and 60 in
the second treatment arm:
nPat <- c(30, 60)
The transition parameters describing the transition hazards per
treatment arm must be passed as a list to
getClinicalTrials()
. The class
TransitionParameters
contains the elements
hazards
, intervals
, weibull_rates
and family
which allow to describe transition hazards
leading to exponential, piecewise exponential or Weibull distributed
survival times. There are some helper functions in the
simIDM
package to create the appropriate transition
parameters for the desired distribution. -
exponential_transition()
: creates a list with class
TransitionParameters
containing hazards, time intervals and
Weibull rates for exponential event times in an illness-death model. -
piecewise_exponential()
: creates a list with class
TransitionParameters
containing hazards, time intervals and
Weibull rates for piecewise exponential event times in an illness-death
model. - weibull_transition()
: creates a list with class
TransitionParameters
containing hazards, time intervals and
Weibull rates for Weibull distributed event times in an illness-death
model.
In our example we consider constant hazard rates, i.e. exponential distributed event times.
library(simIDM)
transitionGroup1 <- exponential_transition(h01 = 1.2, h02 = 1.5, h12 = 1.6)
print(transitionGroup1$hazards)
#> $h01
#> [1] 1.2
#>
#> $h02
#> [1] 1.5
#>
#> $h12
#> [1] 1.6
transitionGroup2 <- exponential_transition(h01 = 1, h02 = 1.3, h12 = 1.7)
print(transitionGroup2$hazards)
#> $h01
#> [1] 1
#>
#> $h02
#> [1] 1.3
#>
#> $h12
#> [1] 1.7
transitionbyArm <- list(transitionGroup1, transitionGroup2)
The specification for random patient dropouts can be passed directly
to getClinicalTrials()
. A list with elements
rate
and time
specifies the drop-out
probability. Random censoring times are generated using the exponential
distribution. dropout$rate
specifies the drop-out
probability per dropout$time
time units. The dropout
parameters can be specified either as one list that should be applied to
all treatment groups or a separate list for each treatment group. If
dropout$rate
is equal to 0, then no censoring due to
dropout is applied. In our example we expect that 10% of the patients
drop-out within 12 months per treatment group (we take month as the time
unit of our trial), thus we specify:
dropout <- list(rate = 0.1, time = 12)
There are two time-scales that we need to consider when simulating
multistate data. The individual time scale with start in the initial
state at time 0 and the study time scale, which matches the individual
time scale only if the study start time (e.g. randomization date) is the
same time in calendar time for all patients. It can also be specified
that patients enter the study in a staggered manner. Uniformly
distributed random variables are used to generate staggered study entry
times. There are two possibilities for the specification: Either, the
length of the accrual period is specified, e.g. 12 month, in which case
the staggered entry times are generated in each treatment group using
random variables \(U ~Unif(0, 12)\).
Or, it is specified how many patients are recruited per time unit in
each treatment group. Thus, if 10 patients are recruited per month, then
the staggered entry times are generated using random variables \(U ~Unif(0, 30/10)\). A list
accural
with elements accrualParam
and
accrualValue
is passed to getClinicalTrials()
describing the accrual intensity. For accrualParam
equal
time, accrualValue
describes the length of the accrual
period. For accrualParam
equal intensity, it describes the
number of patients recruited per time unit. If accrualValue
is equal to 0, all patients start at the same calender time in the
initial state. The accrual parameters can be specified either as one
list that should be applied to all treatment groups or a separate list
for each treatment group.
We now simulate 100 (nRep
=100) clinical trials with the
parameters described and specified above. There are two options for how
the output data is presented, one row per patient or one row per
transition and patient. Let’s take a look at both.
simStudies1 <- getClinicalTrials(
nRep = 100, nPat = nPat, seed = 1234, datType = "1rowTransition",
transitionByArm = transitionbyArm, dropout = dropout,
accrual = accrual
)
simStudies2 <- getClinicalTrials(
nRep = 100, nPat = nPat, seed = 1234, datType = "1rowPatient",
transitionByArm = transitionbyArm, dropout = dropout,
accrual = accrual
)
We get as output a list with nRep
elements, each
containing a data set of a single simulated trial. The specification of
the seed ensures, that the the datasets of the two lists contain the
same study data, only the presentation is different.
simStudies1
shows the transition times per patient and
simStudies2
the PFS and OS times per patient.
head(simStudies1[[1]], 6)
#> id from to entry exit entryAct exitAct censAct trt
#> 1 1 0 2 0.0000000 0.46787743 1.234711 1.702588 286.171654 1
#> 2 2 0 2 0.0000000 0.26010392 7.971605 8.231709 36.076123 1
#> 3 3 0 2 0.0000000 0.06150124 7.442772 7.504273 8.192422 1
#> 4 4 0 1 0.0000000 0.25964639 9.159742 9.419389 207.649214 1
#> 5 4 1 2 0.2596464 2.13580247 9.419389 11.295545 207.649214 1
#> 6 5 0 2 0.0000000 0.25227459 9.945982 10.198257 54.044011 1
head(simStudies2[[1]], 5)
#> id trt PFStime CensoredPFS PFSevent OStime CensoredOS OSevent
#> 1 1 1 0.46787743 0 1 0.46787743 0 1
#> 2 2 1 0.26010392 0 1 0.26010392 0 1
#> 3 3 1 0.06150124 0 1 0.06150124 0 1
#> 4 4 1 0.25964639 0 1 2.13580247 0 1
#> 5 5 1 0.25227459 0 1 0.25227459 0 1
#> recruitTime OStimeCal PFStimeCal
#> 1 1.234711 1.702588 1.702588
#> 2 7.971605 8.231709 8.231709
#> 3 7.442772 7.504273 7.504273
#> 4 9.159742 11.295545 9.419389
#> 5 9.945982 10.198257 10.198257
If we want to simulate only one trial,
getOneClinicalTrial
can also be used and with
getDatasetWideFormat
can be used to convert the dataset
from being displayed with transition time to displaying PFS and OS
times.
simStudy_Trans <- getOneClinicalTrial(
nPat = nPat, transitionByArm = transitionbyArm,
dropout = dropout,
accrual = accrual
)
simStudy_PFSOS <- getDatasetWideFormat(simStudy_Trans)
head(simStudy_Trans, 10)
#> id from to entry exit entryAct exitAct censAct trt
#> 1 1 0 2 0.0000000 0.32181077 5.063864 5.385675 335.59100 1
#> 2 2 0 1 0.0000000 0.44263317 8.083607 8.526241 96.83774 1
#> 3 2 1 2 0.4426332 0.70429214 8.526241 8.787899 96.83774 1
#> 4 3 0 2 0.0000000 0.03497509 4.478954 4.513929 74.19954 1
#> 5 4 0 1 0.0000000 0.19827637 5.606922 5.805199 48.06033 1
#> 6 4 1 2 0.1982764 0.93065829 5.805199 6.537580 48.06033 1
#> 7 5 0 2 0.0000000 0.06933912 9.077324 9.146663 119.07514 1
#> 8 6 0 1 0.0000000 0.44623034 8.790901 9.237131 81.78121 1
#> 9 6 1 2 0.4462303 0.44837021 9.237131 9.239271 81.78121 1
#> 10 7 0 1 0.0000000 0.63135991 8.441810 9.073170 97.36028 1
head(simStudy_PFSOS, 10)
#> id trt PFStime CensoredPFS PFSevent OStime CensoredOS OSevent
#> 1 1 1 0.32181077 0 1 0.32181077 0 1
#> 2 2 1 0.44263317 0 1 0.70429214 0 1
#> 3 3 1 0.03497509 0 1 0.03497509 0 1
#> 4 4 1 0.19827637 0 1 0.93065829 0 1
#> 5 5 1 0.06933912 0 1 0.06933912 0 1
#> 6 6 1 0.44623034 0 1 0.44837021 0 1
#> 7 7 1 0.63135991 0 1 1.69430412 0 1
#> 8 8 1 1.60671207 0 1 1.60671207 0 1
#> 9 9 1 0.22975563 0 1 0.50776145 0 1
#> 10 10 1 0.06312064 0 1 0.06312064 0 1
#> recruitTime OStimeCal PFStimeCal
#> 1 5.0638640 5.385675 5.385675
#> 2 8.0836073 8.787899 8.526241
#> 3 4.4789541 4.513929 4.513929
#> 4 5.6069222 6.537580 5.805199
#> 5 9.0773241 9.146663 9.146663
#> 6 8.7909011 9.239271 9.237131
#> 7 8.4418100 10.136114 9.073170
#> 8 0.4754946 2.082207 2.082207
#> 9 2.8876069 3.395368 3.117363
#> 10 6.6150703 6.678191 6.678191
It is also possible to generate a a study that censors all patients after a pre-specified number of events (PFS or OS) occurred.
simStudy_Trans <- getOneClinicalTrial(
nPat = nPat, transitionByArm = transitionbyArm,
dropout = dropout,
accrual = accrual
)
simStudy_PFSOS <- getDatasetWideFormat(simStudy_Trans)
head(simStudy_Trans, 10)
#> id from to entry exit entryAct exitAct censAct trt
#> 1 1 0 1 0.00000000 0.06961555 7.780312062 7.8499276 102.95744 1
#> 2 1 1 2 0.06961555 1.04718403 7.849927611 8.8274961 102.95744 1
#> 3 2 0 2 0.00000000 0.26116360 4.626272118 4.8874357 47.17874 1
#> 4 3 0 2 0.00000000 0.15075060 6.508751956 6.6595026 168.99387 1
#> 5 4 0 1 0.00000000 0.56212147 2.690053477 3.2521749 48.75687 1
#> 6 4 1 2 0.56212147 2.41915162 3.252174950 5.1092051 48.75687 1
#> 7 5 0 2 0.00000000 0.01950124 8.332294915 8.3517962 118.78556 1
#> 8 6 0 2 0.00000000 0.47629626 0.024984612 0.5012809 145.10228 1
#> 9 7 0 2 0.00000000 0.64391257 0.003990494 0.6479031 63.08757 1
#> 10 8 0 2 0.00000000 0.56831986 7.120901188 7.6892211 659.17510 1
head(simStudy_PFSOS, 10)
#> id trt PFStime CensoredPFS PFSevent OStime CensoredOS OSevent
#> 1 1 1 0.06961555 0 1 1.04718403 0 1
#> 2 2 1 0.26116360 0 1 0.26116360 0 1
#> 3 3 1 0.15075060 0 1 0.15075060 0 1
#> 4 4 1 0.56212147 0 1 2.41915162 0 1
#> 5 5 1 0.01950124 0 1 0.01950124 0 1
#> 6 6 1 0.47629626 0 1 0.47629626 0 1
#> 7 7 1 0.64391257 0 1 0.64391257 0 1
#> 8 8 1 0.56831986 0 1 0.56831986 0 1
#> 9 9 1 0.27386179 0 1 0.27386179 0 1
#> 10 10 1 0.41250249 0 1 1.15933490 0 1
#> recruitTime OStimeCal PFStimeCal
#> 1 7.780312062 8.8274961 7.8499276
#> 2 4.626272118 4.8874357 4.8874357
#> 3 6.508751956 6.6595026 6.6595026
#> 4 2.690053477 5.1092051 3.2521749
#> 5 8.332294915 8.3517962 8.3517962
#> 6 0.024984612 0.5012809 0.5012809
#> 7 0.003990494 0.6479031 0.6479031
#> 8 7.120901188 7.6892211 7.6892211
#> 9 5.236761118 5.5106229 5.5106229
#> 10 5.930290024 7.0896249 6.3427925
simStudy_40PFS <- censoringByNumberEvents(data = simStudy_PFSOS, eventNum = 40, typeEvent = "PFS")
simStudy_30POS <- censoringByNumberEvents(data = simStudy_PFSOS, eventNum = 30, typeEvent = "PFS")
simStudy_40PFS
#> id trt PFStime PFSevent OStime CensoredOS OSevent recruitTime
#> 1 2 1 0.26116360 1 0.26116360 0 1 4.626272118
#> 2 3 1 0.15075060 1 0.15075060 0 1 6.508751956
#> 3 4 1 0.56212147 1 2.41915162 0 1 2.690053477
#> 4 6 1 0.47629626 1 0.47629626 0 1 0.024984612
#> 5 7 1 0.64391257 1 0.64391257 0 1 0.003990494
#> 6 9 1 0.27386179 1 0.27386179 0 1 5.236761118
#> 7 10 1 0.41250249 1 0.89799098 1 0 5.930290024
#> 8 12 1 0.62277501 1 0.64594684 0 1 4.695528368
#> 9 13 1 0.12997017 1 0.12997017 0 1 1.509620696
#> 10 14 1 1.04040922 1 1.04040922 0 1 1.242366128
#> 11 15 1 0.02544847 1 0.02544847 0 1 4.443782684
#> 12 17 1 0.57767544 1 0.57767544 0 1 0.823651729
#> 13 18 1 0.09734062 1 0.09734062 0 1 1.893173764
#> 14 19 1 0.16208977 1 0.16208977 0 1 4.184192105
#> 15 21 1 0.14169789 1 0.14169789 0 1 5.848798379
#> 16 22 1 0.04763364 1 0.04763364 0 1 3.433677910
#> 17 23 1 0.45706380 1 0.45706380 0 1 4.143891723
#> 18 24 1 0.09314261 1 0.91309530 0 1 2.018429318
#> 19 25 1 0.56389389 1 0.56389389 0 1 3.687071947
#> 20 26 1 0.47023947 1 0.47023947 0 1 4.227757026
#> 21 27 1 0.22703896 1 0.22703896 0 1 4.133027100
#> 22 29 1 0.46661062 1 0.51297590 0 1 6.289522646
#> 23 38 2 0.15540772 1 0.15540772 0 1 1.464038296
#> 24 40 2 0.04322971 1 0.04322971 1 0 6.785051292
#> 25 41 2 0.54570637 1 0.54570637 0 1 4.364613695
#> 26 43 2 0.24034500 0 0.24034500 1 0 6.587936003
#> 27 44 2 1.63214588 1 1.63214588 0 1 1.881478205
#> 28 45 2 0.58103357 1 0.58103357 0 1 5.467244969
#> 29 54 2 0.34380339 1 0.74697844 0 1 2.132945149
#> 30 59 2 0.09644431 1 0.27138395 0 1 5.442366586
#> 31 61 2 0.45262441 1 1.01968087 0 1 5.125696822
#> 32 62 2 0.05870165 1 0.05870165 0 1 5.439043818
#> 33 65 2 0.49377546 1 0.49377546 0 1 4.180423580
#> 34 68 2 0.12736172 1 0.12736172 0 1 3.157080468
#> 35 74 2 0.07764841 0 0.07764841 1 0 6.750632599
#> 36 76 2 0.60140979 1 0.60140979 0 1 5.403354042
#> 37 79 2 0.03248963 1 0.03248963 0 1 0.871058516
#> 38 82 2 0.19592203 1 0.19592203 0 1 0.017242287
#> 39 83 2 0.06006929 1 1.21931632 0 1 3.657871913
#> 40 86 2 0.11559171 1 0.11559171 0 1 3.960323525
#> 41 88 2 0.09813191 1 1.79531539 0 1 0.935697695
#> 42 89 2 0.51809902 1 0.51809902 0 1 1.062610177
#> OStimeCal PFStimeCal
#> 1 4.8874357 4.8874357
#> 2 6.6595026 6.6595026
#> 3 5.1092051 3.2521749
#> 4 0.5012809 0.5012809
#> 5 0.6479031 0.6479031
#> 6 5.5106229 5.5106229
#> 7 6.8282810 6.3427925
#> 8 5.3414752 5.3183034
#> 9 1.6395909 1.6395909
#> 10 2.2827753 2.2827753
#> 11 4.4692312 4.4692312
#> 12 1.4013272 1.4013272
#> 13 1.9905144 1.9905144
#> 14 4.3462819 4.3462819
#> 15 5.9904963 5.9904963
#> 16 3.4813115 3.4813115
#> 17 4.6009555 4.6009555
#> 18 2.9315246 2.1115719
#> 19 4.2509658 4.2509658
#> 20 4.6979965 4.6979965
#> 21 4.3600661 4.3600661
#> 22 6.8024985 6.7561333
#> 23 1.6194460 1.6194460
#> 24 6.8282810 6.8282810
#> 25 4.9103201 4.9103201
#> 26 6.8282810 6.8282810
#> 27 3.5136241 3.5136241
#> 28 6.0482785 6.0482785
#> 29 2.8799236 2.4767485
#> 30 5.7137505 5.5388109
#> 31 6.1453777 5.5783212
#> 32 5.4977455 5.4977455
#> 33 4.6741990 4.6741990
#> 34 3.2844422 3.2844422
#> 35 6.8282810 6.8282810
#> 36 6.0047638 6.0047638
#> 37 0.9035481 0.9035481
#> 38 0.2131643 0.2131643
#> 39 4.8771882 3.7179412
#> 40 4.0759152 4.0759152
#> 41 2.7310131 1.0338296
#> 42 1.5807092 1.5807092
simStudy_30POS
#> id trt PFStime PFSevent OStime CensoredOS OSevent recruitTime
#> 1 2 1 0.26116360 1 0.26116360 0 1 4.626272118
#> 2 4 1 0.56212147 1 2.41915162 0 1 2.690053477
#> 3 6 1 0.47629626 1 0.47629626 0 1 0.024984612
#> 4 7 1 0.64391257 1 0.64391257 0 1 0.003990494
#> 5 9 1 0.26098435 0 0.26098435 1 0 5.236761118
#> 6 12 1 0.62277501 1 0.64594684 0 1 4.695528368
#> 7 13 1 0.12997017 1 0.12997017 0 1 1.509620696
#> 8 14 1 1.04040922 1 1.04040922 0 1 1.242366128
#> 9 15 1 0.02544847 1 0.02544847 0 1 4.443782684
#> 10 17 1 0.57767544 1 0.57767544 0 1 0.823651729
#> 11 18 1 0.09734062 1 0.09734062 0 1 1.893173764
#> 12 19 1 0.16208977 1 0.16208977 0 1 4.184192105
#> 13 22 1 0.04763364 1 0.04763364 0 1 3.433677910
#> 14 23 1 0.45706380 1 0.45706380 0 1 4.143891723
#> 15 24 1 0.09314261 1 0.91309530 0 1 2.018429318
#> 16 25 1 0.56389389 1 0.56389389 0 1 3.687071947
#> 17 26 1 0.47023947 1 0.47023947 0 1 4.227757026
#> 18 27 1 0.22703896 1 0.22703896 0 1 4.133027100
#> 19 38 2 0.15540772 1 0.15540772 0 1 1.464038296
#> 20 41 2 0.54570637 1 0.54570637 0 1 4.364613695
#> 21 44 2 1.63214588 1 1.63214588 0 1 1.881478205
#> 22 45 2 0.03050050 0 0.03050050 1 0 5.467244969
#> 23 54 2 0.34380339 1 0.74697844 0 1 2.132945149
#> 24 59 2 0.05537888 0 0.05537888 1 0 5.442366586
#> 25 61 2 0.37204864 0 0.37204864 1 0 5.125696822
#> 26 62 2 0.05870165 1 0.05870165 0 1 5.439043818
#> 27 65 2 0.49377546 1 0.49377546 0 1 4.180423580
#> 28 68 2 0.12736172 1 0.12736172 0 1 3.157080468
#> 29 76 2 0.09439142 0 0.09439142 1 0 5.403354042
#> 30 79 2 0.03248963 1 0.03248963 0 1 0.871058516
#> 31 82 2 0.19592203 1 0.19592203 0 1 0.017242287
#> 32 83 2 0.06006929 1 1.21931632 0 1 3.657871913
#> 33 86 2 0.11559171 1 0.11559171 0 1 3.960323525
#> 34 88 2 0.09813191 1 1.79531539 0 1 0.935697695
#> 35 89 2 0.51809902 1 0.51809902 0 1 1.062610177
#> OStimeCal PFStimeCal
#> 1 4.8874357 4.8874357
#> 2 5.1092051 3.2521749
#> 3 0.5012809 0.5012809
#> 4 0.6479031 0.6479031
#> 5 5.4977455 5.4977455
#> 6 5.3414752 5.3183034
#> 7 1.6395909 1.6395909
#> 8 2.2827753 2.2827753
#> 9 4.4692312 4.4692312
#> 10 1.4013272 1.4013272
#> 11 1.9905144 1.9905144
#> 12 4.3462819 4.3462819
#> 13 3.4813115 3.4813115
#> 14 4.6009555 4.6009555
#> 15 2.9315246 2.1115719
#> 16 4.2509658 4.2509658
#> 17 4.6979965 4.6979965
#> 18 4.3600661 4.3600661
#> 19 1.6194460 1.6194460
#> 20 4.9103201 4.9103201
#> 21 3.5136241 3.5136241
#> 22 5.4977455 5.4977455
#> 23 2.8799236 2.4767485
#> 24 5.4977455 5.4977455
#> 25 5.4977455 5.4977455
#> 26 5.4977455 5.4977455
#> 27 4.6741990 4.6741990
#> 28 3.2844422 3.2844422
#> 29 5.4977455 5.4977455
#> 30 0.9035481 0.9035481
#> 31 0.2131643 0.2131643
#> 32 4.8771882 3.7179412
#> 33 4.0759152 4.0759152
#> 34 2.7310131 1.0338296
#> 35 1.5807092 1.5807092