## Loading required package: idem

Introduction

In randomized studies involving severely ill patients, functional outcomes are often unobserved due to missed clinic visits, premature withdrawal or death. It is well known that if these unobserved functional outcomes are not handled properly, biased treatment comparisons can be produced.

R package idem implement a procedure for comparing treatments that is based on the composite endpoint of both the functional outcome and survival. The procedure considers missing data imputation with a sensitivity analysis strategy to handle the unobserved functional outcomes not due to death.

Data accepted by idem

In dataset accepted by idem, each row should represent a subject with treatment assignment, baseline coveraites, baseline outcome, post-randomization outcomes and survival time.

The idem package provides dataset abc from ABC trial as an example data set.

head(abc);
##     AGE TRT SURV Y2 Y1
## 1 59.63   1  999 NA NA
## 2 66.89   0  999 52 49
## 3 59.70   1    1 NA NA
## 4 81.41   0   72 NA NA
## 5 66.52   1  999 45 51
## 6 40.27   0   65 NA NA

Basic setting

Parameters of most functions in idem are organized and passed by a list. These parameters include variable names in the dataset, endpoint specification, duration of the study, etc..

The function chkPara checks the specification in the list of parameters for errors:

 err.lst.var <- list(trt="TRT", outcome=c("Y1","Y2"),
                 y0=NULL, endfml="Y2", bounds=c(10,20),
                 duration=365);

 chkPara(err.lst.var, abc);
## Model specification in not valid. Please check the following: 
## ----No survival time specified
## ----Endpoint does not involve outcome
## ----Upper bound is bigger than some observed outcomes
 lst.var <- list(trt="TRT", surv="SURV", outcome=c("Y1","Y2"),
                 y0=NULL, endp=c("Y2"),
                 unitTime="days",
                 trt.label = c("UC+SBT", "SAT+SBT"),
                 cov=c("AGE"), endfml="Y2",
                 duration=365, bounds=c(0,100));

 chkPara(lst.var, abc);
## No error found.

Data visualization

idem provides several functions for the visualization of the data.

Spaghetti plot for completers

plotCompleters(abc, lst.var);

Missing pattern frequency table

get.mis.table(abc, lst.var);
##                 Y1         Y2         Control    Intervention
## Deaths on study ""         ""         "58 (62%)" "38 (41%)"  
## S=1             "Observed" "Observed" "18 (19%)" "32 (34%)"  
## S=2             "Observed" "Missing"  "8 (9%)"   "8 (9%)"    
## S=3             "Missing"  "Observed" "1 (1%)"   "0 (0%)"    
## S=4             "Missing"  "Missing"  "9 (10%)"  "15 (16%)"  
## Total           ""         ""         "94"       "93"

Missing pattern heatmap

plotMisPattern(abc, lst.var);

Kaplan-Meier curves

plotSurv(abc, lst.var);

Missing data imputation

Model fitting

The first step in missing data imputation is to fit the imputation model to data observed from the completers, i.e. the subjects who were alive at the end of the study without missing data. The result has class name IDEM.FIT, which will be passed to imputation functions.

rst.fit <- fit.model(abc, lst.var);

Check convergence

The p.scale factor adjusts the mixing of the MCMC sampling for the imputation of missing values. It is suggested that the convergence of the MCMC chains for at least a small subset of the subjects should be checked first. This can be done by the get.imp.all function by setting trace.n to be a non-zero number.

rst.mixing <- get.imp.all(abc, rst.fit, lst.var, deltas=0,
                          trace.n=1, normal=TRUE, iter=500,
                          p.scale=10);
## [1] 1
rst.chain <- list();
for (i in 1:ncol(rst.mixing$mcmc[[1]])) {
    rst.chain[[i]] <- rst.mixing$mcmc[[1]][,i,drop=FALSE];
}
coda::traceplot(rst.chain);

Imputation

The following code shows how to use get.imp.all to get the imputed complete datasets under benchmark assmption delta=0 and for sensitivity analysis. We use 300 iterations to reduce the computation time.

rst.imp <- get.imp.all(abc, rst.fit, lst.var, deltas=c(-0.25,0,0.25),
                       normal=TRUE, iter=20, n.imp=2, thin=1,
                       p.scale=10);

The following results show the completed datasets:

tail(rst.imp, n=10);
##       ID DELTA IMP   AGE TRT SURV       Y2 Y1 ORGY1 ORGY2     ENDP
## 1852 186  0.00   1 67.06   0  999 38.80646 36    36    NA 38.80646
## 1853 186  0.00   2 67.06   0  999 39.69025 36    36    NA 39.69025
## 1854 186  0.25   1 67.06   0  999 41.49159 36    36    NA 41.49159
## 1855 186  0.25   2 67.06   0  999 39.24832 36    36    NA 39.24832
## 187  187 -0.25   1 66.12   1  999 29.96516 26    26    NA 29.96516
## 1871 187 -0.25   2 66.12   1  999 33.11319 26    26    NA 33.11319
## 1872 187  0.00   1 66.12   1  999 32.04440 26    26    NA 32.04440
## 1873 187  0.00   2 66.12   1  999 32.40669 26    26    NA 32.40669
## 1874 187  0.25   1 66.12   1  999 33.94560 26    26    NA 33.94560
## 1875 187  0.25   2 66.12   1  999 34.63039 26    26    NA 34.63039

Plot denisity of the imputed data

Function plotImputed plots the densities of the imputed outcomes and the imputed functional endpoint.

plotImputed(rst.imp, lst.var, deltas=c(-0.25,0,0.25), xlim=c(0,100), endp=FALSE);

plotImputed(rst.imp, lst.var, deltas=c(-0.25,0,0.25), xlim=c(0,100), endp=TRUE);

Composite endpoint analysis

Plot the cumulative distribution of the compositve endpoint

Function plotComposite generates the treatment-specific cumulative distribution functions of the composite endpoint, where the values of the composite endpoint are labeled according to the survival time and functional endpoint among survivors.

plotComposite(rst.imp, lst.var, delta=0);
## Loading required package: DBI
## Loading required package: tcltk

Estimation of \(\theta\) and quantiles

Given a complete dataset with imputed outcomes, idem estimates treatment effect and quantiles of the composite endpoint using function get.theta.quantiles:

rst.est <- get.theta.quantiles(rst.imp, lst.var, quantiles=c(0.25,0.5,0.75));
print(rst.est$theta);
##   Delta0 Delta1      Theta
## 1  -0.25  -0.25 -0.1498513
## 2   0.00  -0.25 -0.1444749
## 3   0.25  -0.25 -0.1338367
## 4  -0.25   0.00 -0.1755891
## 5   0.00   0.00 -0.1729581
## 6   0.25   0.00 -0.1571723
## 7  -0.25   0.25 -0.2195150
## 8   0.00   0.25 -0.2175704
## 9   0.25   0.25 -0.2014413
print(rst.est$quantiles);
##    Delta TRT    Q    Quant
## 1  -0.25   0 0.25 -1.00000
## 2  -0.25   0 0.50 -1.00000
## 3  -0.25   0 0.75 39.68429
## 4  -0.25   1 0.25 -1.00000
## 5  -0.25   1 0.50 29.52372
## 6  -0.25   1 0.75 40.80196
## 7   0.00   0 0.25 -1.00000
## 8   0.00   0 0.50 -1.00000
## 9   0.00   0 0.75 38.69092
## 10  0.00   1 0.25 -1.00000
## 11  0.00   1 0.50 31.86163
## 12  0.00   1 0.75 41.33088
## 13  0.25   0 0.25 -1.00000
## 14  0.25   0 0.50 -1.00000
## 15  0.25   0 0.75 40.14695
## 16  0.25   1 0.25 -1.00000
## 17  0.25   1 0.50 34.31520
## 18  0.25   1 0.75 45.12666

Bootstrap analysis

idem evaluates the uncertainty of the estimated \(\theta\) and quantiles by bootstrap analysis.

For illustration, we run 2 bootstrap samples by the following code:

rst.boot <- get.bs.all(n.boot = 2,
                       n.cores = 1,
                       data.all = abc,
                       lst.var = lst.var,
                       deltas = c(-0.25, 0, 0.25),
                       quantiles = c(0.25,0.5,0.75),
                       normal=TRUE, iter=20,
                       n.imp=2, thin=1,
                       p.scale=10);
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
## [1] 11
## [1] 12
## [1] 13
## [1] 14
## [1] 15
## [1] 16
## [1] 17
## [1] 18
## [1] 19
## [1] 20
## [1] 21
## [1] 22
## [1] 23
## [1] 24
## [1] 25
## [1] 26
## [1] 27
## [1] 28
## [1] 29
## [1] 30
## [1] 31
## [1] 32
## [1] 33
## [1] 34
## [1] 35
## [1] 36
## [1] 37
## [1] 38
## [1] 39
## [1] 40
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
## [1] 11
## [1] 12
## [1] 13
## [1] 14
## [1] 15
## [1] 16
## [1] 17
## [1] 18
## [1] 19
## [1] 20
## [1] 21
## [1] 22
## [1] 23
## [1] 24
## [1] 25
## [1] 26
## [1] 27
## [1] 28
## [1] 29
## [1] 30
## [1] 31
## [1] 32
## [1] 33
## [1] 34
## [1] 35
## [1] 36
## [1] 37
## [1] 38
## [1] 39

Hypothesis testing

Hypothesis testing results and the confidence intervals of and quantiles of the composite endpoint are obtained by summarizing the results from the bootstrap analysis and the analysis on the original dataset:

rst.final <- get.overall.rst(rst.est, rst.boot);
print(rst.final);
## $theta
##   Delta0 Delta1      Theta         SD       PValue
## 1  -0.25  -0.25 -0.1498513 0.01488305 7.606398e-24
## 2   0.00  -0.25 -0.1444749 0.01795673 8.573387e-16
## 3   0.25  -0.25 -0.1338367 0.03445750 1.027064e-04
## 4  -0.25   0.00 -0.1755891 0.04796549 2.514895e-04
## 5   0.00   0.00 -0.1729581 0.04958321 4.862121e-04
## 6   0.25   0.00 -0.1571723 0.06495158 1.552745e-02
## 7  -0.25   0.25 -0.2195150 0.05233334 2.734102e-05
## 8   0.00   0.25 -0.2175704 0.05484081 7.268931e-05
## 9   0.25   0.25 -0.2014413 0.07004741 4.030237e-03
## 
## $quantiles
##    Delta TRT    Q    Quant         LB         UB
## 1  -0.25   0 0.25 -1.00000 -0.2060627 -0.1860673
## 2  -0.25   0 0.50 -1.00000 -0.2050389 -0.1809140
## 3  -0.25   0 0.75 39.68429 -0.1986216 -0.1523278
## 4  -0.25   1 0.25 -1.00000 -0.2740992 -0.2096574
## 5  -0.25   1 0.50 29.52372 -0.2722117 -0.2055965
## 6  -0.25   1 0.75 40.80196 -0.2628603 -0.1755977
## 7   0.00   0 0.25 -1.00000 -0.2898450 -0.2195350
## 8   0.00   0 0.50 -1.00000 -0.2873542 -0.2136754
## 9   0.00   0 0.75 38.69092 -0.2781229 -0.1840140
## 10  0.00   1 0.25 -1.00000 -0.2060627 -0.1860673
## 11  0.00   1 0.50 31.86163 -0.2050389 -0.1809140
## 12  0.00   1 0.75 41.33088 -0.1986216 -0.1523278
## 13  0.25   0 0.25 -1.00000 -0.2740992 -0.2096574
## 14  0.25   0 0.50 -1.00000 -0.2722117 -0.2055965
## 15  0.25   0 0.75 40.14695 -0.2628603 -0.1755977
## 16  0.25   1 0.25 -1.00000 -0.2898450 -0.2195350
## 17  0.25   1 0.50 34.31520 -0.2873542 -0.2136754
## 18  0.25   1 0.75 45.12666 -0.2781229 -0.1840140
## 
## attr(,"class")
## [1] "IDEM.TEST"

A contour plot of p-values in the sensitivity analysis results can be generated by plotContour:

plotContour(rst.final, lst.var, nlevels = 30,
            con.v=0.05, zlim=c(0, 0.05));

Graphical user interface (GUI)

The idem package provides a web-based GUI for composite endpoint analysis. The GUI can be accessed by

run.idem();