Package 'futility'

Title: Interim Analysis of Operational Futility in Randomized Trials with Time-to-Event Endpoints and Fixed Follow-Up
Description: Randomized clinical trials commonly follow participants for a time-to-event efficacy endpoint for a fixed period of time. Consequently, at the time when the last enrolled participant completes their follow-up, the number of observed endpoints is a random variable. Assuming data collected through an interim timepoint, simulation-based estimation and inferential procedures in the standard right-censored failure time analysis framework are conducted for the distribution of the number of endpoints--in total as well as by treatment arm--at the end of the follow-up period. The future (i.e., yet unobserved) enrollment, endpoint, and dropout times are generated according to mechanisms specified in the simTrial() function in the 'seqDesign' package. A Bayesian model for the endpoint rate, offering the option to specify a robust mixture prior distribution, is used for generating future data (see the vignette for details). Inference can be restricted to participants who received treatment according to the protocol and are observed to be at risk for the endpoint at a specified timepoint. Plotting functions are provided for graphical display of results.
Authors: Yingying Zhuang [aut], Michal Juraska [aut, cre], Doug Grove [ctb], Peter Gilbert [ctb], Alexander Luedtke [ctb], Sanne Roels [ctb], An Vandebosch [ctb]
Maintainer: Michal Juraska <mjuraska@fredhutch.org>
License: GPL-2
Version: 0.4
Built: 2024-02-14 08:01:01 UTC
Source: CRAN

Help Index


Treatment Arm-Specific Simulation-Based Completion of a Randomized Efficacy Trial with a Time-to-Event Endpoint and Fixed Follow-up Using an Interim Data-set

Description

Considers MITT data collected through an interim timepoint and generates independent time-to-event data-sets, by treatment arm, to assess the distribution of the number of treatment arm-specific endpoints at the end of the follow-up period. A Bayesian model for treatment arm-specific endpoint rates is used for generating future data (see the vignette).

Usage

completeTrial.byArm(interimData, nTrials, trtNames, N, enrollRate = NULL,
  enrollRatePeriod, eventPriorWeight, eventPriorRate,
  fixedDropOutRate = NULL, ppAnalysis = FALSE, missVaccProb = NULL,
  ppAtRiskTimePoint = NULL, fuTime, visitSchedule,
  visitSchedule2 = NULL, saveFile = NULL, saveDir = NULL,
  randomSeed = NULL)

Arguments

interimData

a data frame capturing observed MITT data at an interim timepoint that contains one row per enrolled participant in the MITT cohort and the following variables: arm (treatment arm), schedule2 (an indicator that a participant follows the visitSchedule2 schedule, e.g., participants who discontinue study product administration may remain in primary follow-up on a different schedule), entry (number of weeks since the reference date until the enrollment date), exit (number of weeks since the reference date until the trial exit date defined as the date of either infection diagnosis, dropout, or primary follow-up completion, whichever occurs first; NA for participants still in primary follow-up), last_visit_dt (number of weeks since the reference date until the last visit date), event (event indicator), dropout (dropout indicator), complete (indicator of completed follow-up), followup (indicator of being in primary follow-up). The reference date is defined as the enrollment date of the first participant. The variables entry, exit, and last_visit_dt use week as the unit of time. Month is defined as 52/12 weeks.

nTrials

the number of trials to be simulated

trtNames

a character vector of treatment labels as specified in interimData$arm determining the order of treatment arms in other input arguments

N

a numeric vector specifying the target number of enrolled participants in each treatment arm, with the arms in the same order as in trtNames

enrollRate

a treatment arm-pooled weekly enrollment rate used for completing enrollment if interimData's enrollment is incomplete. If NULL (default), the rate is calculated as the average over the last enrollRatePeriod weeks of enrollment in interimData. If equal to a numeric value, then enrollRatePeriod is ignored.

enrollRatePeriod

the length (in weeks) of the time period preceding the time of the last enrolled participant in interimData that the average weekly enrollment rate will be based on and used for completing enrollment. If NULL (default), then enrollRate must be specified.

eventPriorWeight

a numeric value in [0,1][0,1] representing a weight assigned to the prior gamma distribution of the treatment arm-specific event rates at the time when 50% of the estimated person-time at risk in each arm has been accumulated (see the vignette)

eventPriorRate

a numeric vector of treatment arm-specific prior mean incidence rates for the endpoint, expressed as numbers of events per person-year at risk, with the arms in the same order as in trtNames

fixedDropOutRate

the pre-trial assumed annual treatment arm-pooled dropout rate. If NULL (default), then the observed treatment arm-pooled dropout rate is used.

ppAnalysis

a logical value (FALSE by default) indicating whether an indicator of membership in the per-protocol cohort shall be generated based on complete MITT data. If TRUE, then interimData must include two additional variables: missVacc (an indicator of a missed vaccination) and pp (an indicator of membership in the per-protocol cohort; NA for participants with an indeterminate status).

missVaccProb

a probability that a participant misses at least one vaccination. If NULL (default) and ppAnalysis=TRUE, then missVaccProb is calculated as the sample proportion of MITT participants in interimData with a missed vaccination using the missVacc variable. If ppAnalysis=TRUE, then the indicator of a missed vaccination for participants in interimData with pp=NA and future enrolled participants is sampled from the Bernoulli distribution with probability missVaccProb.

ppAtRiskTimePoint

a minimal follow-up time (in weeks) for a participant to qualify for inclusion in the per-protocol cohort (NULL by default)

fuTime

a follow-up time (in weeks) of each participant

visitSchedule

a numeric vector of visit weeks at which testing for the endpoint is conducted

visitSchedule2

a numeric vector of visit weeks at which testing for the endpoint is conducted in a subset of participants (e.g., those who discontinue administration of the study product but remain in follow-up). If NULL (default), everyone is assumed to follow visitSchedule.

saveFile

a character string specifying an .RData file storing the output list. If NULL and saveDir is specified, the file name will be generated. If, in turn, saveFile is specified but saveDir equals NULL, then saveFile is ignored, and the output list will be returned.

saveDir

a character string specifying a path for the output directory. If supplied, the output is saved as an .RData file in the directory; otherwise the output is returned as a list.

randomSeed

seed of the random number generator for simulation reproducibility

Value

If saveDir is specified, the output list (named trialObj) is saved as an .RData file; otherwise it is returned. The output object is a list with the following components:

See Also

completeTrial.pooledArms

Examples

arm <- rep(c("C3","T1","T2"), each=250)
schedule <- rbinom(length(arm), 1, 0.01)
entry <- rpois(length(arm), lambda=60)
entry <- entry - min(entry)
last_visit_dt <- entry + runif(length(arm), min=0, max=80)
event <- rbinom(length(arm), 1, 0.01)
dropout <- rbinom(length(arm), 1, 0.02)
dropout[event==1] <- 0
exit <- rep(NA, length(arm))
exit[event==1] <- last_visit_dt[event==1] + 5
exit[dropout==1] <- last_visit_dt[dropout==1] + 5
followup <- ifelse(event==1 | dropout==1, 0, 1)
interimData <- data.frame(arm=arm, schedule2=schedule, entry=entry, exit=exit,
last_visit_dt=last_visit_dt, event=event, dropout=dropout, complete=0, followup=followup)

completeData <- completeTrial.byArm(interimData=interimData, nTrials=5,
trtNames=c("C3","T1","T2"), N=c(500,500,500), enrollRatePeriod=24, eventPriorWeight=0.5,
eventPriorRate=c(0.001,0.0004,0.0004), fuTime=80, visitSchedule=seq(0, 80, by=4),
visitSchedule2=c(0,seq(from=8,to=80,by=12)), randomSeed=9)
### alternatively, to save the .RData output file (no '<-' needed):
completeTrial.byArm(interimData=interimData, nTrials=5, trtNames=c("C3","T1","T2"),
N=c(500,500,500), enrollRatePeriod=24, eventPriorWeight=0.5,
eventPriorRate=c(0.001,0.0004,0.0004), fuTime=80, visitSchedule=seq(0, 80, by=4),
visitSchedule2=c(0,seq(from=8,to=80,by=12)), saveDir="./", randomSeed=9)

Treatment Arm-Pooled Simulation-Based Completion of a Randomized Efficacy Trial with a Time-to-Event Endpoint and Fixed Follow-up Using an Interim Data-set

Description

Considers MITT data collected through an interim timepoint and generates independent time-to-event data-sets, ignoring treatment assignments, to assess the distribution of the number of treatment arm-pooled endpoints at the end of the follow-up period. A Bayesian model for the treatment arm-pooled endpoint rate, offering the option to specify a robust mixture prior distribution, is used for generating future data (see the vignette).

Usage

completeTrial.pooledArms(interimData, nTrials, N, enrollRate = NULL,
  enrollRatePeriod = NULL, eventPriorWeight, eventPriorRate = NULL,
  fixedDropOutRate = NULL, ppAnalysis = FALSE, missVaccProb = NULL,
  ppAtRiskTimePoint = NULL, fuTime, mixture = FALSE,
  mix.weights = NULL, eventPriorWeightRobust = NULL, visitSchedule,
  visitSchedule2 = NULL, saveFile = NULL, saveDir = NULL,
  randomSeed = NULL)

Arguments

interimData

a data frame capturing observed MITT data at an interim timepoint that contains one row per enrolled participant in the MITT cohort and the following variables: arm (treatment arm), schedule2 (an indicator that a participant follows the visitSchedule2 schedule, e.g., participants who discontinue study product administration may remain in primary follow-up on a different schedule), entry (number of weeks since the reference date until the enrollment date), exit (number of weeks since the reference date until the trial exit date defined as the date of either infection diagnosis, dropout, or primary follow-up completion, whichever occurs first; NA for participants still in primary follow-up), last_visit_dt (number of weeks since the reference date until the last visit date), event (event indicator), dropout (dropout indicator), complete (indicator of completed follow-up), followup (indicator of being in primary follow-up). The reference date is defined as the enrollment date of the first participant. The variables entry, exit, and last_visit_dt use week as the unit of time. Month is defined as 52/12 weeks.

nTrials

the number of trials to be simulated

N

the total target number of enrolled participants

enrollRate

a treatment arm-pooled weekly enrollment rate used for completing enrollment if fewer than N participants were enrolled in interimData. If NULL (default), the rate is calculated as the average over the last enrollRatePeriod weeks of enrollment in interimData. If equal to a numerical value, then enrollRatePeriod is ignored.

enrollRatePeriod

the length (in weeks) of the time period preceding the time of the last enrolled participant in interimData that the average weekly enrollment rate will be based on and used for completing enrollment. If NULL (default), then enrollRate must be specified.

eventPriorWeight

a numeric value in [0,1][0,1] representing a weight assigned to the prior gamma distribution of the treatment arm-pooled event rate at the time when 50% of the estimated total person-time at risk has been accumulated (see the vignette)

eventPriorRate

a numeric value of a treatment arm-pooled prior mean incidence rate for the endpoint, expressed as the number of events per person-year at risk. If NULL (default), then use the observed rate in interimData.

fixedDropOutRate

the pre-trial assumed annual dropout rate. If NULL (default), then the observed treatment arm-pooled dropout rate is used.

ppAnalysis

a logical value (FALSE by default) indicating whether an indicator of membership in the per-protocol cohort shall be generated based on complete MITT data. If TRUE, then interimData must include two additional variables: missVacc (an indicator of a missed vaccination) and pp (an indicator of membership in the per-protocol cohort; NA for participants with an indeterminate status).

missVaccProb

a probability that a participant misses at least one vaccination. If NULL (default) and ppAnalysis=TRUE, then missVaccProb is calculated as the sample proportion of MITT participants in interimData with a missed vaccination using the missVacc variable. If ppAnalysis=TRUE, then the indicator of a missed vaccination for participants in interimData with pp=NA and future enrolled participants is sampled from the Bernoulli distribution with probability missVaccProb.

ppAtRiskTimePoint

a minimal follow-up time (in weeks) for a participant to qualify for inclusion in the per-protocol cohort (NULL by default)

fuTime

a follow-up time (in weeks) of each participant

mixture

a logical value indicating whether to use the robust mixture approach (see the vignette). If equal to FALSE (default), then mix.weights and eventPriorWeightRobust are ignored.

mix.weights

a numeric vector of length 2 representing prior weights (values in [0,1][0,1]) of the informative and the weakly informative component, respectively, of the prior gamma-mixture distribution of the treatment arm-pooled event rate. The two weights must sum up to 1. If NULL (default) and mixture=TRUE, then c(0.8,0.2) is used.

eventPriorWeightRobust

a numeric value representing the weight ww used to calculate the β\beta parameter of the weakly informative gamma distribution in the mixture prior. If NULL (default) and mixture=TRUE, then 1/2001/200 is used.

visitSchedule

a numeric vector of visit weeks at which testing for the endpoint is conducted

visitSchedule2

a numeric vector of visit weeks at which testing for the endpoint is conducted in a subset of participants (e.g., those who discontinue administration of the study product but remain in follow-up). If NULL (default), everyone is assumed to follow visitSchedule.

saveFile

a character string specifying an .RData file storing the output list. If NULL and saveDir is specified, the file name will be generated. If, in turn, saveFile is specified but saveDir equals NULL, then saveFile is ignored, and the output list will be returned.

saveDir

a character string specifying a path for the output directory. If supplied, the output is saved as an .RData file in the directory; otherwise the output is returned as a list.

randomSeed

seed of the random number generator for simulation reproducibility

Value

If saveDir is specified, the output list (named trialObj) is saved as an .RData file; otherwise it is returned. The output object is a list with the following components:

See Also

completeTrial.byArm

Examples

arm <- rep(c("C3","T1","T2"), each=250)
schedule <- rbinom(length(arm), 1, 0.01)
entry <- rpois(length(arm), lambda=60)
entry <- entry - min(entry)
last_visit_dt <- entry + runif(length(arm), min=0, max=80)
event <- rbinom(length(arm), 1, 0.01)
dropout <- rbinom(length(arm), 1, 0.02)
dropout[event==1] <- 0
exit <- rep(NA, length(arm))
exit[event==1] <- last_visit_dt[event==1] + 5
exit[dropout==1] <- last_visit_dt[dropout==1] + 5
followup <- ifelse(event==1 | dropout==1, 0, 1)
interimData <- data.frame(arm=arm, schedule2=schedule, entry=entry, exit=exit,
last_visit_dt=last_visit_dt, event=event, dropout=dropout, complete=0,
followup=followup)

completeData <- completeTrial.pooledArms(interimData=interimData, nTrials=5, N=1500,
enrollRatePeriod=24, eventPriorWeight=0.5, eventPriorRate=0.001, fuTime=80,
visitSchedule=seq(0, 80, by=4),
visitSchedule2=c(0,seq(from=8,to=80,by=12)), randomSeed=9)
### alternatively, to save the .RData output file (no '<-' needed):
completeTrial.pooledArms(interimData=interimData, nTrials=5, N=1500,
enrollRatePeriod=24, eventPriorWeight=0.5, eventPriorRate=0.001, fuTime=80,
visitSchedule=seq(0, 80, by=4),
visitSchedule2=c(0,seq(from=8,to=80,by=12)), saveDir="./", randomSeed=9)

Plot Characteristics of the Estimated Distribution of the Treatment Arm-Specific Number of Endpoints

Description

Takes the output from the completeTrial.byArm function and generates a plot describing characteristics of the estimated distribution of the treatment arm-specific number of endpoints.

Usage

plotRCDF.byArm(armLabel, trtNames, eventTimeFrame = NULL,
  eventPPcohort = FALSE, eventPriorRate, eventPriorWeight, xlim = NULL,
  xlab = NULL, ylab = NULL, fileDir)

Arguments

armLabel

a character string matching a treatment label in the arm variable in interimData that indicates the treatment arm for which the plot will be generated

trtNames

a character vector of all treatment labels listed in the same order as in trtNames in completeTrial.byArm

eventTimeFrame

a time frame within which endpoints are counted, specified in weeks as c(start, end). If NULL (default), then all endpoints are counted.

eventPPcohort

a logical value. If TRUE, only endpoints in the per-protocol cohort are counted. The default value is FALSE.

eventPriorRate

a numeric vector of treatment arm-specific prior mean incidence rates for the endpoint, expressed as numbers of events per person-year at risk, matching the order of treatment arms in trtNames

eventPriorWeight

a numeric vector in which each value represents a weight (i.e., a separate scenario) assigned to the prior gamma distribution of the treatment arm-specific event rate at the time when 50% of the estimated person-time at risk in the given arm has been accumulated

xlim

a numeric vector of the form c(xmin, xmax) for the user-specified x-axis limits. If NULL (default), then the computed range of x-axis values will be used.

xlab

a character string for the user-specified x-axis label. If NULL (default), then the label "Number of Infections in Group armLabel (n)" will be used.

ylab

a character string for the user-specified y-axis label. If NULL (default), then the label "P(Number of Infections in Group armLabel >= n ) x 100" will be used.

fileDir

a character string specifying a path for the input directory

Value

None. The function is called solely for plot generation.

See Also

completeTrial.byArm and plotRCDF.pooledArms

Examples

arm <- rep(c("C3","T1","T2"), each=250)
schedule <- rbinom(length(arm), 1, 0.01)
entry <- rpois(length(arm), lambda=60)
entry <- entry - min(entry)
last_visit_dt <- entry + runif(length(arm), min=0, max=80)
event <- rbinom(length(arm), 1, 0.01)
dropout <- rbinom(length(arm), 1, 0.02)
dropout[event==1] <- 0
exit <- rep(NA, length(arm))
exit[event==1] <- last_visit_dt[event==1] + 5
exit[dropout==1] <- last_visit_dt[dropout==1] + 5
followup <- ifelse(event==1 | dropout==1, 0, 1)
interimData <- data.frame(arm=arm, schedule2=schedule, entry=entry, exit=exit,
last_visit_dt=last_visit_dt, event=event, dropout=dropout, complete=0, followup=followup)

weights <- c(0.2, 0.4, 0.6)
for (j in 1:length(weights)){
  completeTrial.byArm(interimData=interimData, nTrials=50,
  trtNames=c("C3","T1","T2"),N=c(500,500,500),
  enrollRatePeriod=24, eventPriorWeight=weights[j], eventPriorRate=c(0.06,0.03,0.03),
  fuTime=80, visitSchedule=seq(0, 80, by=4), visitSchedule2=c(0,seq(from=8,to=80,by=12)),
  saveDir="./", randomSeed=9)
}

pdf(file=paste0("./","rcdf_byArm_arm=T1_",
"eventPriorRateC3=0.06_eventPriorRateT1=0.03_eventPriorRateT2=0.03.pdf"), width=6,
height=5)
plotRCDF.byArm(armLabel="T1", trtNames=c("C3","T1","T2"), eventPriorRate=c(0.06,0.03,0.03),
eventPriorWeight=weights, fileDir="./")
dev.off()

Plot Characteristics of the Estimated Distribution of the Treatment Arm-Pooled Number of Endpoints

Description

Takes the output from the completeTrial.pooledArms function and generates a plot describing characteristics of the estimated distribution of the treatment arm-pooled number of endpoints.

Usage

plotRCDF.pooledArms(eventTimeFrame = NULL, eventPPcohort = FALSE,
  target, power.axis = TRUE, power.TE = NULL, eventPriorRate,
  eventPriorWeight, xlim = NULL, xlab = NULL, ylab = NULL,
  power.lab = NULL, xPosLegend = 0.67, fileDir)

Arguments

eventTimeFrame

a time frame within which endpoints are counted, specified in weeks as c(start, end). If NULL (default), then all endpoints are counted.

eventPPcohort

a logical value. If TRUE, only endpoints in the per-protocol cohort are counted. The default value is FALSE.

target

a vector of target numbers of endpoints for reporting of the estimated probability that the total number of endpoints will be \ge target, with a 95% credible interval

power.axis

a logical value. If TRUE (default), then a top axis is added to the plot, showing power to reject H0H_0: TE \le 0% using a 1-sided 0.025-level Wald test if TE = power.TE throughout the trial.

power.TE

a numeric value of treatment efficacy for which power is shown on the top axis. If power.axis is FALSE, then power.TE is ignored.

eventPriorRate

a numeric value of the treatment arm-pooled prior mean incidence rate for the endpoint, expressed as the number of events per person-year at risk

eventPriorWeight

a numeric vector in which each value represents a weight (i.e., a separate scenario) assigned to the prior gamma distribution of the treatment arm-pooled event rate at the time when 50% of the estimated total person-time at risk has been accumulated

xlim

a numeric vector of the form c(xmin, xmax) for the user-specified x-axis limits. If NULL (default), then the computed range of x-axis values will be used.

xlab

a character string for the user-specified x-axis label. If NULL (default), then the label "Total Number of Infections (n)" will be used.

ylab

a character string for the user-specified y-axis label. If NULL (default), then the label "P( Total Number of Infections >= n ) x 100" will be used.

power.lab

a character string for the user-specified power-axis label. If NULL (default), then the label "Power for TE = power.TE (x 100)" will be used.

xPosLegend

a numeric value in [0,1][0,1] (0.67 by default) specifying the x-coordinate for the position of the legend

fileDir

a character string specifying a path for the input directory

Value

None. The function is called solely for plot generation.

See Also

completeTrial.pooledArms and plotRCDF.byArm

Examples

arm <- rep(c("C3","T1","T2"), each=250)
schedule <- rbinom(length(arm), 1, 0.01)
entry <- rpois(length(arm), lambda=60)
entry <- entry - min(entry)
last_visit_dt <- entry + runif(length(arm), min=0, max=80)
event <- rbinom(length(arm), 1, 0.01)
dropout <- rbinom(length(arm), 1, 0.02)
dropout[event==1] <- 0
exit <- rep(NA, length(arm))
exit[event==1] <- last_visit_dt[event==1] + 5
exit[dropout==1] <- last_visit_dt[dropout==1] + 5
followup <- ifelse(event==1 | dropout==1, 0, 1)
interimData <- data.frame(arm=arm, schedule2=schedule, entry=entry, exit=exit,
last_visit_dt=last_visit_dt, event=event, dropout=dropout, complete=0,
followup=followup)

weights <- c(0.2, 0.4, 0.6)
for (j in 1:length(weights)){
  completeTrial.pooledArms(interimData=interimData, nTrials=50, N=1500, enrollRatePeriod=24,
  eventPriorWeight=weights[j], eventPriorRate=0.06, fuTime=80, visitSchedule=seq(0, 80, by=4),
  visitSchedule2=c(0,seq(from=8,to=80,by=12)), saveDir="./", randomSeed=9)
}

pdf(file=paste0("./","rcdf_pooled_eventPriorRate=",0.06,".pdf"), width=6, height=5)
plotRCDF.pooledArms(target=c(60,30), power.axis=FALSE, eventPriorRate=0.06,
eventPriorWeight=weights, fileDir="./")
dev.off()