diff --git a/R/Data.R b/R/Data.R index 8094c96..1874600 100644 --- a/R/Data.R +++ b/R/Data.R @@ -176,6 +176,11 @@ validate.RoboDataTTE <- function(data, ref_arm){ if(!is.null(data$event)){ data$event <- as.vector(data$event[[1]]) } + if(ncol(data$exposure) == 0){ + data$exposure <- NULL + } else { + data$exposure <- as.vector(data$exposure[[1]]) + } if(ncol(data$strata) == 0){ data$strata <- NULL } diff --git a/R/adjust-glm.R b/R/adjust-glm.R index ae7dffb..add9571 100644 --- a/R/adjust-glm.R +++ b/R/adjust-glm.R @@ -12,6 +12,9 @@ predictions.GLMModel <- function(model, data, mod){ if(!is.null(dmat)){ df <- cbind(df, dmat) } + if(!is.null(data$exposure)){ + df <- cbind(df, exposure=data$exposure) + } preds <- stats::predict(mod, newdata=df, type="response") return(preds) } diff --git a/R/adjust-linear.R b/R/adjust-linear.R index ce160d8..e4991ea 100644 --- a/R/adjust-linear.R +++ b/R/adjust-linear.R @@ -35,7 +35,12 @@ linmod.ANOVA <- function(model, data, family=stats::gaussian, center=TRUE){ treat=data$treat, response=data$response ) - mod <- fitmod(family=family, formula=response ~ 0 + treat, data=df) + if(is.null(data$exposure)){ + mod <- fitmod(family=family, formula=response ~ 0 + treat, data=df) + } else { + df <- cbind(df, exposure=data$exposure) + mod <- fitmod(family=family, formula=response ~ 0 + treat + offset(exposure), data=df) + } return(mod) } @@ -48,10 +53,21 @@ linmod.ANCOVA <- function(model, data, family=stats::gaussian, center=TRUE){ dmat <- get.dmat(data, model$adj_vars) if(center) dmat <- .center.dmat(dmat) df <- cbind(df, dmat) + if(!is.null(data$exposure)){ + df <- cbind(df, exposure=data$exposure) + } if(center){ - mod <- fitmod(family=family, formula=response ~ 0 + treat + ., data=df) + if(is.null(data$exposure)){ + mod <- fitmod(family=family, formula=response ~ 0 + treat + ., data=df) + } else { + mod <- fitmod(family=family, formula=response ~ 0 + treat + . - exposure + offset(exposure), data=df) + } } else { - mod <- fitmod(family=family, formula=response ~ 1 + treat + ., data=df) + if(is.null(data$exposure)){ + mod <- fitmod(family=family, formula=response ~ 1 + treat + ., data=df) + } else { + mod <- fitmod(family=family, formula=response ~ 1 + treat + . - exposure + offset(exposure), data=df) + } } return(mod) } @@ -65,10 +81,21 @@ linmod.ANHECOVA <- function(model, data, family=stats::gaussian, center=TRUE){ if(center) dmat <- .center.dmat(dmat) df <- cbind(df, dmat) + if(!is.null(data$exposure)){ + df <- cbind(df, exposure=data$exposure) + } if(center){ - mod <- fitmod(family=family, response ~ 0 + treat:., data=df) + if(is.null(data$exposure)){ + mod <- fitmod(family=family, response ~ 0 + treat:., data=df) + } else { + mod <- fitmod(family=family, response ~ 0 + treat:(. - exposure) + offset(exposure), data=df) + } } else { - mod <- fitmod(family=family, response ~ 1 + treat:., data=df) + if(is.null(data$exposure)){ + mod <- fitmod(family=family, response ~ 1 + treat:., data=df) + } else { + mod <- fitmod(family=family, response ~ 1 + treat:(. - exposure) + offset(exposure), data=df) + } } return(mod) } diff --git a/R/robincar-SL.R b/R/robincar-SL.R index f072031..03a8a7e 100644 --- a/R/robincar-SL.R +++ b/R/robincar-SL.R @@ -92,7 +92,8 @@ robincar_SL <- function(df, treat_col=treat_col, response_col=response_col, strata_cols=strata_cols, - covariate_cols=covariate_cols + covariate_cols=covariate_cols, + exposure_col=NULL ) validate(data) diff --git a/R/robincar-covhr.R b/R/robincar-covhr.R index 40fdee6..9b9bd64 100644 --- a/R/robincar-covhr.R +++ b/R/robincar-covhr.R @@ -36,7 +36,8 @@ robincar_covhr <- function(df, response_col=response_col, event_col=event_col, strata_cols=strata_cols, - covariate_cols=covariate_cols + covariate_cols=covariate_cols, + exposure_col=NULL ) validate(data, ref_arm) diff --git a/R/robincar-glm.R b/R/robincar-glm.R index fb8874a..c3fc5fd 100644 --- a/R/robincar-glm.R +++ b/R/robincar-glm.R @@ -20,13 +20,14 @@ #' If you wish to use a negative binomial working model with an unknown dispersion parameter, then use `g_family="nb"`. #' @param g_accuracy Level of accuracy to check prediction un-biasedness. #' @param formula An optional formula to use for adjustment specified using as.formula("..."). This overrides strata_cols and covariate_cols. +#' @param exposure_col An offset variable to use for Poisson or negative binomial working models #' #' @export robincar_glm <- function(df, treat_col, response_col, strata_cols=NULL, covariate_cols=NULL, car_scheme="simple", adj_method="heterogeneous", # vcovHC="HC0", covariate_to_include_strata=NULL, - g_family=stats::gaussian, g_accuracy=7, formula=NULL, + g_family=stats::gaussian, g_accuracy=7, formula=NULL, exposure_col=NULL, contrast_h=NULL, contrast_dh=NULL){ .check.car_scheme(car_scheme) @@ -42,7 +43,8 @@ robincar_glm <- function(df, response_col=response_col, strata_cols=strata_cols, covariate_cols=covariate_cols, - formula=formula + formula=formula, + exposure_col=exposure_col ) validate(data) diff --git a/R/robincar-tte.R b/R/robincar-tte.R index b5178d6..966be85 100644 --- a/R/robincar-tte.R +++ b/R/robincar-tte.R @@ -38,7 +38,8 @@ robincar_tte <- function(df, response_col=response_col, event_col=event_col, strata_cols=strata_cols, - covariate_cols=covariate_cols + covariate_cols=covariate_cols, + exposure_col=NULL ) validate(data, ref_arm) diff --git a/man/robincar_glm.Rd b/man/robincar_glm.Rd index 0b79714..586eef2 100644 --- a/man/robincar_glm.Rd +++ b/man/robincar_glm.Rd @@ -16,6 +16,7 @@ robincar_glm( g_family = stats::gaussian, g_accuracy = 7, formula = NULL, + exposure_col = NULL, contrast_h = NULL, contrast_dh = NULL ) @@ -44,6 +45,8 @@ If you wish to use a negative binomial working model with an unknown dispersion \item{formula}{An optional formula to use for adjustment specified using as.formula("..."). This overrides strata_cols and covariate_cols.} +\item{exposure_col}{An offset variable to use for Poisson or negative binomial working models} + \item{contrast_h}{An optional function to specify a desired contrast} \item{contrast_dh}{An optional jacobian function for the contrast (otherwise use numerical derivative)} diff --git a/tests/testthat/test-glm.R b/tests/testthat/test-glm.R index fd6339d..715b556 100644 --- a/tests/testthat/test-glm.R +++ b/tests/testthat/test-glm.R @@ -159,6 +159,41 @@ test_that("GLM full function -- NEGATIVE binomial, permuted block", { }) +test_that("GLM full function -- NEGATIVE binomial, permuted block w offset", { + + DATA2$offset1 <- DATA2$y + rbinom(n=nrow(DATA2), size=10, prob=0.5) + + # Known dispersion parameter + non <- robincar_glm( + df=DATA2, + response_col="y", + treat_col="A", + strata_cols=c("z1"), + covariate_cols=c("x1"), + car_scheme="permuted-block", + g_family=negative.binomial(1), + g_accuracy=7, + adj_method="heterogeneous", + covariate_to_include_strata=TRUE, + exposure_col="offset1") + expect_equal(class(non), "GLMModelResult") + + # Known dispersion parameter + non <- robincar_glm( + df=DATA2, + response_col="y", + treat_col="A", + strata_cols=c("z1"), + covariate_cols=c("x1"), + car_scheme="permuted-block", + g_family="nb", + g_accuracy=7, + adj_method="heterogeneous", + covariate_to_include_strata=TRUE) + expect_equal(class(non), "GLMModelResult") + +}) + test_that("GLM Settings", { non <- robincar_glm( df=DATA2,