| Title: | Harm Boundaries for Clinical Trials |
|---|---|
| Description: | The harmBounds package calculates stopping probabilities, defines stopping boundaries and generates plots for safety monitoring using an event based approach. |
| Authors: | Lukas Bütikofer [aut, cre] (ORCID: <https://orcid.org/0000-0002-0801-746X>) |
| Maintainer: | Lukas Bütikofer <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 2.0.0 |
| Built: | 2026-09-25 14:42:31 UTC |
| Source: | https://github.com/CTU-Bern/harmBounds |
Plot absolute stopping probabilities
absstopPlot(harmbound)absstopPlot(harmbound)
harmbound |
harmbounds objects as generated using the getHarmBound function |
barplot with stopping probabilities under H0 and optionally H1
harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5,pH1=c(0.6,0.7,0.8)) absstopPlot(harmbound)harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5,pH1=c(0.6,0.7,0.8)) absstopPlot(harmbound)
Convert the proportion of events in the treatment arms to risk differences and ratios (and vice versa)
convertRisks( eprop = NULL, etotal = NULL, rd = NULL, rr = NULL, or = NULL, r0 = NULL, n0, n1 = n0 )convertRisks( eprop = NULL, etotal = NULL, rd = NULL, rr = NULL, or = NULL, r0 = NULL, n0, n1 = n0 )
eprop |
proportion of events in treatment arm |
etotal |
total number of events |
rd |
risk difference |
rr |
risk ratio |
or |
odds ratio |
r0 |
risk in the control arm |
n0 |
number of patients in the control arm |
n1 |
number of patients in the treatment arm |
vector with risks in control and treatment arm (r0, r1), the risk difference (rd), risk ratio (rr) and odds ratio (or)
convertRisks(eprop=0.5,etotal=100,n0=200) convertRisks(eprop=0.6,etotal=100,n0=200) convertRisks(rr=1.5,n0=200,r0=0.2)convertRisks(eprop=0.5,etotal=100,n0=200) convertRisks(eprop=0.6,etotal=100,n0=200) convertRisks(rr=1.5,n0=200,r0=0.2)
Plot cumulative stopping probabilities
cumstopPlot(harmbound)cumstopPlot(harmbound)
harmbound |
harmbounds objects as generated using the getHarmBound function |
barplot with cumulative stopping probabilities under H0 and optionally H1
harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5,pH1=c(0.6,0.7,0.8)) cumstopPlot(harmbound)harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5,pH1=c(0.6,0.7,0.8)) cumstopPlot(harmbound)
Find stopping boundary via binomial or beta-binomial distribution. For the latter, the overdispersion factor (or design effect) by which the variance exceeds the regular binomial variance is printed.
findbound( n, alpha_test = 0.025, pH0 = 0.5, alternative = "greater", icc = NULL )findbound( n, alpha_test = 0.025, pH0 = 0.5, alternative = "greater", icc = NULL )
n |
total number of events |
alpha_test |
nominal alpha for the binomial test |
pH0 |
proportion of events in the experimental arm under the null hypothesis, typically based on randomization ratio (e.g. 0.5 for a 1:1 randomization) |
alternative |
direction of alternative, "less" or "greater" |
icc |
intraclass correlation if there is more than one event per patient |
number of events in the experimental group that would lead to a stopping
findbound(n=20, alpha_test=0.025, pH0 = 0.5, alternative="greater") findbound(n=20, alpha_test=0.025, pH0 = 0.5, alternative="less")findbound(n=20, alpha_test=0.025, pH0 = 0.5, alternative="greater") findbound(n=20, alpha_test=0.025, pH0 = 0.5, alternative="less")
Exactly one of alpha_total or power have to be specified. The power requires the specification of an alternative via one of pH1, rrH1, orH1 or rdH1.
getAlphaPerTest( nevents, alpha_total = NULL, power = NULL, pH0 = 0.5, alpha.interval = c(10^(-10), 1), maxevents = NULL, icc = NULL, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL, ... )getAlphaPerTest( nevents, alpha_total = NULL, power = NULL, pH0 = 0.5, alpha.interval = c(10^(-10), 1), maxevents = NULL, icc = NULL, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL, ... )
nevents |
vector with number of events at which an interim analysis is done |
alpha_total |
target family-wise type I error |
power |
target power at the specified alternative |
pH0 |
proportion of events in the treatment arm under the null hypothesis, typically based on randomization ratio (e.g. 0.5 for a 1:1 randomization) |
alpha.interval |
Range for test-wise alpha, c(10^(-10),0.05) by default |
maxevents |
optional maximum number of events expected for the trial (over both arms), used to calculate the expected number of events |
icc |
intraclass correlation if there is more than one event per patient |
pH1 |
optional alternative, numeric vector, proportion of events in the treatment arm |
rrH1 |
alternative specification of alternative as risk ratio (treatment / control) |
orH1 |
alternative specification of alternative as odds ratio (treatment / control). Requires the control proportion (r0). |
rdH1 |
alternative specification of alternative as risk difference (treatment - control). Requires the control proportion (r0). |
r0 |
risk in the control arm. Required if the alternative is given as risk difference or odds ratio. |
... |
input for backward compatibility |
If there are several events per patient, the intraclass correlation coefficient has to be given and a beta-binomial framework is used.
Test-wide alpha
#Control overall family-wise type I error: apt<-getAlphaPerTest(nevents = c(10,50,100), alpha_total = 0.05, pH0 = 0.5) apt getHarmBound(nevents = c(10,50,100),alpha_test = apt, pH0 = 0.5) #Control power assuming 80% of events in expermintal arm apt<-getAlphaPerTest(nevents = c(10,50,100), power = 0.8, pH0 = 0.5, pH1 = 0.6) apt getHarmBound(nevents = c(10,50,100),alpha_test = apt, pH0 = 0.5, pH1 = 0.6)#Control overall family-wise type I error: apt<-getAlphaPerTest(nevents = c(10,50,100), alpha_total = 0.05, pH0 = 0.5) apt getHarmBound(nevents = c(10,50,100),alpha_test = apt, pH0 = 0.5) #Control power assuming 80% of events in expermintal arm apt<-getAlphaPerTest(nevents = c(10,50,100), power = 0.8, pH0 = 0.5, pH1 = 0.6) apt getHarmBound(nevents = c(10,50,100),alpha_test = apt, pH0 = 0.5, pH1 = 0.6)
Calculates the boundaries at each interim analysis, i.e. the number of events in the treatment arm that would lead to a stopping of the trial based binomial exact tests, assuming that the events should be equally distributed among both arms. The indicated scenario (and all more extreme) would lead to a rejection of H0 (equal distribution) and a stopping for safety.
getHarmBound( nevents, alpha_test = NULL, alpha_total = NULL, power = NULL, pH0, maxevents = NULL, icc = NULL, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL )getHarmBound( nevents, alpha_test = NULL, alpha_total = NULL, power = NULL, pH0, maxevents = NULL, icc = NULL, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL )
nevents |
vector with number of events (over both arms) at which an interim analysis is done |
alpha_test |
the nominal alpha level to use for each test |
alpha_total |
target overall family-wise type I error |
power |
target power at the specified alternative |
pH0 |
proportion of events in the treatment arm under the null hypothesis, typically based on randomization ratio (e.g. 0.5 for a 1:1 randomization) |
maxevents |
optional maximum number of events expected for the trial (over both arms), used to calculate the expected number of events |
icc |
intraclass correlation if there is more than one event per patient |
pH1 |
optional alternative, numeric vector, proportion of events in the treatment arm |
rrH1 |
alternative specification of alternative as risk ratio (treatment / control) |
orH1 |
alternative specification of alternative as risk ratio (treatment / control). Requires the control proportion (r0). |
rdH1 |
alternative specification of alternative as risk difference (treatment - control). Requires the control proportion (r0). |
r0 |
risk in the control arm. Required if the alternative is given as risk difference or odds ratio. |
If there are several events per patient, the intraclass correlation coefficient has to be given and a beta-binomial framework is used. The overdispersion factor (or design effect) by which the variance exceeds the regular binomial variance is printed. Note that the effective sample size is reduced by that factor.
The rejection region for the binomial or beta-binomial exact tests must be given for either each test (alpha_test), overall (alpha_total, the family-wise error rate) or by the targetted power for the specified alternative.
a list with 3 data.frames: bounds, stopprob and opchar. bounds has a row for each interim analysis and columns for number of events (events), number of events in control and treatment arm that would lead to a stop (events_treatment, events_control), and the nominal alpha for each test (alpha_test). stopprob has a row for each interim analysis and columns for number of events (events), the hypothesis (pH), the stopping probability (stop_prob), and the cumulative stopping probability (cum_stop_prob) opchar has a row for each hypothesis (null plus each alternative) and columns for the assumed proportion of events in the treatment arm (p), the cumulative stopping probabilities (cum_stop_prob) and the expected total number of events (expected_events) for the null and each alternative.
Available plot methods: plot.harmbound
getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5) #adding an alternative getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1=0.6) #assume that a total of 150 events might occur (for the expected events) getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1=0.6, maxevents=150) #several alternatives getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1 = seq(0.6,0.8,by=0.05), maxevents=150) #using a risk ratio to specify the alternative getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, rrH1=1.5, maxevents=150) # define the test so that an family-wise type I error of 5% is achieved getHarmBound(nevents=c(10,50,100), alpha_total=0.05, pH0=0.5) # define the test so that an over power of 80% is achieved # needs an alternative getHarmBound(nevents=c(10,50,100), power=0.8, pH0=0.5, pH1=0.6)getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5) #adding an alternative getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1=0.6) #assume that a total of 150 events might occur (for the expected events) getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1=0.6, maxevents=150) #several alternatives getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, pH1 = seq(0.6,0.8,by=0.05), maxevents=150) #using a risk ratio to specify the alternative getHarmBound(nevents=c(10,50,100), alpha_test=0.025, pH0=0.5, rrH1=1.5, maxevents=150) # define the test so that an family-wise type I error of 5% is achieved getHarmBound(nevents=c(10,50,100), alpha_total=0.05, pH0=0.5) # define the test so that an over power of 80% is achieved # needs an alternative getHarmBound(nevents=c(10,50,100), power=0.8, pH0=0.5, pH1=0.6)
Plot harmbounds and the observed events
harmboundPlot( harmbound, observed = NULL, colourbound = c("blue", "red"), fill_alpha = 0.5, colourobserved = "black", H0line = TRUE )harmboundPlot( harmbound, observed = NULL, colourbound = c("blue", "red"), fill_alpha = 0.5, colourobserved = "black", H0line = TRUE )
harmbound |
harmbounds objects as generated using the getHarmBound function |
observed |
optional observed number of events, as a vector with the sequential arms in which an event occured (0 for control and 1 for treatment) |
colourbound |
vector with two colours for the bounds, in and out, default is blue and red |
fill_alpha |
opacity of the colours for the bounds |
colourobserved |
colour for the line with the observed events |
H0line |
logical, whether a line to indicate the expectations should be added. |
plot with the bounds and optionally the observed number of events
harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5) harmboundPlot(harmbound) set.seed(123) eventgroups<-rbinom(n=100,size=1,prob=0.5) harmboundPlot(harmbound,observed=eventgroups)harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025,pH0=0.5) harmboundPlot(harmbound) set.seed(123) eventgroups<-rbinom(n=100,size=1,prob=0.5) harmboundPlot(harmbound,observed=eventgroups)
Plot expected number of events
opcharNPlot(harmbound)opcharNPlot(harmbound)
harmbound |
harmbounds objects as generated using the getHarmBound function |
line plot with the expected number of events for all alternatives
harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025, pH0=0.5,pH1=seq(0.5,0.8,by=0.05),maxevents=150) opcharNPlot(harmbound)harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025, pH0=0.5,pH1=seq(0.5,0.8,by=0.05),maxevents=150) opcharNPlot(harmbound)
Plot cumulative stopping probabilities by hypothesis
opcharStopPlot(harmbound)opcharStopPlot(harmbound)
harmbound |
harmbounds objects as generated using the getHarmBound function |
line plot with the cumulative stopping for all alternatives
harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025, pH0=0.5,pH1=seq(0.5,0.8,by=0.05),maxevents=150) opcharStopPlot(harmbound)harmbound<-getHarmBound(nevents=seq(10,100,by=10),alpha_test=0.025, pH0=0.5,pH1=seq(0.5,0.8,by=0.05),maxevents=150) opcharStopPlot(harmbound)
getHarmBound
Plot method for harmbound objects produced by getHarmBound
## S3 method for class 'harmbound' plot(x, which = "bounds", ...)## S3 method for class 'harmbound' plot(x, which = "bounds", ...)
x |
harmbounds objects as generated using the getHarmBound function |
which |
one of |
... |
options passed to plot |
harmbound<-getHarmBound(nevents = seq(10, 100, by=10),alpha_test = 0.025, pH0 = 0.5, pH1 = seq(0.55,0.7,by=0.05), maxevents = 150) plot(harmbound, which = "bounds") plot(harmbound, which = "abs_stopping") plot(harmbound, which = "cum_stopping") plot(harmbound, which = "opchar_stop") plot(harmbound, which = "opchar_n")harmbound<-getHarmBound(nevents = seq(10, 100, by=10),alpha_test = 0.025, pH0 = 0.5, pH1 = seq(0.55,0.7,by=0.05), maxevents = 150) plot(harmbound, which = "bounds") plot(harmbound, which = "abs_stopping") plot(harmbound, which = "cum_stopping") plot(harmbound, which = "opchar_stop") plot(harmbound, which = "opchar_n")
The effect can be given as proportion of events in the experimental group (pH1), the risk difference (rdH1), risk ratio (rrH1) or odds ratio (orH1).
simSafetyStop( nevents, pH0 = 0.5, alpha_test = 0.025, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL, n = NULL, icc = NULL, correct = TRUE )simSafetyStop( nevents, pH0 = 0.5, alpha_test = 0.025, pH1 = NULL, rrH1 = NULL, orH1 = NULL, rdH1 = NULL, r0 = NULL, n = NULL, icc = NULL, correct = TRUE )
nevents |
vector with number of events at which an interim analysis is done |
pH0 |
proportion of events in the experimental arm under the null hypothesis, typically based on randomization ratio (e.g. 0.5 for a 1:1 randomization) |
alpha_test |
nominal alpha level for binomial exact test |
pH1 |
proportion of events in the experimental arm under the alternative hypothesis |
rrH1 |
risk ratio (experimental / control). |
orH1 |
risk ratio (experimental / control). Requires the control proportion (r0). |
rdH1 |
risk difference (experimental - control). Requires the control proportion (r0) and the number of participants (n). |
r0 |
risk in the control arm. Required if the effect is given as risk difference or odds ratio. |
n |
total number of participants. Required if the effect is given as risk difference. |
icc |
intraclass correlation if there is more than one event per patient |
correct |
logical, whether to use icc for boundary construction |
list with a dataframe with number of events in each group plus upper limit for stopping and indicator for whether stopped, plus indicators number of stops and time points at first stop
set.seed(1) simSafetyStop(nevents=seq(10,100,by=10),pH0 = 0.5, pH1 = 0.6, alpha_test=0.025) set.seed(1) simSafetyStop(nevents=seq(10,100,by=10),pH0 = 0.5, rrH1 = 0.6/(1-0.6), alpha_test=0.025)set.seed(1) simSafetyStop(nevents=seq(10,100,by=10),pH0 = 0.5, pH1 = 0.6, alpha_test=0.025) set.seed(1) simSafetyStop(nevents=seq(10,100,by=10),pH0 = 0.5, rrH1 = 0.6/(1-0.6), alpha_test=0.025)