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))

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))

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
cat("The proportion of the experimental arm is ", Qe, "\n")
cat("The proportion of the control arm is ", Qc, "\n")

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)
cat("The expected number of events in the control arm is \n")
events_c

cat("The expected number of events in the experimental arm is \n")
events_e

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))
cat("The overall expected number of events over the time is \n")
events

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.



keaven/gsDesign2 documentation built on Oct. 13, 2022, 8:42 p.m.