The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

bayesmsm for longitudinal data without right-censoring

Xiao Yan, Kuan Liu

Introduction

Simulated longitudinal observational data without right-censoring

In this vignette, we demonstrate how to simulate a clean longitudinal dataset without censoring using simData(). We generate data for 200 individuals observed over 2 visits. At each visit, two normally distributed covariates (L1_j, L2_j) and a binary treatment assignment (A_j) are created. No censoring is applied, so all covariates, treatments, and the final outcome Y are fully observed. The outcome Y is continuous, generated from a linear model on the covariate and treatment history.

Variable Description
L1_1, L2_1 Baseline covariates (continuous)
L1_2, L2_2 Time-varying covariates at visit 2
A1, A2 Binary treatments at visits 1 and 2
Y Continuous end-of-study outcome
# 1) Define coefficient lists for 2 visits
amodel <- list(
  # Visit 1: logit P(A1=1) = -0.3 + 0.4*L1_1 - 0.2*L2_1
  c("(Intercept)" = -0.3, "L1_1" = 0.4, "L2_1" = -0.2),
  # Visit 2: logit P(A2=1) = -0.1 + 0.3*L1_2 - 0.1*L2_2 + 0.5*A_prev
  c("(Intercept)" = -0.1, "L1_2" = 0.3, "L2_2" = -0.1, "A_prev" = 0.5)
)

# 2) Define binary outcome model: logistic on treatments and last covariates
ymodel <- c(
  "(Intercept)" = -0.8,
  "A1"          = 0.2,
  "A2"          = 0.4,
  "L1_2"        = 0.3,
  "L2_2"        = -0.3
)

# 3) Load package and simulate data without censoring
simdat <- simData(
  n                = 100,
  n_visits         = 2,
  covariate_counts = c(2, 2),
  amodel           = amodel,
  ymodel           = ymodel,
  y_type           = "binary",
  right_censor     = FALSE,
  seed             = 123
)

# 4) Inspect first rows
head(simdat)
#>          L1_1        L2_1 A1        L1_2       L2_2 A2 Y
#> 1 -0.56047565 -0.71040656  1 -0.37560287  1.0149432  0 0
#> 2 -0.23017749  0.25688371  0 -0.56187636 -1.9927485  1 0
#> 3  1.55870831 -0.24669188  0 -0.34391723 -0.4272793  1 0
#> 4  0.07050839 -0.34754260  1  0.09049665  0.1166373  1 1
#> 5  0.12928774 -0.95161857  0  1.59850877 -0.8932076  0 1
#> 6  1.71506499 -0.04502772  1 -0.08856511  0.3339029  1 0

\[ ATE = E(Y \mid A_1 = 1, A_2 = 1) - E(Y \mid A_1 = 0, A_2 = 0) \]

Bayesian treatment effect weight estimation using bayesweight

weights <- bayesweight(
  trtmodel.list = list(
    A1 ~ L1_1 + L2_1,
    A2 ~ L1_2 + L2_2 + A1),
  data = simdat,
  n.chains = 1,
  n.iter = 200,
  n.burnin = 100,
  n.thin = 1,
  seed = 890123,
  parallel = FALSE)
#> Compiling model graph
#>    Resolving undeclared variables
#>    Allocating nodes
#> Graph information:
#>    Observed stochastic nodes: 400
#>    Unobserved stochastic nodes: 10
#>    Total graph size: 1824
#> 
#> Initializing model

summary(weights)
#>              Length Class  Mode     
#> weights      100    -none- numeric  
#> model_string   1    -none- character
cat(weights$model_string)
#> model{
#> #N = nobs
#> for(i in 1:N){
#> 
#> # visit 1;
#> # marginal treatment assignment model, visit 1;
#> A1s[i] ~ dbern(pA1s[i])
#> pA1s[i] <- ilogit(bs10)
#> 
#> # conditional treatment assignment model, visit 1;
#> A1[i] ~ dbern(pA1[i])
#> pA1[i] <- ilogit(b10 + b11*L1_1[i] + b12*L2_1[i])
#> 
#> # visit 2;
#> # marginal treatment assignment model, visit 2;
#> A2s[i] ~ dbern(pA2s[i])
#> pA2s[i] <- ilogit(bs20 + bs21*A1s[i])
#> 
#> # conditional treatment assignment model, visit 2;
#> A2[i] ~ dbern(pA2[i])
#> pA2[i] <- ilogit(b20 + b21*L1_2[i] + b22*L2_2[i] + b23*A1[i])
#> 
#> # export quantity in full posterior specification;
#> w[i] <- (pA1s[i]*pA2s[i])/(pA1[i]*pA2[i])
#> }
#> 
#> #prior;
#> bs10~dnorm(0,.01)
#> b10~dnorm(0,.01)
#> b11~dnorm(0,.01)
#> b12~dnorm(0,.01)
#> bs20~dnorm(0,.01)
#> bs21~dnorm(0,.01)
#> b20~dnorm(0,.01)
#> b21~dnorm(0,.01)
#> b22~dnorm(0,.01)
#> b23~dnorm(0,.01)
#> }

Bayesian non-parametric bootstrap to maximize the utility function with respect to the causal effect using bayesmsm

The function bayesmsm estimates causal effect of time-varying treatments. It uses subject-specific treatment assignment weights weights calculated using bayesweight, and performs Bayesian non-parametric bootstrap to estimate the causal parameters.

model <- bayesmsm(ymodel = Y ~ A1 + A2,
  nvisit = 2,
  reference = c(rep(0,2)),
  comparator = c(rep(1,2)),
  family = "binomial",
  data = simdat,
  wmean = weights$weights,
  nboot = 50,
  optim_method = "BFGS",
  parallel = TRUE,
  seed = 890123,
  ncore = 2)
str(model)
#> List of 12
#>  $ RD_mean    : num 0.147
#>  $ RR_mean    : num 2.05
#>  $ OR_mean    : num 2.71
#>  $ RD_sd      : num 0.113
#>  $ RR_sd      : num 0.907
#>  $ OR_sd      : num 1.56
#>  $ RD_quantile: Named num [1:2] -0.0657 0.3452
#>   ..- attr(*, "names")= chr [1:2] "2.5%" "97.5%"
#>  $ RR_quantile: Named num [1:2] 0.793 3.932
#>   ..- attr(*, "names")= chr [1:2] "2.5%" "97.5%"
#>  $ OR_quantile: Named num [1:2] 0.724 5.735
#>   ..- attr(*, "names")= chr [1:2] "2.5%" "97.5%"
#>  $ bootdata   :'data.frame': 50 obs. of  5 variables:
#>   ..$ effect_reference : num [1:50] -1.357 -0.801 -1.43 -0.751 -1.352 ...
#>   ..$ effect_comparator: num [1:50] -1.073 -0.99 -0.805 -1.107 -0.216 ...
#>   ..$ RD               : num [1:50] 0.0501 -0.0389 0.1159 -0.0721 0.2408 ...
#>   ..$ RR               : num [1:50] 1.245 0.874 1.6 0.775 2.172 ...
#>   ..$ OR               : num [1:50] 1.329 0.828 1.868 0.701 3.117 ...
#>  $ reference  : num [1:2] 0 0
#>  $ comparator : num [1:2] 1 1
summary_bayesmsm(model)
#>                  mean        sd        2.5%       97.5%
#> Reference  -1.5636662 0.4170985 -2.20796693 -0.80418106
#> Comparator -0.7422943 0.3787915 -1.49598754 -0.09395954
#> RD          0.1467202 0.1129061 -0.06574406  0.34517250
#> RR          2.0546106 0.9072415  0.79269967  3.93180935
#> OR          2.7059804 1.5647939  0.72376031  5.73496587

Visualization functions: plot_ATE, plot_APO, plot_est_box

The bayesmsm package also provides several other functions for visualizing the above results: plot_ATE, plot_APO, and plot_est_box. These functions help the user better interpret the estimated causal effects.

plot_ATE(model)

plot_APO(model, "effect_reference")

plot_APO(model, "effect_comparator")

plot_est_box(model)

Reference

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.