tests/testthat/test-cea.R

context("cea.R unit tests")
library("data.table")

# Output for testing ----------------------------------------------------------
n_samples <- 50

# cost
c <- vector(mode = "list", length = 6)
names(c) <- c("Strategy 1, Grp 1", "Strategy 1, Grp 2", "Strategy 2, Grp 1",
              "Strategy 2, Grp 2", "Strategy 3, Grp 1", "Strategy 3, Grp 2")
c[[1]] <- rlnorm(n_samples, 2, .1)
c[[2]] <- rlnorm(n_samples, 2, .1)
c[[3]] <- rlnorm(n_samples, 11, .15)
c[[4]] <- rlnorm(n_samples, 11, .15)
c[[5]] <- rlnorm(n_samples, 11, .15)
c[[6]] <- rlnorm(n_samples, 11, .15)

# effectiveness
e <- c
e[[1]] <- rnorm(n_samples, 8, .2)
e[[2]] <- rnorm(n_samples, 8, .2)
e[[3]] <- rnorm(n_samples, 10, .8)
e[[4]] <- rnorm(n_samples, 10.5, .8)
e[[5]] <- rnorm(n_samples, 8.5, .6)
e[[6]] <- rnorm(n_samples, 11, .6)

# cost and effectiveness by strategy and simulation
ce <- data.table(sample = rep(seq(n_samples), length(e)),
                 strategy = rep(paste0("Strategy ", seq(1, 3)), 
                           each = n_samples * 2),
                 grp = rep(rep(c("Group 1", "Group 2"),
                               each = n_samples), 3),
                 cost = do.call("c", c), qalys = do.call("c", e))

ce2 <- copy(ce)
setnames(ce2, c("sample", "strategy", "grp"), c("samp", "strategy_name", "group"))

# net benefits by willingess to pay
krange <- seq(0, 200000, by = 25000)
kval1 <- sample(krange, 1)
kval2 <- sample(krange, 1)
ce[, nmb1 := qalys * kval1 - cost]
ce[, nmb2 := qalys * kval2 - cost]

# Functions to use for testing ------------------------------------------------
# probabilistic sensitivity analysis
ceaR <- function(x, kval, grpname){
  x <- x[grp == grpname] 
  x[, nmb := qalys * kval - cost]
  nmb <- dcast(x, sample ~ strategy, value.var = "nmb")
  strategies <- seq(1, ncol(nmb) - 1)
  nmb_names <- paste0("nmb", strategies)
  setnames(nmb, colnames(nmb), c("sample", nmb_names))
  nmb[, maxj := apply(nmb[, -1, with = FALSE], 1, which.max)]
  nmb[, maxj := factor(maxj, levels = strategies)]
  prob_ce <- as.numeric(prop.table(table(nmb$maxj)))
  enmb <- as.numeric(nmb[, lapply(.SD, mean), .SDcols = nmb_names])
  enmb_maxj <- which.max(enmb)
  ret <- list()
  
  # mce
  ret$mce <- prob_ce
  
  # CEAF
  ret$ceaf <- prob_ce[enmb_maxj]
  
  # evpi
  nmb[, nmbpi := apply(nmb[, 2:(ncol(nmb) -1), with = FALSE], 1, max)]
  nmb$nmbci <- nmb[[nmb_names[enmb_maxj]]]
  vpi <- nmb$nmbpi - nmb$nmbci
  ret$evpi <- mean(vpi)
  
  # return
  return(ret)
}

# incemental changes
deltaR <- function(x, comparator, grpname){
  x <- x[grp == grpname]
  x.comparator <- x[strategy == comparator]
  x.treat <- x[strategy != comparator]
  x.treat.qalys <- dcast(x.treat, sample ~ strategy, value.var = c("qalys"))
  x.treat.cost <- dcast(x.treat, sample ~ strategy, value.var = c("cost"))
  delta.qalys <- x.treat.qalys[, -1, with = FALSE] - x.comparator$qalys
  delta.cost <- x.treat.cost[, -1, with = FALSE] - x.comparator$cost
  n_samples <- max(x$sample)
  ret <- data.table(sample = seq(1, n_samples), 
                    strategy = rep(unique(x.treat$strategy), each = n_samples),
                    grp = grpname,
                    ie = c(as.matrix(delta.qalys)), 
                    ic = c(as.matrix(delta.cost)))
  return(ret)
}

# ceac 
ceacR <- function(ix, kval, grpname) {
  ix <- ix[grp == grpname]
  ix[, nmb := ie * kval - ic] 
  ceac <- ix[, .(prob = mean(nmb >= 0)), by = "strategy"]
}

# Test cea() -------------------------------------------------------------------
cea_out <-  cea(ce, k = krange, sample = "sample", strategy = "strategy",
                grp = "grp", e = "qalys", c = "cost")

test_that("cea() produced expected results", {
  
  # Function gets expected results
  kval <- sample(krange, 1)
  ceaR_1 <- ceaR(ce, kval , "Group 1")
  ceaR_2 <- ceaR(ce, kval , "Group 2")
  
  ## Summary
  ### Group 2
  ce_mean <- ce[grp == "Group 2", .(e_mean = mean(qalys), 
                                     c_mean = mean(cost)), by = "strategy"]
  ce_lower <- ce[grp == "Group 2", .(e_lower = quantile(qalys, .025), 
                                     c_lower = quantile(cost, .025)), by = "strategy"]
  ce_upper <- ce[grp == "Group 2", .(e_upper = quantile(qalys, .975), 
                                     c_upper = quantile(cost, .975)), by = "strategy"]
  summary_test <- data.table(strategy = ce_mean$strategy, 
                             e_mean = ce_mean$e_mean,
                             e_lower = ce_lower$e_lower, 
                             e_upper = ce_upper$e_upper,
                             c_mean = ce_mean$c_mean, 
                             c_lower = ce_lower$c_lower,
                             c_upper = ce_upper$c_upper)
  expect_equal(summary_test, cea_out$summary[grp == "Group 2", -2, with = FALSE])
  
  # MCE
  ### Group 1
  mce <- cea_out$mce[grp == "Group 1" &  k == kval]
  mce_test <- ceaR_1$mce
  expect_equal(mce$prob, mce_test)
  
  ### Group 2
  mce <- cea_out$mce[grp == "Group 2" &  k == kval]
  mce_test <- ceaR_2$mce
  expect_equal(mce$prob, mce_test)
  
  ## CEAF
  ### Group 1
  ceaf <- cea_out$mce[best == 1 & grp == "Group 1" &  k == kval]
  ceaf_test <- ceaR_1$ceaf
  expect_equal(ceaf$prob, ceaf_test)
  
  ### Group 2
  ceaf <- cea_out$mce[best == 1 & grp == "Group 2" &  k == kval]
  ceaf_test <- ceaR_2$ceaf
  expect_equal(ceaf$prob, ceaf_test)  
  
  ## EVPI
  ### Group 1
  evpi <- cea_out$evpi[grp == "Group 1" &  k == kval]
  evpi_test <- ceaR_1$evpi
  expect_equal(evpi$evpi, evpi_test)
  
  # Function works with non-default names
  cea_out2 <-  cea(ce2, k = krange, sample = "samp", strategy = "strategy_name",
               grp = "group", e = "qalys", c = "cost")
  evpi_v2 <- cea_out2$evpi[group == "Group 1" &  k == kval]
  expect_equal(evpi_v2$evpi, evpi$evpi)
})

# Test cea_pw() ----------------------------------------------------------------
cea_pw_out <-  cea_pw(ce, k = krange, comparator = "Strategy 1",
                      sample = "sample", strategy = "strategy", grp = "grp",
                       e = "qalys", c = "cost")
cea_pw_out2 <- cea_pw(ce2,  k = krange, comparator = "Strategy 1",
                      sample = "samp", strategy = "strategy_name", grp = "group",
                       e = "qalys", c = "cost")

test_that("cea_pw() produces expected results", {
  
  ### function gets expected results
  kval <- sample(krange, 1)
  
  ## delta
  delta <- cea_pw_out$delta
  delta_test <- deltaR(ce, comparator = "Strategy 1", grpname = "Group 1")
  expect_equal(delta[grp == "Group 1"], delta_test)
  
  ## summary
  # group 2
  delta_mean <- delta[grp == "Group 2", .(ie_mean = mean(ie), 
                                    ic_mean = mean(ic)), by = "strategy"]
  delta_lower <- delta[grp == "Group 2", .(ie_lower = quantile(ie, .025), 
                                     ic_lower = quantile(ic, .025)), by = "strategy"]
  delta_upper <- delta[grp == "Group 2", .(ie_upper = quantile(ie, .975), 
                                     ic_upper = quantile(ic, .975)), by = "strategy"]
  icer <- delta_mean$ic_mean/delta_mean$ie_mean
  summary_test <- data.table::data.table(strategy = delta_mean$strategy, 
                                         ie_mean = delta_mean$ie_mean,
                                         ie_lower = delta_lower$ie_lower, 
                                         ie_upper = delta_upper$ie_upper,
                                         ic_mean = delta_mean$ic_mean, 
                                         ic_lower = delta_lower$ic_lower,
                                         ic_upper = delta_upper$ic_upper, 
                                         icer = icer)
  expect_equal(summary_test, cea_pw_out$summary[grp == "Group 2", -2, with = FALSE])
  
  ## ceac
  # group 1
  ceac <- cea_pw_out$ceac[grp == "Group 1" & k == kval]
  ceac_test <- ceacR(delta, kval = kval, grpname = "Group 1")
  expect_equal(ceac$prob, ceac_test$prob)
  
  # group 2
  ceac <- cea_pw_out$ceac[grp == "Group 2" & k == kval]
  ceac_test <- ceacR(delta, kval = kval, grpname = "Group 2")
  expect_equal(ceac$prob, ceac_test$prob)
  
  ## inmb
  # group 2
  inmb <- cea_pw_out$inmb[k == kval & grp == "Group 2"]
  einmb_test <- delta[grp == "Group 2", .(einmb = mean(ie * kval - ic)), 
                     by = "strategy"]
  expect_equal(inmb$einmb, einmb_test$einmb)
  
  # Function works with non-default names
  ceac_v2 <- cea_pw_out2$ceac[group == "Group 2" & k == kval]
  expect_equal(ceac$prob, ceac_v2$prob)

})

# Test icer_tbl() --------------------------------------------------------------
test_that("icer_tbl() produces expected results", {
  # No "credible interval"
  expect_warning(icer <- icer_tbl(cea_pw_out))
  expect_true(inherits(icer, "list"))
  expect_true(inherits(icer[[1]], "matrix"))
  
  # With "credible interval"
  expect_warning(icer <- icer_tbl(cea_pw_out, cri = TRUE))
  expect_true(inherits(icer, "list"))
  
  # data.table output
  expect_warning(icer <- icer_tbl(cea_pw_out, output = "data.table"))
  expect_true(inherits(icer, "data.table"))
  
  # Single group with output = "matrix"
  cea_pw_out2 <-  cea_pw(ce[grp == "Group 1"],  k = krange, comparator = "Strategy 1",
                         sample = "sample", strategy = "strategy", e = "qalys", c = "cost")
  expect_warning(icer <- icer_tbl(cea_pw_out2))
  expect_true(inherits(icer, "matrix"))
  expect_equal(ncol(icer), 3)
  
  # Single group with output = "matrix" and drop = FALSE
  expect_warning(icer <- icer_tbl(cea_pw_out2, drop = FALSE))
  expect_true(inherits(icer, "list"))
  
  # Specifying row and column names
  cols <- c("S1", "S2", "S3")
  rows <- c("iqalys", "icosts", "inmb", "icer", "conclusion")
  expect_warning(icer <- icer_tbl(cea_pw_out2, colnames = cols, rownames = rows))
  expect_true(inherits(icer, "matrix"))
  expect_equal(colnames(icer), cols)
  expect_equal(rownames(icer), rows)
  
  # Expect errors
  expect_error(expect_warning(icer_tbl(2)))
  expect_error(expect_warning(icer_tbl(cea_pw_out, prob = 1.4)))
})

# Test icer() ------------------------------------------------------------------
labs <- list("strategy" = c("s1" = "Strategy 1",
                            "s2" = "Strategy 2", 
                            "s3" = "Strategy 3"),
             "grp" = c("g1" = "Group 1", 
                       "g2" = "Group 2"))

test_that("icer() and format.icer() return the correct columns", {
  # icer()
  x <- icer(cea_pw_out2)
  expect_equal(colnames(x),
               c("strategy", "grp", "outcome", "estimate", "lower", "upper"))
  
  # Formatting
  ## Pivoting
  ### Default
  y <- format(x)
  expect_true("Strategy 2" %in% colnames(y))
  
  ### No pivoting
  y <- format(x, pivot_from = NULL)
  expect_equal(colnames(y), c("Strategy", "Group", "Outcome", "Value"))

  ### Pivot strategy
  y <- format(x, pivot_from = "strategy")
  expect_true("Strategy 3" %in% colnames(y))
  
  ### Pivot group
  y <- format(x, pivot_from = "grp")
  expect_true("Group 1" %in% colnames(y))
  
  ### Pivot group and outcome
  y <- format(x, pivot_from = c("grp", "outcome"))
  expect_true(!"Outcome" %in% colnames(y))
  expect_true(!"Group" %in% colnames(y))
})

test_that("icer() correctly passes labels", {
  x <- icer(cea_pw_out, labels = labs)
  expect_equal(c("s2", "s3"), as.character(unique(x$strategy)))
  expect_equal(c("g1", "g2"), as.character(unique(x$grp)))
})

test_that("format.icer() will drop groups", {
  z <- cea_pw(ce[grp == "Group 1"], 
              k = krange, comparator = "Strategy 1",
              sample = "sample", strategy = "strategy", grp = "grp",
                         e = "qalys", c = "cost")
  x <- format(icer(z))
  expect_true(!"grp" %in% colnames(x))
})

# Test plot_ceplane() ----------------------------------------------------------
p <- plot_ceplane(cea_pw_out, labels = labs)

test_that("plot_ceplane() returns ggplot", {
  expect_true(inherits(p, "ggplot"))
})

test_that("plot_ceplane() correctly passes labels", {
  expect_equal(levels(p$data$strategy), names(labs$strategy))
  expect_equal(levels(p$data$grp), names(labs$grp))
})

test_that("plot_ceplane() throws error if 'x' is wrong class", {
  expect_error(plot_ceplane(2),
               "'x' must be of class 'cea_pw'.")
})

# Test plot_ceac() -------------------------------------------------------------
p1 <- plot_ceac(cea_out, labels = labs)
p2 <- plot_ceac(cea_pw_out, labels = labs)

test_that("plot_ceac returns ggplot from cea object", {
  expect_true(inherits(p1, "ggplot"))
})

test_that("plot_ceac returns ggplot from cea_pw object", {
  expect_true(inherits(p2, "ggplot"))
})

test_that("plot_ceac works with no labels", {
  expect_true(inherits(plot_ceac(cea_out), "ggplot"))
})

# Test plot_ceaf() -------------------------------------------------------------
p <- plot_ceaf(cea_out, labels = labs)

test_that("plot_ceaf() only uses data for optimal treatment strategy", {
  expect_equal(unique(p$data$best), 1)
})

test_that("plot_ceaf() throws error if 'x' is wrong class", {
  expect_error(plot_ceaf(2),
               "'x' must be of class 'cea'.")
})

# Test plot_evpi() -------------------------------------------------------------
test_that("plot_evpi() throws error if 'x' is wrong class", {
  expect_error(plot_evpi(2),
               "'x' must be of class 'cea'.")
})

test_that("plot_evpi() works with one group", {
  z <- cea(ce[grp == "Group 1"], k = krange, sample = "sample", 
           strategy = "strategy", grp = "grp", e = "qalys", c = "cost")
  expect_true(inherits(plot_evpi(z), "ggplot"))
})

# Test incr_effect() -----------------------------------------------------------
test_that("incr_effect", {
  # Default
  delta <- incr_effect(ce, comparator = "Strategy 1", sample = "sample", 
                       strategy = "strategy", grp = "grp",
                       outcomes = c("cost", "qalys"))
  expect_equal(delta[strategy == "Strategy 2" & grp == "Group 1", icost][1], 
               ce[strategy == "Strategy 2" & grp == "Group 1", cost][1] -
                 ce[strategy == "Strategy 1" & grp == "Group 1", cost][1])
  expect_equal(delta[strategy == "Strategy 2" & grp == "Group 2", icost][5], 
               ce[strategy == "Strategy 2" & grp == "Group 2", cost][5] -
                 ce[strategy == "Strategy 1" & grp == "Group 2", cost][5])
  
  # Without group
  ce2 <- ce[grp == "Group 1"]
  ce2[, grp := NULL]
  delta <- incr_effect(ce2, comparator = "Strategy 1", sample = "sample", 
                       strategy = "strategy",
                       outcomes = c("cost", "qalys"))  
  expect_equal(delta[strategy == "Strategy 2", icost][3], 
               ce[strategy == "Strategy 2", cost][3] -
               ce[strategy == "Strategy 1", cost][3])
})

Try the hesim package in your browser

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

hesim documentation built on Sept. 4, 2022, 1:06 a.m.