For users, it may be useful to know both the expected drift at the jth analysis and the expected drift between analyses to get there.
This could be helpful to clarify in the vignette on CP as well so that users are not including a future drift parameter that ends up requiring nearly all information between analyses to come from essentially a single group.
I provide sample functions below for ease of reference at a later date.
#' Computation of non-constant incremental natural parameter based on cumulative natural parameter.
#'
#' @details
#' We assume that \eqn{\theta_i, i = 1, ..., K} are the cumulative natural parameters
#' and \eqn{\delta_i, i = 1, ..., K} are the incremental natural parameters.
#' We assume that the analysis occur at information fractions \eqn{t_i, i = 1, ..., K}.
#' We assume that the information available at \eqn{t_i} is given by \eqn{I_i}.
#'
#' Then the B-value at time \eqn{t_j} is given by \eqn{B_j = \theta_j I_j^{1/2} }.
#' We assume the relationship between analyses for sequential B-values is linear.
#' Thus, the B-value at time \eqn{t_j} can be expressed in terms of the information differences
#' and the incremental natural parameters \delta_i as
#' \deqn{E(B_j) = \delta_1 I_1^{1/2} + \sum_{k=i+1}^j \delta_k (I_{k} - I_{k-1})^{1/2})}
#' The value of $\delta_j, j > i$ can be computed sequentially after $\delta_1 = \theta_1$ as
#' \deqn{\delta_j = \frac{ \theta_j I_j^{1/2} - \theta_1 I_1^{1/2} +
#' \sum_{k=i+1}^{j-1} \delta_k (I_{k} - I_{k-1})^{1/2} }{(I_j - I_{j-1})^{1/2}}}
#' where the summand from $k=i+1$ to $j-1$ is 0 if $j=i+1$.
#'
#' @param theta A vector of j-i+1, which specifies the natural parameter for treatment effect.
#' The first element of `theta` is the treatment effect of an interim analysis i.
#' The second element of `theta` is the treatment effect of an interim analysis i+1.
#' ...
#' The last element of `theta` is the treatment effect of a future analysis j.
#' @param t A vector of j-i+1, which specifies the information fraction under the treatment effect `theta`.
#' @param info A vector of j-i+1, which specifies the statistical information under the treatment effect `theta`.
#' @return A vector of j-i+1, which specifies the incremental natural parameter for treatment effect.
#' @noRd
#'
#' @examples
#' library(gsDesign2)
#' library(dplyr)
#' library(mvtnorm)
#' # Example 1 ----
#' # Calculate the incremental natural parameters when the cumulative drift is the same at all analyses
#' # assuming that the cumulative drift is -log(0.7) based on a survival outcome with hazard ratio 0.7
#' # The incremental drift should decrease at each subsequent analysis.
#' # We provide both the delta and the transformed hazard rate between analyses.
#' delta <- theta_cum_to_inc(theta = c(-log(.7), -log(.7), -log(.7)),
#' t = c(0.5, 0.75, 1),
#' info = c(50, 75, 100))
#' delta
#' exp(-delta)
#'
#' # Example 2 ----
#' # Calculate the incremental natural parameters when the cumulative drift
#' # is improving from a detrimental effect, to a positive effect, to a very positive effect.
#' # The delta starts negative and grows more positive.
#' delta <- theta_cum_to_inc(theta = c(-log(1.1), -log(.8), -log(.6)),
#' t = c(0.5, 0.75, 1),
#' info = c(50, 75, 100))
#' delta
#' exp(-delta)
theta_cum_to_inc <- function(theta, t, info){
# check that theta, t, and info are all the same length
if(length(theta) != length(t) | length(theta) != length(info)){
stop("The inputs theta, t, and info must all be the same length")
}
# check that t is increasing and between 0 and 1
if(any(diff(t) <= 0) | any(t < 0) | any(t > 1)){
stop("The input t must be increasing and between 0 and 1")
}
# Compute the incremental drift parameters delta
delta <- numeric(length(theta))
delta[1] <- theta[1]
if (length(theta) > 1) {
delta[2] <- (theta[2] * sqrt(info[2]) - theta[1] * sqrt(info[1])) / sqrt(diff(info[1:2]))
if (length(theta) > 2) {
for (j in 3:length(theta)) {
delta[j] <- (theta[j] * sqrt(info[j]) - theta[1] * sqrt(info[1]) -
sum(delta[2:(j-1)] * sqrt(diff(info[2:j])))) / sqrt(diff(info[(j-1):j]))
}
}
}
return(delta)
}
#' Computation of cumulative natural parameter based on incremental natural parameter.
#'
#' @details
#' This is the reverse transformation of \code{theta_cum_to_inc}.
#' We assume that \eqn{\delta_i, i = 1, ..., K} are the incremental natural parameters
#' and \eqn{\theta_i, i = 1, ..., K} are the cumulative natural parameters.
#' We assume that the analyses occur at information fractions \eqn{t_i, i = 1, ..., K}.
#' We assume that the information available at \eqn{t_i} is given by \eqn{I_i}.
#'
#' The B-value at time \eqn{t_j} is:
#' \deqn{E(B_j) = \delta_1 I_1^{1/2} + \sum_{k=2}^j \delta_k (I_{k} - I_{k-1})^{1/2}}
#'
#' Since \eqn{E(B_j) = \theta_j I_j^{1/2}}, the cumulative natural parameter is recovered as:
#' \deqn{\theta_j = \frac{\delta_1 I_1^{1/2} + \sum_{k=2}^j \delta_k (I_{k} - I_{k-1})^{1/2}}{I_j^{1/2}}}
#'
#' @param delta A vector of j-i+1, which specifies the incremental natural parameter for treatment effect.
#' The first element of `delta` is the treatment effect at the first analysis.
#' Subsequent elements are the incremental treatment effects over each interval.
#' @param t A vector of j-i+1, which specifies the information fraction under the treatment effect.
#' @param info A vector of j-i+1, which specifies the statistical information.
#' @return A vector of j-i+1, which specifies the cumulative natural parameter for treatment effect.
#' @noRd
#'
#' @examples
#' library(gsDesign2)
#' library(dplyr)
#' # Example 1 ----
#' # Round-trip: cumulative -> incremental -> cumulative
#' theta_orig <- c(-log(.7), -log(.7), -log(.7))
#' info <- c(50, 75, 100)
#' t <- c(0.5, 0.75, 1)
#' delta <- theta_cum_to_inc(theta = theta_orig, t = t, info = info)
#' theta_recovered <- theta_inc_to_cum(delta = delta, t = t, info = info)
#' (all.equal(theta_orig, theta_recovered))
#'
#' # Example 2 ----
#' # Given incremental HRs, compute cumulative theta
#' delta <- c(-log(1.0), -log(0.7), -log(0.65))
#' theta <- theta_inc_to_cum(delta = delta, t = c(0.5, 0.75, 1), info = c(50, 75, 100))
#' theta
#' exp(-theta) # cumulative HR at each analysis
theta_inc_to_cum <- function(delta, t, info){
# check that delta, t, and info are all the same length
if(length(delta) != length(t) | length(delta) != length(info)){
stop("The inputs delta, t, and info must all be the same length")
}
# check that t is increasing and between 0 and 1
if(any(diff(t) <= 0) | any(t < 0) | any(t > 1)){
stop("The input t must be increasing and between 0 and 1")
}
# Compute the cumulative drift parameters theta
theta <- numeric(length(delta))
theta[1] <- delta[1]
if (length(delta) > 1) {
for (j in 2:length(delta)) {
B_j <- delta[1] * sqrt(info[1]) + sum(delta[2:j] * sqrt(diff(info[1:j])))
theta[j] <- B_j / sqrt(info[j])
}
}
return(theta)
}
For users, it may be useful to know both the expected drift at the jth analysis and the expected drift between analyses to get there.
This could be helpful to clarify in the vignette on CP as well so that users are not including a future drift parameter that ends up requiring nearly all information between analyses to come from essentially a single group.
I provide sample functions below for ease of reference at a later date.