Skip to contents
library(tibble)
library(dplyr)
#library(gsDesign2)
devtools::load_all()

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.

enroll <- enrollRates %>% filter(Stratum == s)
fail <- failRates %>% filter(Stratum == s)

Step 3: we calculate the enrollment rates in experimental arm and control arm, respectively.

enroll_c <- enroll %>% mutate(rate = rate * Qc)
enroll_e <- enroll %>% mutate(rate = rate * Qe)

Step 4: we update the failure rate in the control and experimental arm.

fail_c <- fail
fail_e <- fail %>% mutate(failRate = failRate * hr)

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.