Skip to content

Commit

Permalink
conditional power vignette added
Browse files Browse the repository at this point in the history
keaven committed Mar 26, 2024
1 parent 9e8ea3c commit beb2957
Showing 3 changed files with 178 additions and 0 deletions.
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
@@ -142,6 +142,7 @@ articles:
- GentleIntroductionToGSD
- gsDesignPackageOverview
- SpendingFunctionOverview
- ConditionalPowerPlot
- nNormal
- hGraph
- GraphicalMultiplicity
166 changes: 166 additions & 0 deletions vignettes/ConditionalPowerPlot.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: "Conditional Power and Conditional Error"
output: rmarkdown::html_vignette
bibliography: gsDesign.bib
vignette: >
%\VignetteIndexEntry{Conditional Power and Conditional Error}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---

```{r, include=FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
dev = "ragg_png",
dpi = 96,
fig.retina = 1,
fig.width = 7.2916667,
fig.asp = 0.618,
fig.align = "center",
out.width = "80%"
)
options(width = 58)
```

## Introduction

```{r, echo=FALSE, message=FALSE, warning=FALSE}
library(gsDesign)
library(tidyr)
library(knitr)
library(tibble)
```

We provide a simple plot of conditional power at the time of interim analysis.
While group sequential boundaries should be designed to be the primary decision boundaries,
conditional power evaluations can be useful supportive information.

## Design

We consider the default design from `gsSurv()`, only altering the targeted hazard ratio to `hr = 0.7`, trial duration of `T = 36` and minimum follow-up of `minfup = 24`. This implies expected enrollment duration of 12 months at a constant rate.
We note that the expected interim analysis timing leaves enough time for a data monitoring committee (DMC) to review and make recommendations to the trial sponsor between analyses.
We use the `toInteger()` function to round sample size and event counts to appropriate integers resulting in a slightly larger power (90.05% versus the targeted 90%) and slightly altered interim timing (117/353 = 0.3314, 235/353 = 0.6657) compared to plan (0.3333, 0.6667).

```{r}
design <- gsSurv(hr = 0.7, lambdaC = log(2) / 12, minfup = 24, T = 36) %>% toInteger()
design %>% gsBoundSummary()
```

We also provide a textual summary.

```{r, results = 'asis'}
cat(design %>% summary())
```

## Update design at time of interim analysis

Assume when the first interim is performed, there are 125 instead of the planned 117 endpoints included in the analysis.
We update the bounds as follows:

```{r}
update <- gsDesign(
k = design$k,
test.type = design$test.type,
alpha = design$alpha,
beta = design$beta,
sfu = design$upper$sf,
sfupar = design$upper$param,
sfl = design$lower$sf,
sflpar = design$lower$param,
n.I = c(117, design$n.I[2:3]),
maxn.IPlan = design$n.I[design$k],
delta = design$delta,
delta1 = design$delta1,
delta0 = design$delta0
)
gsBoundSummary(
update,
deltaname = "HR",
logdelta = TRUE,
Nname = "Events",
digits = 4,
ddigits = 2,
tdigits = 1,
exclude = c(
"B-value", "CP", "CP H1", "PP",
paste0("P(Cross) if HR=", round(c(design$hr0, design$hr), digits = 2))
)
)
```

## Testing and conditional power

We assume an interim p-value of 0.04, one-sided.
This does not come close to the first efficacy or futility bound above.
However, it is a trend in the right direction.

```{r}
# Nominal 1-sided p-value
p <- 0.04
```

This translates to a first order approximation of the Cox regression estimate with the @Schoenfeld1981 approximation:

```{r}
zn2hr(-qnorm(p), n = update$n.I[1])
```
Typically, conditional power is reported based on 3 different assumptions about the future treatment effect:

1) The observed HR; here we base this on the above approximation.
2) No treatment effect; this translates to conditional error.
3) The originally targeted treatment effect in the design.

These are displayed below, translated to the hazard ratio scale:

```{r}
cp <- gsCP(x = update, i = 1, zi = -qnorm(p))
# 3 treatment effects as outlined above
# design$ratio is the experimental:control randomization ratio
exp(-cp$theta * sqrt((1 + design$ratio)^2 / design$ratio))
```

Now we display the probability of crossing an efficacy boundary before a futility boundary conditional on the above observed p-value at the first interim analysis from the above call to `gsCP()`.
The columns of the resulting matrix correspond to the above treatment effects.
The rows correspond to the second interim and final analyses.
Adding the numbers in the first column, we get a conditional power of `r round(sum(cp$upper$prob[,1]),3)` for the treatment effect observed at the first interim.
The third column yields a conditional power of `r round(sum(cp$upper$prob[,3]),3)` for the originally targeted hazard ratio of `r design$hr`.
Finally, the second column yields a conditional error under the assumption of a future hazard ratio of 1 (no underlying treatment effect) of
`r round(sum(cp$upper$prob[,2]), 3)`.
This could be used with the conditional error method of @muller2004general to adapt the design for endpoints other than the time-to-event example used here (e.g., a binary outcome).

```{r}
cp$upper$prob
```

We demonstrate a conditional power plot that may be of some use.
We will assume a wide range of potential underlying hazard ratios for future events.

```{r}
hr <- seq(.6, 1.1, .01)
```

We compute conditional probabilities based on the observed interim 1 p-value over this range:

```{r}
# Translate hazard ratio to standardized effect size
theta <- -log(hr) * sqrt(design$ratio / (1 + design$ratio)^2)
cp <- gsCP(x = update, i = 1, zi = -qnorm(p), theta = theta)
```

Finally, we plot conditional power as a function of future HR.
Note the use of the power plot option for the **gsDesign** plot function.
The `offset = 1` argument changes the legend to be labeled with "Future Analysis" 2 and 3.
The solid black line shows the conditional probability of crossing any future bound prior to crossing a lower bound.
In general, black lines on this plot will show the cumulative conditional probability of crossing an efficacy bound prior to crossing a lower bound by the time of any given future analysis by different underlying treatment effect assumptions.
The red lines show 1 minus the cumulative conditional probability of crossing a lower bound prior to crossing an efficacy bound by any given future analysis by different underlying treatment effect (HR) assumptions.

```{r}
plot(cp, xval = hr, xlab = "Future HR", ylab = "Conditional Power/Error",
main="Conditional probability of crossing future bound", offset = 1)
```



## References
11 changes: 11 additions & 0 deletions vignettes/gsDesign.bib
Original file line number Diff line number Diff line change
@@ -187,6 +187,17 @@ @article{MaurerBretz2013
pages = {311--320}
}

@article{muller2004general,
title={A general statistical principle for changing a design any time during the course of a trial},
author={M{\"u}ller, Hans-Helge and Sch{\"a}fer, Helmut},
journal={Statistics in medicine},
volume={23},
number={16},
pages={2497--2508},
year={2004},
publisher={Wiley Online Library}
}

@book{PLWBook,
author = {Michael A. Proschan and K. K. Gordon Lan and Janet Turk Wittes},
title = {Statistical Monitoring of Clinical Trials: A Unified Approach},

0 comments on commit beb2957

Please sign in to comment.