## Loading required package: idem
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.
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
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.
idem provides several functions for the visualization of the data.
plotCompleters(abc, lst.var);
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"
plotMisPattern(abc, lst.var);
plotSurv(abc, lst.var);
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);
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);
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
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);
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
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
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 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));
The idem package provides a web-based GUI for composite endpoint analysis. The GUI can be accessed by
run.idem();