AHR: computes AHR under NPH assumptions and (stratified) populations
Source:vignettes/usage_AHR.Rmd
usage_AHR.Rmd
Introduction of AHR()
AHR()
provides a geometric average hazard ratio under various non-proportional hazards assumptions for either single or multiple strata studies. The piecewise exponential distribution allows a simple method to specify a distribution and enrollment pattern where the enrollment, failure and dropout rates changes over time.
Usage of AHR()
Example 1: Un-stratified population
enrollRates <- tibble(Stratum = "All",
duration = c(2, 10, 4, 4, 8),
rate = c(5, 10, 0, 3, 6))
failRates <- tibble(Stratum = "All",
duration = 1,
failRate = c(.1, .2, .3, .4),
hr = c(.9, .75, .8, .6),
dropoutRate = .001)
AHR(enrollRates = enrollRates, failRates = failRates, totalDuration = c(15, 30))
## # A tibble: 2 × 5
## Time AHR Events info info0
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 15 0.694 91.0 22.6 22.7
## 2 30 0.685 154. 37.9 38.6
Example 2: Stratified population
enrollRates <- tibble(Stratum = c(rep("Low", 2), rep("High", 3)),
duration = c(2, 10, 4, 4, 8),
rate = c(5, 10, 0, 3, 6))
failRates <- tibble(Stratum = c(rep("Low", 2), rep("High", 2)),
duration = 1,
failRate = c(.1, .2, .3, .4),
hr = c(.9, .75, .8, .6),
dropoutRate = .001)
AHR(enrollRates = enrollRates, failRates = failRates, totalDuration = c(15, 30))
## # A tibble: 2 × 5
## Time AHR Events info info0
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 15 0.733 113. 28.1 28.3
## 2 30 0.718 166. 41.3 41.5
Inner Logic of AHR()
Let’s take the un-stratified population as an example, where the enrollment rate, failure rates and dropout rates are
enrollRates <- tibble(Stratum = "All",
duration = c(2, 10, 4),
rate = c(5, 10, 0))
failRates <- tibble(Stratum = "All",
duration = 1,
failRate = c(.1, .2),
hr = c(.9, .75),
dropoutRate = .001)
ratio <- 2
totalDuration <- 30
Step 1: compute proportion in each group
Qe <- ratio / (1 + ratio)
Qc <- 1 - Qe
## The proportion of the experimental arm is 0.6666667
## The proportion of the control arm is 0.3333333
To compute the expected events over different treatment group, stratum and time period, we iterate over totalDuration
and Strata
. Since in this example, we only have one analysis time (totalDuration = 30
) and one stratum (Stratum = "All"
), we only iterate once. In one has multiple analysis time and strata, one can use a for loop and bind the results by row.
td <- totalDuration
s <- "All"
Step 2: subset the enrollment rates and failure rates by stratum.
Step 3: we calculate the enrollment rates in experimental arm and control arm, respectively.
Step 4: we update the failure rate in the control and experimental arm.
Step 5: we calculate the expected number of events in the control and experimental by eEvents_df()
.
events_c <- eEvents_df(enrollRates = enroll_c, failRates = fail_c, totalDuration = td, simple = FALSE)
events_e <- eEvents_df(enrollRates = enroll_e, failRates = fail_e, totalDuration = td, simple = FALSE)
## The expected number of events in the control arm is
## # A tibble: 3 × 3
## t failRate Events
## <dbl> <dbl> <dbl>
## 1 0 0.1 3.49
## 2 1 0.2 30.6
## 3 2 0.2 1.98
## The expected number of events in the experimental arm is
## # A tibble: 3 × 3
## t failRate Events
## <dbl> <dbl> <dbl>
## 1 0 0.09 6.31
## 2 1 0.15 57.2
## 3 2 0.15 6.86
Here the t
column is the start of period, the failRate
column is the failure rate during the period, and the Events
column is the expected events during the period.
Step 6: we combine the results together and output it.
# combine control and experimental
events <- rbind(events_c %>% mutate(Treatment = "Control"),
events_e %>% mutate(Treatment = "Experimental")) %>%
arrange(t, Treatment) %>%
ungroup() %>%
# recompute HR, events, info by period
group_by(t) %>%
summarize(Stratum = s,
info = (sum(1 / Events))^(-1),
Events = sum(Events),
HR = last(failRate) / first(failRate)) %>%
# compute info0
mutate(Time = td,
lnhr = log(HR),
info0 = Events * Qc * Qe) %>%
ungroup() %>%
group_by(Time, Stratum, HR) %>%
summarize(t = min(t),
Events = sum(Events),
info0 = sum(info0),
info = sum(info)) %>%
# pool time period together
group_by(Time) %>%
summarize(AHR = exp(sum(log(HR) * Events) / sum(Events)),
Events = sum(Events),
info = sum(info),
info0 = sum(info0))
## The overall expected number of events over the time is
## # A tibble: 1 × 5
## Time AHR Events info info0
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 30 0.763 106. 23.7 23.6
Please note that, in the output, the info
column is based on the following input.
enrollRates <- tibble(Stratum = "All",
duration = c(2, 10, 4),
rate = c(5, 10, 0))
failRates <- tibble(Stratum = "All",
duration = 1,
failRate = c(.1, .2),
hr = c(.9, .75),
dropoutRate = .001)
If the alternative hypothesis \(H_1\) is \[
\text{hr}
=
\left\{
\begin{array}{ll}
0.9 & \text{for the first 1 month} \\
0.75 & \text{afterwards},
\end{array}
\right.
\] then info = info1
, where info1
is the statistical information under \(H_1\). But notice that the above enrollRates
and failRates
is not always the \(H_1\), so we call it as info
, rather than info1
.