testthat::context("lexpand sanity checks") testthat::test_that("lexpand arguments can be passed as symbol, expression, character name of variable, and symbol of a character variable", { popEpi:::skip_normally() sr <- copy(sire)[dg_date < ex_date, ][1:100,] sr[, id := as.character(1:.N)] x <- lexpand(sr, fot = c(0, Inf), birth = "bi_date", entry = dg_date, exit = "ex_date", status = status %in% 1:2, id = "id") x2 <- lexpand(sr, fot = c(0, Inf), birth = bi_date, entry = "dg_date", exit = ex_date, status = status %in% 1:2, id = id) x3 <- lexpand(sr, fot = c(0, Inf), birth = bi_date, entry = dg_date, exit = ex_date, status = status %in% 1:2, id = id) testthat::expect_identical(x, x2) testthat::expect_identical(x, x3) }) testthat::test_that("original total pyrs equals pyrs after splitting w/ large number of breaks", { popEpi:::skip_normally() x <- copy(sire)[dg_date < ex_date, ] x[, fot := get.yrs(ex_date, year.length = "actual") - get.yrs(dg_date, year.length = "actual")] totpyrs <- x[, sum(fot)] x <- lexpand(sire, birth = bi_date, entry = dg_date, exit = ex_date, status = status %in% 1:2, breaks=list(fot= seq(0,20,1/12), age= c(0:100, Inf), per= c(1960:2014))) setDT(x) totpyrs_split <- x[, sum(lex.dur)] testthat::expect_equal(totpyrs, totpyrs_split, tolerance = 1e-05) }) testthat::test_that("pp not added to data if pp = FALSE but pop.haz is", { x <- lexpand(sire[dg_date < ex_date, ][0:100], birth = bi_date, entry = dg_date, exit = ex_date, status = status %in% 1:2, breaks=list(fot=0:5), pophaz=data.table(popEpi::popmort), pp = FALSE) testthat::expect_equal(intersect(names(x), c("pp", "pop.haz")), "pop.haz") testthat::expect_true(!any(is.na(x$pop.haz))) }) testthat::test_that("lexpand produces the same results with internal/external dropping", { popEpi:::skip_normally() x <- lexpand(sire[dg_date < ex_date, ], birth = bi_date, entry = dg_date, exit = ex_date, status = status %in% 1:2, breaks=list(fot=0:5), pophaz=data.table(popEpi::popmort), pp = TRUE, drop = TRUE) x2 <-lexpand(sire[dg_date < ex_date, ], birth = bi_date, entry = dg_date, exit = ex_date, status = status %in% 1:2, breaks=list(fot=0:5), pophaz=data.table(popEpi::popmort), pp = TRUE, drop = FALSE) x2 <-popEpi:::intelliDrop(x2, breaks = list(fot=0:5), dropNegDur = TRUE) setDT(x) setDT(x2) popEpi:::doTestBarrage(dt1 = x, dt2 = x2, allScales = c("fot", "per", "age")) }) testthat::test_that("lexpanding with aggre.type = 'unique' works", { popEpi:::skip_normally() BL <- list(fot = 0:5, age = seq(0,100, 5)) ag1 <- lexpand(sire[dg_date < ex_date, ], breaks = BL, status = status, birth = bi_date, entry = dg_date, exit = ex_date) setDT(ag1) ag1 <- ag1[, list(pyrs = sum(lex.dur), from0to1 = sum(lex.Xst == 1L)), keyby = list(fot = popEpi:::cutLow(fot, BL$fot), age = popEpi:::cutLow(age, BL$age))] ag2 <- lexpand(sire[dg_date < ex_date, ], breaks = BL, status = status, birth = bi_date, entry = dg_date, exit = ex_date, aggre = list(fot, age), aggre.type = "unique") setDT(ag2) testthat::expect_equal(ag1$pyrs, ag2$pyrs) testthat::expect_equal(ag1$from0to1, ag2$from0to1) }) testthat::test_that("lexpanding with aggre.type = 'cartesian' works; no time scales used", { popEpi:::skip_normally() BL <- list(fot = c(0,Inf)) ag1 <- lexpand(sire[dg_date < ex_date, ], breaks = BL, status = status, entry.status = 0L, birth = bi_date, entry = dg_date, exit = ex_date) setDT(ag1) forceLexisDT(ag1, breaks = BL, allScales = c("fot", "per", "age")) e <- quote(list(sex = factor(sex, 0:1, c("m", "f")), period = cut(get.yrs(dg_date), get.yrs(as.Date(paste0(seq(1970, 2015, 5), "-01-01")))))) ag1[, c("sex", "period") := eval(e)] ceejay <- do.call(CJ, lapply(ag1[, list(sex, period)], function(x) {if (is.factor(x)) levels(x) else unique(x)})) setkey(ceejay, sex, period); setkey(ag1, sex, period) ag1 <- ag1[ceejay, list(pyrs = sum(lex.dur), from0to1 = sum(lex.Xst == 1L)), by = .EACHI] ag1[is.na(pyrs), pyrs := 0] ag1[is.na(from0to1), from0to1 := 0] ag2 <- lexpand(sire[dg_date < ex_date, ], breaks = BL, status = status, entry.status = 0L, birth = bi_date, entry = dg_date, exit = ex_date, aggre = list(sex = factor(sex, 0:1, c("m", "f")), period = cut(get.yrs(dg_date), get.yrs(as.Date(paste0(seq(1970, 2015, 5), "-01-01"))))), aggre.type = "cartesian") setDT(ag2) setkeyv(ag1, c("sex", "period")) setkeyv(ag2, c("sex", "period")) testthat::expect_equal(sum(ag1$pyrs), sum(ag2$pyrs)) testthat::expect_equal(sum(ag1$from0to1), sum(ag2$from0to1)) testthat::expect_equal(ag1$pyrs, ag2$pyrs) testthat::expect_equal(ag1$from0to1, ag2$from0to1) }) testthat::test_that("lexpanding with aggre.type = 'cartesian' works; only time scales used", { popEpi:::skip_normally() BL <- list(fot = 0:5, age = seq(0,100, 5)) ag1 <- lexpand(sire[dg_date < ex_date, ], breaks = BL, status = status, entry.status = 0L, birth = bi_date, entry = dg_date, exit = ex_date) setDT(ag1) forceLexisDT(ag1, breaks = BL, allScales = c("fot", "per", "age")) ag3 <- aggre(ag1, by = list(fot, age), type = "cartesian") setDT(ag3) ag4 <- aggre(ag1, by = list(fot, age), type = "unique") setDT(ag4) ag1[, `:=`(fot = try2int(popEpi:::cutLow(fot, c(BL$fot, Inf))), age = try2int(popEpi:::cutLow(age, c(BL$age, Inf))))] ceejay <- do.call(CJ, lapply(BL, function(x) x[-length(x)])) setkey(ceejay, fot, age); setkey(ag1, fot, age) ag1 <- ag1[ceejay, list(pyrs = sum(lex.dur), from0to1 = sum(lex.Xst == 1L)), by = .EACHI] ag1[is.na(pyrs), pyrs := 0] ag1[is.na(from0to1), from0to1 := 0] ag2 <- lexpand(sire[dg_date < ex_date, ], breaks = list(fot = 0:5, age = seq(0,100, 5)), status = status, entry.status = 0L, birth = bi_date, entry = dg_date, exit = ex_date, aggre = list(fot, age), aggre.type = "cartesian") setDT(ag2) setkeyv(ag1, c("fot", "age")) setkeyv(ag2, c("fot", "age")) setkeyv(ag3, c("fot", "age")) testthat::expect_equal(sum(ag1$pyrs), sum(ag3$pyrs)) testthat::expect_equal(sum(ag1$from0to1), sum(ag3$from0to1)) testthat::expect_equal(ag1$pyrs, ag3$pyrs) testthat::expect_equal(ag1$from0to1, ag3$from0to1) testthat::expect_equal(sum(ag1$pyrs), sum(ag2$pyrs)) testthat::expect_equal(sum(ag1$from0to1), sum(ag2$from0to1)) testthat::expect_equal(ag1$pyrs, ag2$pyrs) testthat::expect_equal(ag1$from0to1, ag2$from0to1) }) testthat::test_that("lexpanding and aggregating to years works", { ag1 <- lexpand(sire[dg_date < ex_date, ], breaks = list(per=2000:2014), status = status, birth = bi_date, entry = dg_date, exit = ex_date) setDT(ag1) ag1[, `:=`(per = as.integer(popEpi:::cutLow(per, 2000:2014)))] ag1 <- ag1[, list(pyrs = sum(lex.dur), from0to1 = sum(lex.Xst == 1L)), keyby = per] ag2 <- lexpand(sire[dg_date < ex_date, ], breaks = list(per = 2000:2014), status = status, birth = bi_date, entry = dg_date, exit = ex_date, aggre = list(per), aggre.type = "unique") setDT(ag2) ag3 <- lexpand(sire[dg_date < ex_date, ], breaks = list(per = 2000:2014, age = c(seq(0,100,5),Inf), fot = c(0:10, Inf)), status = status, birth = bi_date, entry = dg_date, exit = ex_date, aggre = list(y = per), aggre.type = "unique") setDT(ag3) testthat::expect_equal(ag1$pyrs, ag2$pyrs) testthat::expect_equal(ag1$from0to1, ag2$from0to1) testthat::expect_equal(ag1$pyrs, ag3$pyrs) testthat::expect_equal(ag1$from0to1, ag3$from0to1) }) # Aggre check (to totpyrs) ----------------------------------------------------- testthat::test_that("lexpand aggre produces correct results", { popEpi:::skip_normally() x <- copy(sire)[dg_date < ex_date, ] x[, fot := get.yrs(ex_date, year.length = "actual") - get.yrs(dg_date, year.length = "actual")] totpyrs <- x[, sum(fot)] counts <- x[, .N, by = .(status)] x <- lexpand(sire[dg_date < ex_date, ], birth = bi_date, entry = dg_date, exit = ex_date, breaks=list(fot=c(0,5,10,50,Inf), age=c(seq(0,85,5),Inf), per = 1993:2013), status=status, aggre = list(fot, age, per)) setDT(x) row_length <- x[,list( length(unique(age)), length(unique(per)), length(unique(fot)))] testthat::expect_equal( x[,sum(pyrs)], totpyrs, tolerance = 0.001) testthat::expect_equal( x[,sum(from0to0)], counts[1,N]) testthat::expect_equal( x[,sum(from0to1)], counts[2,N]) testthat::expect_equal( x[,sum(from0to2)], counts[3,N]) #expect_equal( prod(row_length), x[,.N]) }) testthat::test_that('lexpand aggre: multistate column names correct', { x <- lexpand(sire[dg_date < ex_date, ][0:100], birth = bi_date, entry = dg_date, exit = ex_date, breaks=list(fot=c(0,5,10,50,Inf), age=c(seq(0,85,5),Inf), per = 1993:2013), status=status, aggre = list(fot, age, per)) testthat::expect_equal(intersect(names(x), c('from0to0','from0to1','from0to2')), c('from0to0','from0to1','from0to2')) }) # overlapping time lines -------------------------------------------------- testthat::test_that('lexpansion w/ overlapping = TRUE/FALSE produces double/undoubled pyrs', { popEpi:::skip_normally() sire2 <- copy(sire)[dg_date < ex_date, ][1:100] sire2[, dg_yrs := get.yrs(dg_date, "actual")] sire2[, ex_yrs := get.yrs(ex_date, "actual")] sire2[, bi_yrs := get.yrs(bi_date, "actual")] sire2[, id := 1:.N] sire2 <- sire2[rep(1:.N, each=2)] sire2[seq(2,.N, by=2), dg_yrs := (ex_yrs + dg_yrs)/2L] sire2[, dg_age := dg_yrs-bi_yrs] x <- lexpand(sire2, birth = "bi_yrs", entry = "bi_yrs", event="dg_yrs", exit = "ex_yrs", status="status", entry.status = 0L, id = "id", overlapping = TRUE) setDT(x) testthat::expect_equal(x[, sum(lex.dur), keyby=lex.id]$V1, sire2[, sum(ex_yrs-bi_yrs), keyby=id]$V1) x <- lexpand(sire2, birth = "bi_yrs", entry = "bi_yrs", event="dg_yrs", exit = "ex_yrs", status="status", entry.status = 0L, id = "id", overlapping = FALSE) setDT(x) testthat::expect_equal(x[, sum(lex.dur), keyby=lex.id]$V1, sire2[!duplicated(id), sum(ex_yrs-bi_yrs), keyby=id]$V1) }) testthat::test_that("different specifications of time vars work with event defined and overlapping=FALSE", { dt <- data.table(bi_date = as.Date('1949-01-01'), dg_date = as.Date(paste0(1999:2000, "-01-01")), start = as.Date("1997-01-01"), end = as.Date('2002-01-01'), status = c(1,2), id=1) ## birth -> entry -> event -> exit x1 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = start, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE) testthat::expect_equal(x1$lex.dur, c(2,1,2)) testthat::expect_equal(x1$age, c(48,50,51)) testthat::expect_equal(x1$lex.Cst, 0:2) testthat::expect_equal(x1$lex.Xst, c(1,2,2)) ## birth -> entry = event -> exit testthat::expect_error( lexpand(data = dt, subset = NULL, birth = bi_date, entry = dg_date, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE), regexp = paste0("some rows have simultaneous 'entry' and 'event', ", "which is not supported with overlapping = FALSE; ", "perhaps separate them by one day?") ) ## birth = entry -> event -> exit x3 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = bi_date, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE) testthat::expect_equal(x3$lex.dur, c(50,1,2)) testthat::expect_equal(x3$age, c(0,50,51)) testthat::expect_equal(x3$lex.Cst, 0:2) testthat::expect_equal(x3$lex.Xst, c(1,2,2)) ## birth -> entry -> event = exit testthat::expect_error( lexpand(data = dt, subset = NULL, birth = bi_date, entry = dg_date, exit = end, event = end, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE), regexp = paste0("subject\\(s\\) defined by lex.id had several rows ", "where 'event' time had the same value, which is not ", "supported with overlapping = FALSE; perhaps separate ", "them by one day?") ) ## birth = entry -> event -> exit x6 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = bi_date, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE) testthat::expect_equal(x6$lex.dur, c(50,1,2)) testthat::expect_equal(x6$age, c(0,50,51)) testthat::expect_equal(x6$lex.Cst, 0:2) testthat::expect_equal(x6$lex.Xst, c(1,2,2)) }) testthat::test_that("lexpand drops persons outside breaks window correctly", { popEpi:::skip_normally() dt <- data.table(bi_date = as.Date('1949-01-01'), dg_date = as.Date(paste0(2000, "-01-01")), start = as.Date("1997-01-01"), end = as.Date('2002-01-01'), status = c(2), id=1) ## by age x1 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = start, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE, breaks = list(age = 50:55)) testthat::expect_equal(x1$age, c(50, 51, 52)) ## by period x1 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = start, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE, breaks = list(per = 2000:2005)) testthat::expect_equal(x1$per, c(2000, 2001)) ## by fot x1 <- lexpand(data = dt, subset = NULL, birth = bi_date, entry = start, exit = end, event = dg_date, id = id, overlapping = FALSE, entry.status = 0, status = status, merge = FALSE, breaks = list(fot = 2:5)) testthat::expect_equal(x1$fot, c(2, 3, 4)) })