This R Markdown document provides an example for planning a trial with a survival endpoint using rpact thereby illustrating the different ways of entering recruitment schemes. It also demonstrates the use of the survival simulation function.

**First, load the rpact package**

```
library(rpact)
packageVersion("rpact") # version should be version 2.0.5 or later
```

`## [1] '3.3.1'`

A survival trial is planned to be performed with one interim stage and using an O’Brien & Fleming type \(\alpha\)-spending approach at \(\alpha = 0.025\). The interim is planned to be performed after half of the necessary events were observed. It is assumed that the median survival time is 18 months in the treatment group, and 12 months in the control. We assume that the drop-out rate is 5% after 1 year and the drop-out time is exponentially distributed.

The patients should be recruited within 12 months assuming uniform accrual. We assume an additional follow-up time of 12 months, i.e., the study should be conducted within 2 years. We also assume the survival time to be exponentially distributed.

In this simplest example, accrual and follow-up time needs to be specified and the necessary number of events and patients (total and per month) in order to reach power 90% with the assumed median survival times will be calculated.

The effect size is defined in terms of `lambda1`

and `lambda2`

(you can
also specify `lambda2`

and `hazardRatio`

) and the function `getLambdaByMedian()`

is used (for `lambda2`

the direct calculation is illustrated):

```
<- getDesignGroupSequential(kMax = 2, typeOfDesign = "asOF", beta = 0.1)
dGS
<- getSampleSizeSurvival(dGS,
x1 lambda1 = getLambdaByMedian(18), lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = 12, followUpTime = 12
)kable(summary(x1))
```

**Sample size calculation for a survival endpoint**

Sequential analysis with a maximum of 2 looks (group sequential design), overall significance level 2.5% (one-sided). The sample size was calculated for a two-sample logrank test, H0: hazard ratio = 1, H1: treatment lambda(1) = 0.039, control lambda(2) = 0.058, accrual time = 12, accrual intensity = 38.9, dropout rate(1) = 0.05, dropout rate(2) = 0.05, dropout time = 12, power 90%.

Stage | 1 | 2 |
---|---|---|

Information rate | 50% | 100% |

Efficacy boundary (z-value scale) | 2.963 | 1.969 |

Overall power | 0.2525 | 0.9000 |

Expected number of subjects | 467.3 | |

Number of subjects | 467.3 | 467.3 |

Cumulative number of events | 128.3 | 256.5 |

Expected study duration | 21.3 | |

Cumulative alpha spent | 0.0015 | 0.0250 |

One-sided local significance level | 0.0015 | 0.0245 |

Efficacy boundary (t) | 0.593 | 0.782 |

Exit probability for efficacy (under H0) | 0.0015 | |

Exit probability for efficacy (under H1) | 0.2525 |

Legend:

*(t)*: treatment effect scale

We conclude that a maximum number of 257 events
needs to be observed to reach 90% power. Under the assumed accrual and
follow-up time (and the median survival times) this number of events are
expected to be observed if 468 subjects are
observed at the end of the trial. This corresponds to about
39
( = `accrualIntensity`

) patient per month to be accrued.

The interim analysis is performed after 128.3 events (which in practice needs to be rounded up or down). This number is expected to be observed at analysis time 13.14.

Note that in this case you can also enter the accrual time as
`accrualTime = c(0,12)`

and so `accrualTime = 12`

is just a shortcut (see
below).

Assume that accrual stops after 16 months with 25 patients per month, i.e., after 400 patients were recruited. We now can estimate the necessary follow-up time such that 257 events will be observed at the end of the trial.

There are two ways of defining the situation of *given maximum number of
subjects*: You can either specify `accrualTime`

and `maxNumberOfSubjects`

directly; or you specify `accrualTime`

and `accrualIntensity`

.

In both cases, at given accrual time and number of patients, the follow-up time is calculated.

This is the code and the output for the first case:

```
<- getSampleSizeSurvival(dGS,
x2 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = c(0, 16), accrualIntensity = 25
)
ceiling(x2$maxNumberOfSubjects)
```

`## [1] 400`

`$followUpTime x2`

`## [1] 15.96226`

`$analysisTime x2`

```
## [,1]
## [1,] 16.82864
## [2,] 31.96226
```

This is the code and the output for the second case:

```
<- getSampleSizeSurvival(dGS,
x2 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = c(0, 16), maxNumberOfSubjects = 400
)
$accrualIntensity x2
```

`## [1] 25`

`$followUpTime x2`

`## [1] 15.96226`

`$analysisTime x2`

```
## [,1]
## [1,] 16.82864
## [2,] 31.96226
```

Note that for these two cases entering the accrual time in the form of `c(0,16)`

is mandatory, i.e., you cannot enter just the end of accrual which was the
shortcut before.

Alternatively, you might enter the `accrualTime`

as a list in the form

```
<- list(
atList "0 - <16" = 25
)
```

and then enter `accrualTime = atList`

in `getSampleSizeSurvival()`

:

```
<- getSampleSizeSurvival(dGS,
x2 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = atList
)
$accrualIntensity x2
```

`## [1] 25`

`$followUpTime x2`

`## [1] 15.96226`

`$analysisTime x2`

```
## [,1]
## [1,] 16.82864
## [2,] 31.96226
```

Assume now that 25 patients can be recruited each month and that there is
uniform accrual. We now want to estimate the necessary accrual time if
the *planned follow-up time is given* and equal to 12 as before.

Here the end of accrual and the number of patients is calculated at given follow-up time and absolute accrual intensity:

```
<- getSampleSizeSurvival(dGS,
x3 hazardRatio = 2 / 3, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = 0, accrualIntensity = 25, followUpTime = 12
)
ceiling(x3$maxNumberOfSubjects)
```

`## [1] 435`

`$accrualTime x3`

`## [1] 17.38334`

`$analysisTime x3`

```
## [,1]
## [1,] 16.79806
## [2,] 29.38334
```

This case illustrates how the accrual of subjects can be entered if there is piecewise accrual over predefined intervals where it is assumed that accrual within the intervals is uniform.

For example, assume that in the first 3 months 15 patients, in the second 3 months 20 patients, and after 6 months 25 patients per month can be accrued.

If the follow-up time at given number of patients is to be calculated (Section
1.2), it is simply to enter
`accrualTime = c(0, 3, 6, 16)`

and `accrualIntensity = c(15, 20, 25)`

as follows
(`maxNumberOfSubjects`

will be calculated):

```
<- getSampleSizeSurvival(dGS,
x4 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = c(0, 3, 6, 16), accrualIntensity = c(15, 20, 25)
)
ceiling(x4$maxNumberOfSubjects)
```

`## [1] 355`

`$followUpTime x4`

`## [1] 23.60973`

`$analysisTime x4`

```
## [,1]
## [1,] 18.83368
## [2,] 39.60973
```

Alternatively, you can enter

```
<- list(
atList "0 - < 3" = 15,
"3 - < 6" = 20,
"6 - <= 16" = 25
)
```

and run

```
<- getSampleSizeSurvival(dGS,
x4 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = atList
)
ceiling(x4$maxNumberOfSubjects)
$followUpTime
x4$analysisTime x4
```

If `maxNumberOfSubjects`

is specified, the corresponding list definition is as
follows:

```
<- list(
atList "0 - < 3" = 15,
"3 - < 6" = 20,
"6 - Inf" = 25
)
```

and

```
<- getSampleSizeSurvival(dGS,
x4 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = atList, maxNumberOfSubjects = 355
)
ceiling(x4$accrualTime)
$followUpTime
x4$analysisTime x4
```

does the job.

If the follow-up time is given and the end of accrual is to be calculated (Section 1.3), this can be achieved as follows:

```
<- getSampleSizeSurvival(dGS,
x5 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
accrualTime = c(0, 3, 6), accrualIntensity = c(15, 20, 25), followUpTime = 12
)
ceiling(x5$maxNumberOfSubjects)
```

`## [1] 421`

`$accrualTime x5`

`## [1] 3.00000 6.00000 18.61383`

`$analysisTime x5`

```
## [,1]
## [1,] 18.28469
## [2,] 30.61383
```

Assume that the study is planned with 257 events and 400 patients under the assumptions that accrual stops after 16 months with 25 patients per month and the staggered patient entry from above. We now want to verify by simulation the correctness of the results obtained by the analytical formulae.

For this, we first use the function `getPowerSurvival()`

in order to obtain
the test characteristics if the study is performed with 257 events. The
analysis time is obtained by the analytical formulae and we verify that the
power is indeed exceeding 90% (note that we have to specify `directionupper = FALSE`

in order to indicate that \(p\)-values are getting small for *negative* values of
the test statistics, i.e., for observed hazard ratios smaller than 1):

```
<- getPowerSurvival(dGS,
y3 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
accrualTime = c(0, 3, 6, 16), accrualIntensity = c(15, 20, 25),
maxNumberOfEvents = 257, directionUpper = FALSE
)$analysisTime y3
```

```
## [,1]
## [1,] 18.85699
## [2,] 39.74904
```

`$overallReject y3`

`## [1] 0.9005251`

Practically the same result is obtained with the simulation function
`getSimulationSurvival()`

(note that `plannedEvents = c(129,257)`

needs to be specified in the simulation tool instead of
`maxNumberOfEvents = 257`

in the power calculation:

```
<- getSimulationSurvival(dGS,
z3 lambda1 = log(2) / 18, lambda2 = log(2) / 12,
dropoutRate1 = 0.05, dropoutRate2 = 0.05, dropoutTime = 12,
maxNumberOfIterations = 10000,
accrualTime = c(0, 3, 6, 16), accrualIntensity = c(15, 20, 25),
plannedEvents = c(129, 257), directionUpper = FALSE, seed = 12345
)$analysisTime z3
```

```
## [,1]
## [1,] 18.91939
## [2,] 39.63640
```

`$overallReject z3`

`## [1] 0.9054`

Assume now that a sample size increase up to a ten-fold of the originally
planned number of events is foreseen. Conditional power 90% *based on the
observed hazard ratios* is used to increase the number of events. We can
now assess by simulation the magnitude of power increase when using the
appropriate method.

Note that we have to make sure that enough subjects are used in the simulation.
For this, we set `maxNumberOfSubjects = 2000`

and no drop-outs.

Since we perform a data driven sample size recalculation (SSR), we define an inverse normal design with the same parameters as the original group sequential design:

`<- getDesignInverseNormal(kMax = 2, typeOfDesign = "asOF", beta = 0.1) dIN `

The following code simulates the SSR with conditional power 90% under the
observed hazard ratio. `minNumberOfEventsPerStage = c(NA,128)`

,
and `maxNumberOfEventsPerStage = 10*c(NA,128)`

defines:

- no sample size decrease
- up to a 10 fold increase of number of events for the final stage.

This is compared with the situation without SSR:

```
# Without SSR
<- getPowerSurvival(dIN,
z0
```