Skip to content

Commit

Permalink
resolve conflict when rebasing feature off main
Browse files Browse the repository at this point in the history
  • Loading branch information
audreyyeoCH committed Oct 10, 2024
1 parent 9fbc3ba commit d9cc2e3
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 74 deletions.
73 changes: 42 additions & 31 deletions R/boundsPredprob.R
Original file line number Diff line number Diff line change
@@ -1,38 +1,36 @@
#' Decision cutpoints for boundary (based on predictive probability)
#' Decision cutpoints for boundary (based on predictive probability) for Decision 1 rule.
#'
#' This function is used to identify the efficacy boundary and futility
#' boundary based on predictive probabilities, i.e.:
#' boundary based on the following rules:
#' Efficacy boundary: find minimum x (xU) where
#' Pr(Pr(P > p | x, Y) >= tT | x) > phiU,
#' Pr(Pr(P > p0 | x, Y, a, b) >= tT | x) >= phiU,
#' Futility boundary: find maximum x (xL) where
#' Pr(Pr(P > p | x, Y) >= tT | x) < phiL
#' Pr(Pr(P > p0 | x, Y, a, b) >= tT | x) =< phiL
#'
#' @param nvec a vector of number of patients
#' @param Nmax maximum number of patients at the end of the trial
#' (default: maximum of \code{nvec})
#' @param p threshold on the response rate
#' @param tT threshold on the posterior probability to be above p
#' @param phiL futility boundary predictive probability threshold
#' @param phiU efficacy boundary predictive probability threshold
#' @param a the alpha parameter of a beta prior of treatment group
#' @param b the beta parameter of a beta prior of treatment group
#' @return A matrix where for each sample size in \code{nvec}, this function
#' returns the maximum number of responses that meet the futility
#' threshold (xL), its corresponding response rate (pL), predictive probability
#' (ppL) and posterior probability (postL), the upper bound of one
#' sided 95% CI for the response rate based on an
#' exact binomial test (UciL), and the same boundary parameters for efficacy:
#' the minimal number of responses that meet the efficacy threshold (xU),
#' the corresponding response rate (pU), predictive probability
#' (ppL) and posterior probability (postU), the lower bound of one sided
#' 95% CI for the response rate based on exact binomial test (LciU).
#' @inheritParams predprob
#' @inheritParams ocPredprob
#' @inheritParams boundsPostprob
#' @return A matrix for each same size in `nvec`. For each sample size, the following is returned:
#' - `xL` : the maximum number of responses that meet the futility.
#' threshold
#' - `pL` : response rate corresponding to `xL`.
#' - `ppL` : predictive probability corresponding to `xL`
#' - `postL`: posterior probability corresponding to `xL`.
#' - `Ucil` : upper bound of one sided 95% CI for the response rate based on an
#' exact binomial test.
#' - `xU` : the minimal number of responses that meet the efficacy threshold.
#' - `pU` : response rate corresponding to `xU`.
#' - `postL`: posterior probability corresponding to `xU`.
#' - `ppU` : predictive probability corresponding to `xU`
#' - `LciU` : lower bound of one sided 95% CI for the response rate based on exact
#' binomial test.
#'
#' @importFrom stats binom.test
#'
#' @example examples/boundsPredprob.R
#' @export
#' @keywords graphics
boundsPredprob <- function(nvec, Nmax = max(nvec), p, tT, phiL, phiU, a, b) {
boundsPredprob <- function(nvec, Nmax = max(nvec), p0, tT, phiL, phiU, a, b) {
znames <- c(
"xL", "pL", "ppL", "postL", "UciL",
"xU", "pU", "ppU", "postU", "LciU"
Expand All @@ -46,29 +44,42 @@ boundsPredprob <- function(nvec, Nmax = max(nvec), p, tT, phiL, phiU, a, b) {
xL <- NA
xU <- NA
for (x in 0:n) {
pp <- predprob(x, n, Nmax, p, tT, parE = c(a, b))$result
pp <- predprob(x, n, Nmax, p0, tT, parE = c(a, b))$result
if (pp <= phiL) {
xL <- x
ppL <- pp
}
if (pp >= phiU) {
xU <- x
ppU <- ppL
# done: leave innermost for loop
break
}
}
# reset xU to NA if phiU=1 and n<Nmax
# reset xU to NA if phiU = 1 and n < Nmax
if (n < Nmax && phiU == 1) {
xU <- NA
}
# calculate predictive and posterior probabilities at boundaries
ppL <- predprob(xL, n, Nmax, p, tT, parE = c(a, b))$result
ppU <- predprob(xU, n, Nmax, p, tT, parE = c(a, b))$result
postL <- postprob(xL, n, p, parE = c(a, b))
postU <- postprob(xU, n, p, parE = c(a, b))
ppL <- predprob(xL, n, Nmax, p0, tT, parE = c(a, b))$result
ppU <- predprob(xU, n, Nmax, p0, tT, parE = c(a, b))$result
postL <- postprob(xL, n, p0, parE = c(a, b))
postU <- postprob(xU, n, p0, parE = c(a, b))
# calculate lower CI at boundaries
UciL <- ifelse(!is.na(xL), stats::binom.test(xL, n, alt = "less")$conf.int[2], NA)
LciU <- ifelse(!is.na(xU), stats::binom.test(xU, n, alt = "greater")$conf.int[1], NA)
z[k, ] <- c(xL, xL / n, ppL, postL, UciL, xU, xU / n, ppU, postU, LciU)
z[k, ] <- c(
xL,
xL / n,
ppL,
postL,
UciL,
xU,
xU / n,
ppU,
postU,
LciU
)
}
return(round(data.frame(nvec, z), 4))
}
16 changes: 8 additions & 8 deletions examples/boundsPredprob.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## 40 pts trial with interim looks after each 10 pts.,
## final efficacy decision if more than 80% probability to be above 20% ORR,
## final futility decision otherwise.
## Interim efficacy decision if more than 90% predictive probability reach this,
## interim futility decision if less than 10% predictive probability.
## Uniform prior (i.e. beta(1, 1)) on the ORR:
# 40 pts trial with interim looks after each 10 pts.,
# final efficacy decision if more than 80% probability to be above 20% ORR,
# final futility decision otherwise.
# Interim efficacy decision if more than 90% predictive probability reach this,
# interim futility decision if less than 10% predictive probability.
# Uniform prior (i.e. beta(1, 1)) on the ORR:
boundsPredprob(
nvec = c(10, 20, 30, 40), p = 0.20, tT = 0.80,
phiL = 0.10, phiU = 0.90, a = 1, b = 1
)
## From this we see e.g. that at the first IA at 10 pts, we would stop for futility
## if no patient responded, and for efficacy if 4 or more pts responded.
# From this we see e.g. that at the first IA at 10 pts, we would stop for futility
# if no patient responded, and for efficacy if 4 or more pts responded.
69 changes: 34 additions & 35 deletions man/boundsPredprob.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions tests/testthat/test-boundsPredprob.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# boundsPostProb ----
test_that("boundsPredprob gives correct result and list", {
result <- boundsPredprob(
nvec = c(10, 20, 30, 40),
p0 = 0.2,
tT = 0.80,
phiL = 0.10,
phiU = 0.90,
a = 1,
b = 1
)
expected <- data.frame(
list(
nvec = c(10, 20, 30, 40),
xL = c(0, 2, 5, 9),
pL = c(0, 0.1, 0.1667, 0.225),
postL = c(0.0859, 0.1787, 0.3931, 0.704),
UciL = c(0.2589, 0.2826, 0.319, 0.3598),
xU = c(4, 7, 9, 10),
pU = c(0.4, 0.35, 0.3, 0.25),
postU = c(0.9496, 0.9569, 0.9254, 0.8177),
LciU = c(0.15, 0.1773, 0.1663, 0.1424)
)
)
expect_equal(result$xL, c(0, 2, 5, 9))
expect_equal(result$pL, c(0, 0.1, 0.1667, 0.225))
expect_equal(result$postL, c(0.0859, 0.1787, 0.3931, 0.704))
expect_equal(result$UciL, c(0.2589, 0.2826, 0.319, 0.3598))
expect_equal(result$xU, c(4, 7, 9, 10))
expect_equal(result$pU, c(0.4, 0.35, 0.3, 0.25))
expect_equal(result$postU, c(0.9496, 0.9569, 0.9254, 0.8177))
expect_equal(result$LciU, c(0.15, 0.1773, 0.1663, 0.1424))
})

0 comments on commit d9cc2e3

Please sign in to comment.