Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16: clean postprobDist #20

Merged
merged 118 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 115 commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
50ef5b1
cleaning up dbetabinom
audreyyeoCH Aug 14, 2023
4342b5a
removed rounding, not needed
audreyyeoCH Aug 14, 2023
b095ae6
rmarkdown language and assert for dbetabinom
audreyyeoCH Aug 22, 2023
889e97d
changed x and m to number instead of numeric
audreyyeoCH Aug 22, 2023
2eafdc5
test
audreyyeoCH Aug 22, 2023
9dc428b
pbetaMix function and test
audreyyeoCH Aug 23, 2023
dd1d8c4
added new tests and changed documentation
audreyyeoCH Aug 24, 2023
6d7f478
upper case for test_that comments and more tests for qbeta
audreyyeoCH Aug 24, 2023
d520ff0
Merge branch 'main' into 9_pbeta
audreyyeoCH Aug 25, 2023
0b361e3
test_thats for pbetaMix and qbetaMix
audreyyeoCH Aug 27, 2023
8b20f72
tidy syntax and last checks
audreyyeoCH Aug 28, 2023
b0c2218
tidy syntax and last checks
audreyyeoCH Aug 28, 2023
9f53521
Merge remote-tracking branch 'origin/9_pbeta' into 9_pbeta
audreyyeoCH Aug 28, 2023
5384c3d
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
f5403fa
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Aug 28, 2023
0dd2bab
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
ca0236f
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
9cf54d0
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
2eb3bd2
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
c08435f
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
e36facd
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
f45d2f0
Update R/dbetabinom.R
audreyyeoCH Aug 28, 2023
0505982
Update examples/pbetaMix.R
audreyyeoCH Aug 28, 2023
469ed6e
p and q inputs
audreyyeoCH Aug 29, 2023
1abea50
q,p changes
audreyyeoCH Aug 29, 2023
b7b523c
Update R/dbetabinom.R
audreyyeoCH Aug 29, 2023
34a663b
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Aug 29, 2023
f384100
documentation to reflect p and q changes
audreyyeoCH Aug 29, 2023
f0d5d00
Merge remote-tracking branch 'origin/9_pbeta' into 9_pbeta
audreyyeoCH Aug 29, 2023
b9e50b2
amending qt
audreyyeoCH Aug 29, 2023
0ab047d
intro x-> q
audreyyeoCH Aug 29, 2023
4164b46
amented postprob file
audreyyeoCH Aug 29, 2023
5d98627
amended postprob file
audreyyeoCH Aug 29, 2023
205e574
fixed mistake on x
audreyyeoCH Aug 29, 2023
01bd1bf
Merge remote-tracking branch 'origin/9_pbeta' into 9_pbeta
audreyyeoCH Aug 29, 2023
2d093ba
qbetaMix was in postprobDist
audreyyeoCH Aug 29, 2023
c7dbbf9
trying to find R CMD check error
audreyyeoCH Aug 30, 2023
640f9f3
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Aug 30, 2023
3f01c97
manual of ocPostprobDist
audreyyeoCH Aug 30, 2023
99d6eb5
Merge remote-tracking branch 'origin/9_pbeta' into 9_pbeta
audreyyeoCH Aug 30, 2023
cc069c3
fixing roxygen type to p
audreyyeoCH Aug 30, 2023
626345c
see if this fixes the CMD check
audreyyeoCH Aug 30, 2023
3882982
see if fixes CMD check error
audreyyeoCH Aug 30, 2023
f6c7df2
xi removed
audreyyeoCH Aug 30, 2023
80eee89
example post prob works
audreyyeoCH Aug 30, 2023
1d115b4
clean
audreyyeoCH Aug 30, 2023
2185dea
Merge branch 'tmp' into 9_pbeta
audreyyeoCH Aug 30, 2023
5bb074e
assert_number
audreyyeoCH Aug 30, 2023
9d4b62c
in postprobDist, I changed p-> q
audreyyeoCH Aug 30, 2023
db8fb65
change p to q
audreyyeoCH Aug 30, 2023
51ed0c9
Merge remote-tracking branch 'origin/9_pbeta' into 9_pbeta
audreyyeoCH Aug 30, 2023
8470616
postprobold
audreyyeoCH Aug 30, 2023
3c86a99
postprobOld
audreyyeoCH Aug 31, 2023
80606cf
Merge remote-tracking branch 'origin/main' into 11_postprob
audreyyeoCH Aug 31, 2023
2f9b831
clean post prob
audreyyeoCH Sep 7, 2023
5d553ee
nice titles
audreyyeoCH Sep 7, 2023
c475186
documentations
audreyyeoCH Sep 8, 2023
0dd9c8a
clean
audreyyeoCH Sep 8, 2023
9ddd5df
clean
audreyyeoCH Sep 21, 2023
476ad27
clean
audreyyeoCH Sep 22, 2023
5397930
clean
audreyyeoCH Sep 22, 2023
6fd620f
Merge remote-tracking branch 'origin/main' into 14_ocPostProb
audreyyeoCH Sep 22, 2023
2dd0a44
clean
audreyyeoCH Sep 26, 2023
0af15cd
clean
audreyyeoCH Sep 27, 2023
63de68a
some examples and tests
audreyyeoCH Sep 28, 2023
7eba969
clean
audreyyeoCH Sep 29, 2023
8135abd
fix R CMD check errors
audreyyeoCH Oct 2, 2023
c79982c
fix R CMD check errors for PR
audreyyeoCH Oct 2, 2023
cf0ace7
Update R/ocPostprob.R
audreyyeoCH Oct 3, 2023
3b1ed09
Update R/ocPostprob.R
audreyyeoCH Oct 3, 2023
271edd4
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 3, 2023
7f2c01b
Update R/ocPostprob.R
audreyyeoCH Oct 3, 2023
027e432
Update R/ocPostprob.R
audreyyeoCH Oct 3, 2023
459dac9
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 3, 2023
7964767
Update R/ocPostprob.R
audreyyeoCH Oct 3, 2023
c3ab3ea
PR feedback
audreyyeoCH Oct 3, 2023
71f797e
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 3, 2023
645024c
Merge remote-tracking branch 'origin/14_ocPostProb' into 14_ocPostProb
audreyyeoCH Oct 3, 2023
7724a7a
clean
audreyyeoCH Oct 5, 2023
f436dbb
Merge remote-tracking branch 'origin/14_ocPostProb' into 14_ocPostProb
audreyyeoCH Oct 5, 2023
35126ab
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 5, 2023
76a430f
clean
audreyyeoCH Oct 25, 2023
7f4a095
Merge branch 'main' into 16_postprobdist
audreyyeoCH Oct 25, 2023
c83eeab
merge
audreyyeoCH Oct 25, 2023
b6958c9
clean
audreyyeoCH Oct 27, 2023
136c4d8
works
audreyyeoCH Nov 2, 2023
6e9e814
clean
audreyyeoCH Nov 3, 2023
24efa48
the error is now on dbetabinom.R#141
audreyyeoCH Nov 4, 2023
dc6a884
clean
audreyyeoCH Nov 6, 2023
19c6a42
postprobDist works
audreyyeoCH Nov 9, 2023
e90d273
clean
audreyyeoCH Nov 14, 2023
c3435af
Update R/postprobDist.R
audreyyeoCH Nov 14, 2023
f1fc03a
Update R/postprobDist.R
audreyyeoCH Nov 14, 2023
b712070
clean
audreyyeoCH Nov 14, 2023
1664871
Auto stash before checking out "origin/16_postprobdist"
audreyyeoCH Nov 14, 2023
0ba4561
clean
audreyyeoCH Nov 16, 2023
eb99f76
clean
audreyyeoCH Nov 16, 2023
b0e2a11
clean
audreyyeoCH Nov 16, 2023
5a81304
clean
audreyyeoCH Nov 16, 2023
a199f63
clean
audreyyeoCH Nov 16, 2023
b799be4
just changed c(1) -> 1
audreyyeoCH Nov 16, 2023
76a0258
Update R/postprobDist.R
audreyyeoCH Nov 17, 2023
8fbb597
Update R/postprobDist.R
audreyyeoCH Nov 17, 2023
ad89a23
Update examples/postprobDist.R
audreyyeoCH Nov 17, 2023
6cf8743
Update examples/postprobDist.R
audreyyeoCH Nov 17, 2023
0ab1ead
clean
audreyyeoCH Nov 17, 2023
038c6a6
clean
audreyyeoCH Nov 17, 2023
933d043
Update R/postprobDist.R
audreyyeoCH Nov 17, 2023
90b4d7f
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
236617b
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
dc8d311
Update examples/postprobDist.R
audreyyeoCH Nov 17, 2023
2a4c3b3
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
07fd3b1
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
6ad8f58
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
89c5d66
Update tests/testthat/test-postprobDist.R
audreyyeoCH Nov 17, 2023
6d79c5d
clean
audreyyeoCH Nov 18, 2023
67d1022
clean
audreyyeoCH Nov 18, 2023
7814570
clean
audreyyeoCH Nov 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions R/dbetabinom.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
#' whether to return the log density value (not default).
#' @return The density values of the beta-binomial distribution at `x`.
#'
#' @note `x`, `a` and `b` can be vectors.
#'
#' @example examples/dbetabinom.R
#' @export
dbetabinom <- function(x, m, a, b, log = FALSE) {
Expand Down Expand Up @@ -57,8 +55,6 @@ dbetabinom <- function(x, m, a, b, log = FALSE) {
#' whether to return the log density value (not default).
#' @return The (log) density values of the mixture of beta-binomial distributions at `x`.
#'
#' @note `x` can be a vector.
#'
#' @example examples/dbetabinomMix.R
#' @export
dbetabinomMix <- function(x, m, par, weights, log = FALSE) {
Expand Down Expand Up @@ -89,6 +85,7 @@ dbetabinomMix <- Vectorize(dbetabinomMix, vectorize.args = "x")
#'
#' @example examples/getBetamixPost.R
#' @export

getBetamixPost <- function(x, n, par, weights) {
## check the format
stopifnot(
Expand Down Expand Up @@ -125,6 +122,7 @@ getBetamixPost <- function(x, n, par, weights) {
}



#' Beta-mixture density function
#'
#' Note that `x` can be a vector.
Expand Down
1 change: 0 additions & 1 deletion R/postprob.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ postprobBeta <- function(x, n, p, a = 1, b = 1) {
stats::pbeta(p, a + x, b + n - x, lower.tail = FALSE)
}


#' Posterior Probability of Efficacy Given Beta-Mixture Prior
#'
#' @description `r lifecycle::badge("experimental")`
Expand Down
291 changes: 178 additions & 113 deletions R/postprobDist.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,135 +2,198 @@
#' @include postprob.R
NULL

#' Compute the posterior probability with beta prior on SOC
#'
#' Using the approach by Thall and Simon (Biometrics, 1994), evaluate the
#' posterior probability of having Pr(P_E > P_S + delta | data) (but see below
#' for relative delta margin). Both for the new treatment E as well as for the
#' SOC S data might be available. However the default is that no data is
#' available for the SOC, corresponding to the single arm trial situation. Note
#' that a uniform prior is the useful default for the treatment proportion,
#' while in the single arm trial an informative prior on the SOC proportion is
#' useful.
#'
#' Beta mixture prior can be specified for the treatment (\code{parE}
#' and \code{weights} parameters) and control proportion (\code{parS} and
#' \code{weightsS} parameters), see \code{\link{postprob}} for details. Note
#' that being able to specify a beta mixture prior also on the control
#' treatment is e.g. important for the futility decision making (see the
#' \code{\link{oc2}} code).
#'
#' @param x number of successes (in the treatment group). Note that \code{x}
#' can be a vector.
#' @param n number of patients (in the treatment group)
#' @param xS number of successes in the SOC group (default: 0)
#' @param nS number of patients in the SOC group (default: 0)
#' @param delta margin by which the response rate in the treatment group should
#' be better than in the SOC group (default: 0)
#' @param relativeDelta should the delta be relative? (not default). If this is
#' \code{TRUE}, then a relative delta is used. This means we want to have
#' response at least in delta proportion of the SOC non-responding patients.
#' Non-responding patients rate is 1 - P_S, and we want to have P_S + (1 - P_S)
#' * delta response rate (at least) in the treatment. That is, we evaluate the
#' posterior probability Pr(P_E > P_S + (1 - P_S) * delta | data).
#' @param parE the beta parameters matrix, with K rows and 2 columns,
#' corresponding to the beta parameters of the K components. default is a
#' uniform prior.
#' @param weights the mixture weights of the beta mixture prior. Default are
#' uniform weights across mixture components.
#' @param parS beta parameters for the SOC group (default: uniform)
#' @param weightsS weights for the SOC group (default: uniform)
#' @return the posterior probability
#' The Posterior Beta Mixture Integrand when `delta` is relative
#'
#' The helper function to generate Integrand function when `relative Delta = TRUE`.
#'
#' @typed delta : number
#' the margin of which treatment group `E` is superior than the success rate of
#' the standard of care `S`. See also note about the calculation of `delta` when `relative Delta = TRUE`.
#' @typed p_s : number
#' probability of success or response rate of standard of care or `SOC` group.
#' @typed activeBetamixPost : list
#' a list of posterior parameters of a beta-mixture-binomial distribution with generic names
#' `par` and `weights`. See `[getBetaMix()]`.
#' @typed controlBetamixPost : list
#' a list of posterior parameters of a beta-mixture-binomial distribution with generic names
#' `par` and `weights`. See `[getBetaMix()]`.
#'
#' @return Function that is an argument for `[stats::integrate()]`.
#'
#' @keywords internal
#'
h_integrand_relDelta <- function(p_s, delta, activeBetamixPost, controlBetamixPost) {
cdf <- postprob(
x = 0, # Needed for Vectorize()
p = (1 - p_s) * delta + p_s,
betamixPost = activeBetamixPost
)
pdf <- with(
controlBetamixPost,
dbetaMix(x = p_s, par = par, weights = weights)
)
cdf * pdf
}

#' The Posterior Beta Mixture Integrand when Delta is absolute
#'
#' The helper function to generate Integrand function when `relative Delta = FALSE`,
#' a default setting.
#'
#' @inheritParams h_integrand_relDelta
#'
#' @return Function that is an argument for `[stats::integrate()]`.
#'
#' @keywords internal
#'
h_integrand <- function(p_s, delta, activeBetamixPost, controlBetamixPost) {
cdf <- postprob(
x = 0, # Needed for Vectorize()
p = p_s + delta,
betamixPost = activeBetamixPost
)
pdf <- with(
controlBetamixPost,
dbetaMix(x = p_s, par = par, weights = weights)
)
cdf * pdf
}

#' Generating bounds for the Integration of Beta Mixture Posterior
#'
#' Using the quantile of the Beta Mixture Distribution from parameters given by standard of care `SOC` or
#' experimental group `E` to determine bounds as inputs to `[stats::integrate()]`.
#'
#' @inheritParams h_integrand_relDelta
#' @return Integrand function
#'
#' @keywords internal
#'
h_get_bounds <- function(controlBetamixPost) {
epsilon <- .Machine$double.xmin
with(
controlBetamixPost,
qbetaMix(
p = c(epsilon, 1 - epsilon),
par = par,
weights = weights
)
)
}

#' Compute the Posterior Probability with Beta Prior on `SOC`
#'
#' @description `r lifecycle::badge("experimental")`
#'
#' Using the approach by Thall and Simon (Biometrics, 1994), this evaluates the
#' posterior probability of achieving superior response rate in the treatment group compared to standard of care (SOC):
#'
#' `Pr(P_E > P_S | data) = \int 1-F(p_s + delta | alpha_E + x, beta_E + n- x) f(p_s; alpha_S, beta_S`.
#' See note below for two formulations of the difference in response rates.
#'
#' @typed x : numeric
#' number of success counts in the treatment group.
#' @typed n : number
#' number of patients in the treatment group.
#' @typed xS : number
#' number of success counts in the SOC group.
#' @typed nS : number
#' number of patients in the SOC group.
#' @typed delta : number
#' margin by which the response rate in the treatment group should
#' be better than in the SOC group. Must be >= `0`. See note.
#' @typed relativeDelta : flag
#' If `TRUE`, then a `relativeDelta` is used. Represents that a minimum
#' response rate in magnitude of `delta` of the SOC non-responding patients. See note.
#' @typed parE : "`numeric` or `matrix`"
#' parameters for beta distribution. If it is a matrix, it needs to have 2 columns,
#' and each row corresponds to each component of a beta-mixture distribution
#' for the `E` group. See details.
#' @typed weights : numeric
#' the non-negative mixture weights of the beta mixture prior for group `E`.
#' equal weights across mixture components.
#' In the simple case of no mixture of priors given, the Beta parameters are weighted as `100 %`.
audreyyeoCH marked this conversation as resolved.
Show resolved Hide resolved
#' Weights can exceed 1, to which the algorithm will normalize the weights such that all weights sum to 1.
#' @typed parS : "`numeric` or `matrix`"
#' parameters for beta distribution. If it is a matrix, it needs to have 2 columns,
#' and each row corresponds to each component of a beta-mixture distribution
#' for the `S` group. See details.
#' @typed weightsS : numeric
#' weights for the SOC group. See also `weights`.
#' @typed epsilon : number
#' the smallest non-negative floating number to represent the lower bound for
#' the interval of integration.
#' @return The posterior probability
#'
#' @note
#'
#' ## Delta :
#'
#' The desired improvement is denoted as `delta`. There are two options in using `delta`.
#' The absolute case when `relativeDelta = FALSE` and relative as when `relativeDelta = TRUE`.
#'
#' 1. The absolute case is when we define an absolute delta, greater than `P_S`,
#' the response rate of the `SOC` group such that
#' the posterior is `Pr(P_E > P_S + delta | data)`.
#'
#' 2. In the relative case, we suppose that the treatment group's
#' response rate is assumed to be greater than `P_S + (1-P_S) * delta` such that
#' the posterior is `Pr(P_E > P_S + (1 - P_S) * delta | data)`.
#'
#' @details
#'
#' The beta mixture prior for the E arm requires argument `parE` and `weights`.
#' The beta mixture prior for the E arm requires argument `parS` and `weightsS`.
#' See `[postprob()]` for details.
#'
#' @example examples/postprobDist.R
#' @export
postprobDist <- function(x, n,
xS = 0, nS = 0,
delta = 0,
postprobDist <- function(x,
n,
xS = 0,
nS = 0,
delta,
relativeDelta = FALSE,
parE = c(1, 1),
weights,
parS = c(1, 1),
weightsS) {
## if parE is a vector => situation where there is only one component
if (is.vector(parE)) {
## check that it has exactly two entries
stopifnot(identical(length(parE), 2L))

## and transpose to matrix with one row
assert_true(identical(length(parE), 2L))
parE <- t(parE)
}

## if prior weights of the beta mixture are not supplied
if (missing(weights)) {
weights <- rep(1, nrow(parE))
}

## if parS is a vector => situation where there is only one component
if (is.vector(parS)) {
## check that it has exactly two entries
stopifnot(identical(length(parS), 2L))

## and transpose to matrix with one row
assert_true(identical(length(parS), 2L))
parS <- t(parS)
}

## if prior weights of the beta mixture are not supplied
if (missing(weights)) {
weights <- rep(1, nrow(parE))
}
if (missing(weightsS)) {
weightsS <- rep(1, nrow(parS))
}

## compute updated beta parameters
assert_numeric(x, lower = 0, upper = n, finite = TRUE)
assert_number(n, lower = x, finite = TRUE)
assert_number(xS, lower = 0, upper = n, finite = TRUE)
assert_numeric(nS, lower = 0, finite = TRUE)
assert_number(delta, lower = 0, finite = TRUE)
assert_flag(relativeDelta)
assert_numeric(weights, lower = 0, finite = TRUE)
assert_numeric(weightsS, lower = 0, finite = TRUE)
assert_numeric(parE, lower = 0, finite = TRUE)
assert_numeric(parS, lower = 0, finite = TRUE)
activeBetamixPost <- getBetamixPost(x = x, n = n, par = parE, weights = weights)
controlBetamixPost <- getBetamixPost(x = xS, n = nS, par = parS, weights = weightsS)

## use numerical integration to compute this probability, as given on p.338
## in the article by Thall and Simon (1994):
integrand <-
if (relativeDelta) {
function(p) {
cdf <- postprob(
x = x,
p = (1 - delta) * p + delta,
betamixPost = activeBetamixPost
)

pdf <- with(
controlBetamixPost,
dbetaMix(x = p, par = par, weights = weights)
)

return(cdf * pdf)
}
} else {
function(p) {
cdf <- postprob(
x = x,
p = p + delta,
betamixPost = activeBetamixPost
)

pdf <- with(
controlBetamixPost,
dbetaMix(x = p, par = par, weights = weights)
)

return(cdf * pdf)
}
}

## do the integration. be careful to cover the region where there can
## really be any non-zero values. I.e. only integrate over the region where
## the beta density of the control is non-zero.
epsilon <- 1e-13
bounds <- with(
controlBetamixPost,
qbetaMix(
p = c(epsilon, 1 - epsilon),
par = par,
weights = weights
)
)
assert_names(names(activeBetamixPost), identical.to = c("par", "weights"))
assert_names(names(controlBetamixPost), identical.to = c("par", "weights"))
if (relativeDelta) {
epsilon <- .Machine$double.xmin
integrand <- h_integrand_relDelta
} else {
epsilon <- .Machine$double.xmin
integrand <- h_integrand
}
bounds <- h_get_bounds(controlBetamixPost = controlBetamixPost)
intRes <- integrate(
f = integrand,
lower =
Expand All @@ -142,11 +205,13 @@ postprobDist <- function(x, n,
min(
ifelse(relativeDelta, 1, 1 - delta),
bounds[2]
)
),
delta = delta,
activeBetamixPost = activeBetamixPost,
controlBetamixPost = controlBetamixPost
)

if (intRes$message == "OK") {
return(intRes$value)
intRes$value
} else {
stop(intRes$message)
}
Expand Down
Loading