Skip to content

Commit

Permalink
Updated output to message format
Browse files Browse the repository at this point in the history
  • Loading branch information
elliecurnow committed Sep 30, 2024
1 parent 0ec706c commit c64eced
Show file tree
Hide file tree
Showing 43 changed files with 1,882 additions and 1,404 deletions.
11 changes: 7 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ Description: A guidance system for analysis with missing data. It incorporates
expert, up-to-date methodology to help researchers choose the most
appropriate analysis approach when some data are missing. You provide the
available data and the assumed causal structure, including the likely causes
of missing data. 'midoc' will advise whether multiple imputation is needed, and
if so, how best to perform it.
of missing data. `midoc` will advise which analysis approaches can be used,
and how best to perform them. `midoc` follows the framework for the treatment
and reporting of missing data in observational studies (TARMOS). Lee et al
(2021). <doi:10.1016/j.jclinepi.2021.01.008>.
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
Suggests:
knitr,
shiny,
testthat (>= 3.0.0)
testthat
Config/testthat/edition: 3
Imports:
arm,
Expand All @@ -35,7 +37,8 @@ Imports:
mice (>= 3.16.0),
rlang,
rmarkdown,
stats
stats,
utils
VignetteBuilder: knitr
Depends:
R (>= 3.6)
Expand Down
73 changes: 32 additions & 41 deletions R/checkcra.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,73 +26,64 @@
#' the proposed DAG and analysis model outcome and covariate(s)
#' @export
#'
#' @references Hughes R, Heron J, Sterne J, Tilling K. 2019. Accounting for
#' missing data in statistical analyses: multiple imputation is not always the
#' answer. Int J Epidemiol. <doi:10.1093/ije/dyz032>
#'
#' Bartlett JW, Harel O, Carpenter JR. 2015. Asymptotically Unbiased
#' Estimation of Exposure Odds Ratios in Complete Records Logistic Regression.
#' Am J Epidemiol. <doi:10.1093/aje/kwv114>
#'
#' @examples
#' # Example DAG for which complete records analysis is not valid, but could be
#' ## valid for a different set of covariates
#' ## valid for a different set of covariates
#' checkCRA(y="bmi7", covs="matage", r_cra="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r")
#' ## For the DAG in the example above, complete records analysis is valid
#' ## if a different set of covariates is used
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r")
#' # For the DAG in the example above, complete records analysis is valid
#' ## if a different set of covariates is used
#' checkCRA(y="bmi7", covs="matage mated", r_cra="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r")
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r")
#'
#' # Example DAG for which complete records is not valid, but could be valid
#' ## for a different estimand
#' ## for a different estimand
#' checkCRA(y="bmi7", covs="matage mated", r_cra="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r matage -> bmi3 mated -> bmi3 bmi3 -> bmi7
#' bmi3 -> r")
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r matage -> bmi3
#' mated -> bmi3 bmi3 -> bmi7 bmi3 -> r")
#'
#' # Example DAG for which complete records analysis is not valid
#' # Example DAG for which complete records analysis is never valid
#' checkCRA(y="bmi7", covs="matage mated", r_cra="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r bmi7 -> r")
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r bmi7 -> r")
checkCRA <- function(y, covs, r_cra, mdag) {
mdagspec <- paste('dag {',mdag,'}')
covsvec <- unlist(strsplit(covs," "))
#If r does not depend on y conditional on covariates, then CRA is valid
if(dagitty::dseparated(dagitty::dagitty(mdagspec, layout=T), y, r_cra, covsvec)){
cat(strwrap("Based on the proposed directed acyclic graph (DAG),
the analysis model outcome and complete record indicator are independent
given analysis model covariates. Hence, complete records analysis is valid."),"\n",fill=TRUE)
result <- paste("Based on the proposed directed acyclic graph (DAG), the analysis model outcome and complete record indicator are independent given analysis model covariates. Hence, complete records analysis is valid.", collapse="\n")
}
else {
cat(strwrap("Based on the proposed directed acyclic graph (DAG),
the analysis model outcome and complete record indicator are not independent
given analysis model covariates.
Hence, in general, complete records analysis is not valid."),"\n",
strwrap("In special cases, depending on the type of analysis model and estimand of interest, complete
records analysis may still be valid. See, for example, Bartlett et al. (2015)
(https://doi.org/10.1093/aje/kwv114) for further details."),"\n", fill=TRUE)
result1 <- paste("Based on the proposed directed acyclic graph (DAG), the analysis model outcome and complete record indicator are not independent given analysis model covariates. Hence, in general, complete records analysis is not valid. \n \nIn special cases, depending on the type of analysis model and estimand of interest, complete records analysis may still be valid. See, for example, Bartlett et al. (2015) (https://doi.org/10.1093/aje/kwv114) for further details.\n",collapse = "\n")

adjsets <- dagitty::adjustmentSets(mdagspec,exposure=c(covsvec,r_cra),outcome=y,type = "all")
adjsetsfull <- dagitty::adjustmentSets(mdagspec,exposure=r_cra,outcome=y,type = "all")
if(length(adjsets)==0 & length(adjsetsfull)==0){
cat(strwrap("There are no other variables which could be added to the model to make
the analysis model outcome and complete record indicator conditionally independent. Consider
using a different strategy e.g. multiple imputation."),"\n", fill=TRUE)
result2 <- paste("There are no other variables which could be added to the model to make the analysis model outcome and complete record indicator conditionally independent. Consider using a different strategy e.g. multiple imputation.",collapse = "\n")
}
if(length(adjsets)==0 & length(adjsetsfull)>0){
cat(strwrap("There are no other variables which could be added to the model to make
the analysis model outcome and complete record indicator conditionally independent,
without changing the estimand of interest."),"\n",
strwrap("Consider using a different strategy e.g.
multiple imputation. Alternatively, consider whether a different estimand could
be of interest. For example, the analysis model outcome and complete record
indicator are independent given each of the following sets of variables:"),"\n", fill=TRUE)
print(adjsetsfull)
result2 <- paste("There are no other variables which could be added to the model to make the analysis model outcome and complete record indicator conditionally independent, without changing the estimand of interest. Consider using a different strategy e.g. multiple imputation. \n \nAlternatively, consider whether a different estimand could be of interest. For example, the analysis model outcome and complete record indicator are independent given each of the following sets of variables:\n \n",
paste0(adjsetsfull, prefix="\n", collapse = "\n"),collapse = "\n")
#print(adjsetsfull)
}
if(length(adjsets)>0){
cat(strwrap("Consider using a different analysis model and/or strategy, e.g. multiple imputation.
\nFor example, the analysis model outcome and complete record indicator are independent
if, in addition to the specified covariates, the following sets of variables are included
as covariates in the analysis model (note that this list is not necessarily exhaustive,
particularly if your DAG is complex):"),"\n", fill=TRUE)
print(adjsets)
result2 <- paste("Consider using a different analysis model and/or strategy, e.g. multiple imputation. \n \nFor example, the analysis model outcome and complete record indicator are independent if, in addition to the specified covariates, the following sets of variables are included as covariates in the analysis model (note that this list is not necessarily exhaustive, particularly if your DAG is complex):\n \n", paste0(adjsets, prefix="\n", collapse = "\n"), collapse = "\n")
#print(adjsets)
}
result <- paste(result1, "\n", result2, collapse="\n")
}
message(paste(strwrap(result),collapse="\n"))
}


42 changes: 21 additions & 21 deletions R/checkmi.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,44 @@
#' proposed DAG and imputation model
#' @export
#'
#' @references Curnow E, Tilling K, Heron JE, Cornish RP, Carpenter JR. 2023.
#' Multiple imputation of missing data under missing at random: including a
#' collider as an auxiliary variable in the imputation model can induce bias.
#' Frontiers in Epidemiology. <doi:10.3389/fepid.2023.1237447>
#'
#' @examples
#' # Example DAG for which multiple imputation is valid
#' checkMI(dep="bmi7", preds="matage mated pregsize", r_dep="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r pregsize -> bmi7 pregsize -> bwt sep_unmeas -> bwt")
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r pregsize -> bmi7
#' pregsize -> bwt sep_unmeas -> bwt")
#'
#' # Example DAG for which multiple imputation is not valid, due to a collider
#' checkMI(dep="bmi7", preds="matage mated bwt", r_dep="r",
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7 sep_unmeas ->
#' mated sep_unmeas -> r pregsize -> bmi7 pregsize -> bwt sep_unmeas -> bwt")
#' mdag="matage -> bmi7 mated -> matage mated -> bmi7
#' sep_unmeas -> mated sep_unmeas -> r pregsize -> bmi7
#' pregsize -> bwt sep_unmeas -> bwt")
checkMI <- function(dep, preds, r_dep, mdag) {
mdagspec <- paste('dag {',mdag,'}')
predsvec <- unlist(strsplit(preds," "))
#If r_dep does not depend on dep conditional on predictors, then MI is valid
if(dagitty::dseparated(dagitty::dagitty(mdagspec, layout=T), dep, r_dep, predsvec)){
cat(strwrap("Based on the proposed directed acyclic graph (DAG),
the incomplete variable and its missingness indicator are independent
given imputation model predictors. Hence, multiple imputation methods which
assume data are missing at random are valid in principle."), fill=TRUE)
result <- paste("Based on the proposed directed acyclic graph (DAG), the incomplete variable and its missingness indicator are independent given imputation model predictors. Hence, multiple imputation methods which assume data are missing at random are valid in principle.", collapse="\n")
} else {
cat(strwrap("Based on the proposed directed acyclic graph (DAG),
the incomplete variable and its missingness indicator are not independent
given imputation model predictors. Hence, multiple imputation methods which
assume data are missing at random are not valid."),"\n",
strwrap("Consider using a different imputation model and/or strategy (e.g. not-at-random
fully conditional specification)."),"\n",fill=TRUE)
result1 <- paste("Based on the proposed directed acyclic graph (DAG), the incomplete variable and its missingness indicator are not independent given imputation model predictors. Hence, multiple imputation methods which assume data are missing at random are not valid. \n \nConsider using a different imputation model and/or strategy (e.g. not-at-random fully conditional specification).",
collapse="\n")
adjsets_r <- dagitty::adjustmentSets(mdagspec,exposure=c(predsvec,r_dep),outcome=dep,type = "all")
adjsets_dep <- dagitty::adjustmentSets(mdagspec,exposure=c(predsvec,dep),outcome=r_dep,type = "all")
if(length(adjsets_r)>0) (adjsets <- adjsets_r)
else (adjsets <- adjsets_dep)
if(length(adjsets)>0){
cat(strwrap("For example, the incomplete variable and its missingness indicator are
independent if, in addition to the specified predictors, the following sets of
variables are included as predictors in the imputation model
(note that this list is not necessarily exhaustive, particularly if your DAG is complex):"),"\n",fill=TRUE)
print(adjsets)
}
}
result2 <- paste("For example, the incomplete variable and its missingness indicator are independent if, in addition to the specified predictors, the following sets of variables are included as predictors in the imputation model (note that this list is not necessarily exhaustive, particularly if your DAG is complex):\n \n",
paste0(adjsets, prefix="\n", collapse = "\n"),collapse = "\n")
#print(adjsets)
}
result <- paste(result1, "\n", result2, collapse = "\n")
}
message(paste(strwrap(result),collapse="\n"))
}


Expand Down
Loading

0 comments on commit c64eced

Please sign in to comment.