tests/testthat/test-data_combine.R

library(multinma)
library(dplyr)

test_that("combine_network error if not passed nma_data objects", {
  msg <- "Expecting to combine objects of class `nma_data`, created using set_\\* functions"

  expect_error(combine_network(1), msg)
  expect_error(combine_network(1, 2), msg)
  expect_error(combine_network(1, set_agd_arm(smoking, studyn, trtc, r = r, n = n)), msg)
  expect_error(combine_network(set_agd_arm(smoking, studyn, trtc, r = r, n = n), 1), msg)
})

# Dummy data
agd_arm <- tibble(
  studyn = c(1, 1, 2, 2, 2),
  studyc = letters[studyn],
  studyf = factor(studyc),
  studyf2 = factor(studyc, levels = letters[5:1]),
  trtn = c(1, 2, 1, 2, 3),
  trtc = LETTERS[trtn],
  trtf = factor(trtc),
  trtf2 = factor(trtc, levels = LETTERS[4:1]),
  tclassn = c(1, 2, 1, 2, 2),
  tclassc = letters[tclassn],
  tclassf = factor(tclassc, levels = letters[1:3]),
  tclassf2 = factor(tclassc, levels = letters[3:1]),
  y = rnorm(5),
  se = runif(5)
)
net_a_a <- set_agd_arm(agd_arm, studyf, trtf, y = y, se = se)
net_a_a2 <- set_agd_arm(agd_arm, studyf2, trtf2, y = y, se = se)

agd_contrast <- tibble(
  studyn = c(3, 3, 3),
  studyc = letters[studyn],
  studyf = factor(studyc),
  studyf2 = factor(studyc, levels = letters[5:1]),
  trtn = c(2, 3, 4),
  trtc = LETTERS[trtn],
  trtf = factor(trtc),
  trtf2 = factor(trtc, levels = LETTERS[4:1]),
  tclassn = c(2, 2, 3),
  tclassc = letters[tclassn],
  tclassf = factor(tclassc, levels = letters[1:3]),
  tclassf2 = factor(tclassc, levels = letters[3:1]),
  tclassn_bad = c(3, 3, 3),
  y = c(NA, rnorm(2)),
  se = c(0.5, 1, 1)
)
net_a_c <- set_agd_contrast(agd_contrast, studyf, trtf, y = y, se = se)
net_a_c2 <- set_agd_contrast(agd_contrast, studyf2, trtf2, y = y, se = se)

ipd <- tibble(
  studyn = c(4, 4, 4, 5, 5),
  studyc = letters[studyn],
  studyf = factor(studyc),
  studyf2 = factor(studyc, levels = letters[5:1]),
  trtn = c(1, 2, 3, 1, 4),
  trtc = LETTERS[trtn],
  trtf = factor(trtc),
  trtf2 = factor(trtc, levels = LETTERS[4:1]),
  tclassn = c(1, 2, 2, 1, 3),
  tclassc = letters[tclassn],
  tclassf = factor(tclassc, levels = letters[1:3]),
  tclassf2 = factor(tclassc, levels = letters[3:1]),
  tclassn_bad = c(1, 3, 3, 3, 4),
  y = rnorm(5)
)
net_i <- set_ipd(ipd, studyf, trtf, y = y)
net_i2 <- set_ipd(ipd, studyf2, trtf2, y = y)

test_that("combine_network produces combined treatment, class, and study factors", {
  # Note: original_levels attribute unset because levels differ in sub-networks

  c1 <- combine_network(net_a_a, net_i)
  expect_equal(c1$treatments, .default(factor(LETTERS[1:4])))
  expect_equal(levels(c1$agd_arm$.trt), LETTERS[1:4])
  expect_equal(levels(c1$ipd$.trt), LETTERS[1:4])
  expect_equal(c1$studies, factor(letters[c(1, 2, 4, 5)]))
  expect_equal(levels(c1$agd_arm$.study), letters[c(1, 2, 4, 5)])
  expect_equal(levels(c1$ipd$.study), letters[c(1, 2, 4, 5)])

  c2 <- combine_network(net_a_a, net_i, net_a_c)
  expect_equal(c2$treatments, .default(factor(LETTERS[c(2, 1, 3, 4)],
                                              levels = LETTERS[c(2, 1, 3, 4)])))
  expect_equal(levels(c2$agd_arm$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(levels(c2$agd_contrast$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(levels(c2$ipd$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(c2$studies, factor(letters[1:5]))
  expect_equal(levels(c2$agd_arm$.study), letters[1:5])
  expect_equal(levels(c2$agd_contrast$.study), letters[1:5])
  expect_equal(levels(c2$ipd$.study), letters[1:5])

  c1_classed <- combine_network(
    set_agd_arm(agd_arm, studyf, trtf, y = y, se = se, trt_class = tclassc),
    set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassc)
  )
  # Reference trt is A
  expect_equal(c1_classed$treatments, .default(factor(LETTERS[1:4])))
  expect_equal(levels(c1_classed$agd_arm$.trt), LETTERS[1:4])
  expect_equal(levels(c1_classed$ipd$.trt), LETTERS[1:4])
  expect_equal(c1_classed$studies, factor(letters[c(1, 2, 4, 5)]))
  expect_equal(levels(c1_classed$agd_arm$.study), letters[c(1, 2, 4, 5)])
  expect_equal(levels(c1_classed$ipd$.study), letters[c(1, 2, 4, 5)])
  expect_equal(c1_classed$classes, factor(letters[c(1, 2, 2, 3)]))
  expect_equal(levels(c1_classed$agd_arm$.trtclass), letters[1:3])
  expect_equal(levels(c1_classed$ipd$.trtclass), letters[1:3])

  c2_classed <- combine_network(
    set_agd_arm(agd_arm, studyf, trtf, y = y, se = se, trt_class = tclassc),
    set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassc),
    set_agd_contrast(agd_contrast, studyf, trtf, y = y, se = se, trt_class = tclassc)
  )
  # Reference treatment is B
  expect_equal(c2_classed$treatments, .default(factor(LETTERS[c(2, 1, 3, 4)],
                                                      levels = LETTERS[c(2, 1, 3, 4)])))
  expect_equal(levels(c2_classed$agd_arm$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(levels(c2_classed$agd_contrast$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(levels(c2_classed$ipd$.trt), LETTERS[c(2, 1, 3, 4)])
  expect_equal(c2_classed$studies, factor(letters[1:5]))
  expect_equal(levels(c2_classed$agd_arm$.study), letters[1:5])
  expect_equal(levels(c2_classed$agd_contrast$.study), letters[1:5])
  expect_equal(levels(c2_classed$ipd$.study), letters[1:5])
  expect_equal(c2_classed$classes, factor(letters[c(2, 1, 2, 3)], levels = c(letters[c(2, 1, 3)])))
  expect_equal(levels(c2_classed$agd_arm$.trtclass), letters[c(2, 1, 3)])
  expect_equal(levels(c2_classed$ipd$.trtclass), letters[c(2, 1, 3)])
  expect_equal(levels(c2_classed$agd_contrast$.trtclass), letters[c(2, 1, 3)])
})

test_that("combine_network produces combined treatment, class, and study factors from explicit factors", {
  # Note: original_levels attribute now set because levels are explicitly the same in sub-networks

  c1 <- combine_network(net_a_a2, net_i2)
  c1_trtf <- .default(factor(LETTERS[c(1, 4:2)], levels = LETTERS[c(1, 4:2)]))
  attr(c1_trtf, "original_levels") <- LETTERS[4:1]
  expect_equal(c1$treatments, c1_trtf)
  expect_equal(levels(c1$agd_arm$.trt), LETTERS[c(1, 4:2)])
  expect_equal(levels(c1$ipd$.trt), LETTERS[c(1, 4:2)])
  c1_studyf <- factor(letters[c(5, 4, 2, 1)], levels = letters[c(5, 4, 2, 1)])
  attr(c1_studyf, "original_levels") <- letters[5:1]
  expect_equal(c1$studies, c1_studyf)
  expect_equal(levels(c1$agd_arm$.study), letters[c(5, 4, 2, 1)])
  expect_equal(levels(c1$ipd$.study), letters[c(5, 4, 2, 1)])

  c2 <- combine_network(net_a_a2, net_i2, net_a_c2)
  c2_trtf <- .default(factor(LETTERS[c(2, 4, 3, 1)], levels = LETTERS[c(2, 4, 3, 1)]))
  attr(c2_trtf, "original_levels") <- LETTERS[4:1]
  expect_equal(c2$treatments, c2_trtf)
  expect_equal(levels(c2$agd_arm$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c2$agd_contrast$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c2$ipd$.trt), LETTERS[c(2, 4, 3, 1)])
  c2_studyf <- factor(letters[5:1], levels = letters[5:1])
  attr(c2_studyf, "original_levels") <- letters[5:1]
  expect_equal(c2$studies, c2_studyf)
  expect_equal(levels(c2$agd_arm$.study), letters[5:1])
  expect_equal(levels(c2$agd_contrast$.study), letters[5:1])
  expect_equal(levels(c2$ipd$.study), letters[5:1])

  c1_classed <- combine_network(
    set_agd_arm(agd_arm, studyf2, trtf2, y = y, se = se, trt_class = tclassf2),
    set_ipd(ipd, studyf2, trtf2, y = y, trt_class = tclassf2)
  )
  # Reference trt is A
  expect_equal(c1_classed$treatments, c1_trtf)
  expect_equal(levels(c1_classed$agd_arm$.trt), LETTERS[c(1, 4:2)])
  expect_equal(levels(c1_classed$ipd$.trt), LETTERS[c(1, 4:2)])
  expect_equal(c1_classed$studies, c1_studyf)
  expect_equal(levels(c1_classed$agd_arm$.study), letters[c(5, 4, 2, 1)])
  expect_equal(levels(c1_classed$ipd$.study), letters[c(5, 4, 2, 1)])
  c1_classf <- factor(letters[c(1, 3, 2, 2)], levels = letters[c(1, 3, 2)])
  attr(c1_classf, "original_levels") <- letters[3:1]
  expect_equal(c1_classed$classes, c1_classf)
  expect_equal(levels(c1_classed$agd_arm$.trtclass), letters[c(1, 3, 2)])
  expect_equal(levels(c1_classed$ipd$.trtclass), letters[c(1, 3, 2)])

  c2_classed <- combine_network(
    set_agd_arm(agd_arm, studyf2, trtf2, y = y, se = se, trt_class = tclassf2),
    set_ipd(ipd, studyf2, trtf2, y = y, trt_class = tclassf2),
    set_agd_contrast(agd_contrast, studyf2, trtf2, y = y, se = se, trt_class = tclassf2)
  )
  # Reference treatment is B
  expect_equal(c2_classed$treatments, c2_trtf)
  expect_equal(levels(c2_classed$agd_arm$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c2_classed$agd_contrast$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c2_classed$ipd$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(c2_classed$studies, c2_studyf)
  expect_equal(levels(c2_classed$agd_arm$.study), letters[5:1])
  expect_equal(levels(c2_classed$agd_contrast$.study), letters[5:1])
  expect_equal(levels(c2_classed$ipd$.study), letters[5:1])
  c2_classf <- factor(letters[c(2, 3, 2, 1)], levels = c(letters[c(2, 3, 1)]))
  attr(c2_classf, "original_levels") <- letters[3:1]
  expect_equal(c2_classed$classes, c2_classf)
  expect_equal(levels(c2_classed$agd_arm$.trtclass), letters[c(2, 3, 1)])
  expect_equal(levels(c2_classed$ipd$.trtclass), letters[c(2, 3, 1)])
  expect_equal(levels(c2_classed$agd_contrast$.trtclass), letters[c(2, 3, 1)])

  # Check that unused levels are dropped
  c3_classed <- combine_network(
    set_agd_arm(agd_arm,
                forcats::fct_expand(studyf2, "xxx"),
                forcats::fct_expand(trtf2, "yyy"),
                y = y, se = se,
                trt_class = forcats::fct_expand(tclassf2, "zzz")),
    set_ipd(ipd,
            forcats::fct_expand(studyf2, "xxx"),
            forcats::fct_expand(trtf2, "yyy"),
            y = y,
            trt_class = forcats::fct_expand(tclassf2, "zzz")),
    set_agd_contrast(agd_contrast,
                     forcats::fct_expand(studyf2, "xxx"),
                     forcats::fct_expand(trtf2, "yyy"),
                     y = y, se = se,
                     trt_class = forcats::fct_expand(tclassf2, "zzz")))

  # Reference treatment is B
  c3_trtf <- c2_trtf
  attr(c3_trtf, "original_levels") <- c(attr(c3_trtf, "original_levels"), "yyy")
  expect_equal(c3_classed$treatments, c3_trtf)
  expect_equal(levels(c3_classed$agd_arm$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c3_classed$agd_contrast$.trt), LETTERS[c(2, 4, 3, 1)])
  expect_equal(levels(c3_classed$ipd$.trt), LETTERS[c(2, 4, 3, 1)])
  c3_studyf <- c2_studyf
  attr(c3_studyf, "original_levels") <- c(attr(c3_studyf, "original_levels"), "xxx")
  expect_equal(c3_classed$studies, c3_studyf)
  expect_equal(levels(c3_classed$agd_arm$.study), letters[5:1])
  expect_equal(levels(c3_classed$agd_contrast$.study), letters[5:1])
  expect_equal(levels(c3_classed$ipd$.study), letters[5:1])
  c3_classf <- factor(letters[c(2, 3, 2, 1)], levels = c(letters[c(2, 3, 1)]))
  attr(c3_classf, "original_levels") <- c(letters[3:1], "zzz")
  expect_equal(c3_classed$classes, c3_classf)
  expect_equal(levels(c3_classed$agd_arm$.trtclass), letters[c(2, 3, 1)])
  expect_equal(levels(c3_classed$ipd$.trtclass), letters[c(2, 3, 1)])
  expect_equal(levels(c3_classed$agd_contrast$.trtclass), letters[c(2, 3, 1)])
})

test_that("combine_network can set alternative trt_ref", {
  c1 <- combine_network(net_a_a, net_i, net_a_c, trt_ref = "C")
  expect_equal(c1$treatments, factor(LETTERS[c(3, 1, 2, 4)], levels = LETTERS[c(3, 1, 2, 4)]))
  expect_equal(levels(c1$agd_arm$.trt), LETTERS[c(3, 1, 2, 4)])
  expect_equal(levels(c1$agd_contrast$.trt), LETTERS[c(3, 1, 2, 4)])
  expect_equal(levels(c1$ipd$.trt), LETTERS[c(3, 1, 2, 4)])

  expect_error(combine_network(net_a_a, net_i, net_a_c, trt_ref = 2),
               "does not match a treatment.*Suitable values are: A, B, C, D")
  expect_error(combine_network(net_a_a, net_a_c,
                               set_ipd(mutate(ipd, trtf = factor(LETTERS[3:7])),
                                       studyf, trtf, y = y),
                               trt_ref = 2),
               "does not match a treatment.*Suitable values are: A, B, C, D, E, \\.\\.\\.")

  expect_error(combine_network(net_a_a, net_a_c,
                               set_ipd(mutate(ipd, studyf = factor("a")),
                                       studyf, trtf, y = y)),
               "Studies with same label found in multiple data sources: a")
  expect_error(combine_network(net_a_a, net_a_a),
               "Studies with same label found in multiple data sources: a, b")

  c1_classed <- combine_network(
    set_agd_arm(agd_arm, studyf, trtf, y = y, se = se, trt_class = tclassc),
    set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassc),
    set_agd_contrast(agd_contrast, studyf, trtf, y = y, se = se, trt_class = tclassc),
    trt_ref = "C"
  )
  expect_equal(c1_classed$treatments, factor(LETTERS[c(3, 1, 2, 4)], levels = LETTERS[c(3, 1, 2, 4)]))
  expect_equal(levels(c1_classed$agd_arm$.trt), LETTERS[c(3, 1, 2, 4)])
  expect_equal(levels(c1_classed$agd_contrast$.trt), LETTERS[c(3, 1, 2, 4)])
  expect_equal(levels(c1_classed$ipd$.trt), LETTERS[c(3, 1, 2, 4)])
  expect_equal(c1_classed$classes, factor(letters[c(2, 1, 2, 3)], levels = letters[c(2, 1, 3)]))
  expect_equal(levels(c1_classed$agd_arm$.trtclass), letters[c(2, 1, 3)])
  expect_equal(levels(c1_classed$agd_contrast$.trtclass), letters[c(2, 1, 3)])
  expect_equal(levels(c1_classed$ipd$.trtclass), letters[c(2, 1, 3)])
})

test_that("combine_network error if outcomes do not match for same data source type", {
  m <- "Multiple outcome types present"
  dat_a <- tibble(study = 1, trt = 1:2, r = 1, n = 1, y = 1, se = 1)
  dat_b <- tibble(study = 2, trt = 2:3, r = 1, n = 1, y = 1, se = 1)

  expect_error(combine_network(set_ipd(dat_a, study, trt, r = r),
                               set_ipd(dat_b, study, trt, y = y)), m)
  expect_error(combine_network(set_agd_arm(dat_a, study, trt, r = r, n = n),
                               set_agd_arm(dat_b, study, trt, y = y, se = se)), m)
})

test_that("combine_network error if mismatch outcomes across data types", {
  m <- "Combining.+not supported"
  dat_a <- tibble(study = 1, trt = 1:2, r = 1, n = 1, E = 1, y = 1, se = 1)
  dat_b <- tibble(study = 2, trt = 2:3, r = 1, n = 1, E = 1, y = 1, se = 1)

  expect_error(combine_network(set_ipd(dat_a, study, trt, r = r),
                               set_agd_arm(dat_b, study, trt, y = y, se = se)), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(n, r, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, y = y, se = se)), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(n, r, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = r, n = n)), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = r, E = E),
                               set_agd_arm(dat_b, study, trt, y = y, se = se)), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, y = y),
                               set_agd_arm(dat_b, study, trt, r = r, n = n)), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, y = y),
                               set_agd_arm(dat_b, study, trt, r = multi(n, r, inclusive = TRUE))), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = r),
                               set_agd_arm(dat_b, study, trt, r = multi(n, r, inclusive = TRUE))), m)
  expect_error(combine_network(set_ipd(dat_a, study, trt, y = y),
                               set_agd_arm(dat_b, study, trt, r = r, E = E)), m)
})

test_that("combine_network error if multinomial outcomes mismatched", {
  dat_a <- tibble(study = 1, trt = 1:2, a = 1, b = 1, c = 0)
  dat_b <- tibble(study = 2, trt = 2:3, a = 1, b = 1, c = 0)

  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(a, b, inclusive = TRUE))),
               "different numbers of categories")
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(b, a, c, inclusive = TRUE))),
               "different category labels")
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(A = a, B = b, C = c, inclusive = TRUE))),
               "different category labels")

  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_ipd(dat_b, study, trt, r = multi(a, b, inclusive = TRUE))),
               "different numbers of categories")
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_ipd(dat_b, study, trt, r = multi(b, a, c, inclusive = TRUE))),
               "different category labels")
  expect_error(combine_network(set_ipd(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_ipd(dat_b, study, trt, r = multi(A = a, B = b, C = c, inclusive = TRUE))),
               "different category labels")

  expect_error(combine_network(set_agd_arm(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(a, b, inclusive = TRUE))),
               "different numbers of categories")
  expect_error(combine_network(set_agd_arm(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(b, a, c, inclusive = TRUE))),
               "different category labels")
  expect_error(combine_network(set_agd_arm(dat_a, study, trt, r = multi(a, b, c, inclusive = TRUE)),
                               set_agd_arm(dat_b, study, trt, r = multi(A = a, B = b, C = c, inclusive = TRUE))),
               "different category labels")

  # Check combining ordered and competing outcomes is disallowed, when competing are implemented
})

test_that("combine_network error if treatment classes do not match across sources", {
  m <- "Treatment present in more than one class"

  expect_error(combine_network(
    set_agd_arm(agd_arm, studyf, trtf, y = y, se = se, trt_class = tclassn),
    set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassn_bad)), m)

  expect_error(combine_network(
    set_agd_arm(agd_arm, studyf, trtf, y = y, se = se, trt_class = tclassn),
    set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassn_bad),
    set_agd_contrast(agd_contrast, studyf, trtf, y = y, se = se, trt_class = tclassn_bad)), m)
})

test_that("combine_network warns if not all sources have treatment classes", {
  expect_warning(combine_network(net_a_a,
                                 set_ipd(ipd, studyf, trtf, y = y, trt_class = tclassc)),
                 "Not all data sources have defined treatment classes")
})

test_that("combine_network works combining survival outcomes from same type of ipd/agd source", {
  expect_equivalent(combine_network(set_agd_surv(filter(ndmm_agd, study == "Morgan2012"), studyf, trtf,
                                                 Surv = Surv(eventtime, status),
                                                 covariates = ndmm_agd_covs),
                                    set_agd_surv(filter(ndmm_agd, study != "Morgan2012"), studyf, trtf,
                                                 Surv = Surv(eventtime, status),
                                                 covariates = ndmm_agd_covs))$agd_arm,
                    set_agd_surv(ndmm_agd, studyf, trtf,
                                 Surv = Surv(eventtime, status),
                                 covariates = ndmm_agd_covs)$agd_arm)

  expect_equivalent(combine_network(set_ipd(filter(ndmm_agd, study == "Morgan2012"), studyf, trtf,
                                                 Surv = Surv(eventtime, status)),
                                    set_ipd(filter(ndmm_agd, study != "Morgan2012"), studyf, trtf,
                                                 Surv = Surv(eventtime, status)))$ipd,
                    set_ipd(ndmm_agd, studyf, trtf,
                                 Surv = Surv(eventtime, status))$ipd)
})

Try the multinma package in your browser

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

multinma documentation built on June 22, 2024, 9:10 a.m.