tests/testthat/test-oc1S.R

context("oc1S: 1-Sample Operating Characteristics")

## test the analytical OC function via brute force simulation
set.seed(12354)

## expect results to be 1% exact
eps <- 1e-2

## here we test against the reference Neuenschwander et al.,
## Statist. Med. 2011, 30, 1618 (*the* double criterion paper)

## Example for Figure 3
s <- 2
theta_ni <- 0.4

theta_a <- 0
alpha <- 0.05
beta  <- 0.2

za <- qnorm(1-alpha)
n1 <- 155
c1 <- theta_ni - za * s / sqrt(n1)

thetaA <- c(theta_a, theta_ni)

## standard NI design, tests only statistical significance to be
## smaller than theta_ni with 1-alpha certainty
decA <- decision1S(1 - alpha, theta_ni, lower.tail=TRUE)

prior <- mixnorm(c(1,0,100), sigma=s)

test_scenario <- function(oc_res, ref) {
    resA <- oc_res - ref
    expect_true(all(abs(resA) < eps))
}

test_that("Classical NI design critical value", expect_true( abs(decision1S_boundary(prior, 155, decA) - c1) < eps))

## n set to give power 80% to detect 0 and type I error 5% for no
## better than theta_ni
test_that("Classical NI design at target    sample size for OCs", test_scenario(oc1S(prior, 155, decA)(thetaA), c(1-beta, alpha)) )
test_that("Classical NI design at increased sample size for OCs", test_scenario(oc1S(prior, 233, decA)(thetaA), c(1-0.08, alpha)) )
test_that("Classical NI design at decreased sample size for OCs", test_scenario(oc1S(prior,  77, decA)(thetaA), c(1-0.45, alpha)) )

## now double criterion with indecision point (mean estimate must be
## lower than this)
theta_c <- c1

## statistical significance
dec1 <- decision1S(1-alpha, theta_ni, lower.tail=TRUE)
## require mean to be at least as good as theta_c
dec2 <- decision1S(0.5, theta_c, lower.tail=TRUE)
## combination
decComb <- decision1S(c(1-alpha, 0.5), c(theta_ni, theta_c), lower.tail=TRUE)

thetaD <- c(theta_c, theta_ni)

## since theta_c == c1, both decision criteria are the same for n =
## 155
test_that("Double criterion NI design at target    sample size for OCs, combined      ", test_scenario(oc1S(prior, 155, decComb)(thetaD), c(0.50, alpha)) )
test_that("Double criterion NI design at target    sample size for OCs, stat criterion", test_scenario(oc1S(prior, 155, dec1)(thetaD),    c(0.50, alpha)) )
test_that("Double criterion NI design at target    sample size for OCs, mean criterion", test_scenario(oc1S(prior, 155, dec2)(thetaD),    c(0.50, alpha)) )

## at an increased sample size only the mean criterion is active
test_that("Double criterion NI design at increased sample size for OCs, combined      ", test_scenario(oc1S(prior, 233, decComb)(thetaD), c(0.50, 0.02)) )
test_that("Double criterion NI design at increased sample size for OCs, mean criterion", test_scenario(oc1S(prior, 233, dec2)(thetaD),    c(0.50, 0.02)) )

## at a  decreased sample size only the stat criterion is active
test_that("Double criterion NI design at decreased sample size for OCs, combined      ", test_scenario(oc1S(prior,  78, decComb)(thetaD), c(1-0.68, alpha)) )
test_that("Double criterion NI design at decreased sample size for OCs, stat criterion", test_scenario(oc1S(prior,  78, dec1)(thetaD),    c(1-0.68, alpha)) )

## test type 1 error and correctness of critical values wrt to
## lower.tail=TRUE/FALSE
dec1b <- decision1S(1-alpha, theta_ni, lower.tail=FALSE)

## design object, decision function, posterior function must return
## posterior after updatding the prior with the given value
test_critical_discrete <- function(crit, decision, posterior) {
    lower.tail <- attr(decision, "lower.tail")
    if(lower.tail) {
        expect_equal(decision(posterior(crit-1)), 1)
        expect_equal(decision(posterior(crit  )), 1)
        expect_equal(decision(posterior(crit+1)), 0)
    } else {
        expect_equal(decision(posterior(crit-1)), 0)
        expect_equal(decision(posterior(crit  )), 0)
        expect_equal(decision(posterior(crit+1)), 1)
    }
}

## binary case
beta_prior <- mixbeta(c(1, 1, 1))
design_binary <- oc1S(beta_prior, 1000, dec1)
design_binaryB <- oc1S(beta_prior, 1000, dec1b)
crit1 <- decision1S_boundary(beta_prior, 1000, dec1)
crit1B <- decision1S_boundary(beta_prior, 1000, dec1b)
posterior_binary <- function(r) postmix(beta_prior, r=r, n=1000)
test_that("Binary type I error rate", test_scenario(design_binary(theta_ni), alpha))
test_that("Binary crticial value, lower.tail=TRUE",  test_critical_discrete(crit1,  dec1,  posterior_binary))
test_that("Binary crticial value, lower.tail=FALSE", test_critical_discrete(crit1B, dec1b, posterior_binary))

test_that("Binary boundary case, lower.tail=TRUE",  expect_numeric(design_binary( 1), lower=0, upper=1, finite=TRUE, any.missing=FALSE))
test_that("Binary boundary case, lower.tail=FALSE", expect_numeric(design_binaryB(0), lower=0, upper=1, finite=TRUE, any.missing=FALSE))

## poisson case
gamma_prior <- mixgamma(c(1, 2, 2))
dec_count  <- decision1S(1-alpha, 1, lower.tail=TRUE)
dec_countB <- decision1S(1-alpha, 1, lower.tail=FALSE)
design_poisson  <- oc1S(gamma_prior, 1000, dec_count)
design_poissonB <- oc1S(gamma_prior, 1000, dec_countB)
pcrit1 <- decision1S_boundary(gamma_prior, 1000, dec_count)
pcrit1B <- decision1S_boundary(gamma_prior, 1000, dec_countB)
posterior_poisson <- function(m) postmix(gamma_prior, m=m/1000, n=1000)
test_that("Poisson type I error rate", test_scenario(design_poisson(1), alpha) )
test_that("Poisson critical value, lower.tail=TRUE",  test_critical_discrete(pcrit1,  dec_count,  posterior_poisson))
test_that("Poisson critical value, lower.tail=FALSE", test_critical_discrete(pcrit1B, dec_countB, posterior_poisson))

Try the RBesT package in your browser

Any scripts or data that you put into this service are public.

RBesT documentation built on Aug. 22, 2023, 1:08 a.m.