Longitudinal Ordinal Analysis for Violet2
Introduction
VIOLET 2 was a randomized clinical trial of seriously ill adults in ICUs to study the effectiveness of vitamin D vs. placebo. It has the advantage of having daily ordinal outcomes assessed for 28 days. The original NEJM paper focused on 1078 patients with confirmed baseline vitamin D deficiency. The analyses presented here use 1352 of the original 1360 randomized patients. Of the 1078 patients, 72 of 539 placebo patients died by day 28, and 92 of 531 vitamin D patients died (proportions of 0.13 and 0.17). Our starting dataset has 1359 patients, with death counts of 89 and 112 (proportions 0.13 and 0.16).
See this and related analyses of the ORCHID study and some additional analysis of VIOLET 2. See this for a study of modeling irregular time spacings with Markov models. Go here for a list of papers about Markov longitudinal modeling of binary and ordinal outcomes.
require(rmsb)knitrSet(lang='markdown', w=7, h=7, dev='png', fig.path='png/stat-')
alrsimdone <- TRUE
Load(violet2)
d <- violet2
omit <- c('Home', 'Dead', 'In Post Hospital facility')
k <- with(d, sum(day == 1 & bstatus %in% omit))
d <- subset(d, bstatus %nin% omit)
oldstatus <- d$status
levels(d$status) <-
list(Dead='Dead',
'Vent/ARDS' = c('On Vent', 'ARDS'),
'In Hospital/Facility' = c('In Hospital',
'In Post Hospital Facility'),
Home = 'Home')
table(oldstatus, d$status)##
## oldstatus Dead Vent/ARDS In Hospital/Facility Home
## Dead 3749 0 0 0
## ARDS 0 377 0 0
## On Vent 0 2966 0 0
## In Hospital 0 0 8191 0
## In Post Hospital Facility 0 0 2937 0
## Home 0 0 0 19586
d$bstatus <- droplevels(d$bstatus)
label(d$day) <- 'Day'
label(d$bstatus) <- 'Baseline Status'
dcf <- d
saveRDS(dcf, 'dcf.rds')
dd <- datadist(d); options(datadist='dd')
options(prType='html')Descriptive Statistics
7 patients with day 0 status of dead, at home, or in post hospital facility were dropped.
html(describe(d))12 Variables 37856 Observations
id: Reference Id
| n | missing | distinct |
|---|---|---|
| 37856 | 0 | 1352 |
| lowest : | A01-00208 | A01-00210 | A01-00261 | A01-00337 | A01-00354 |
| highest: | W05-00581 | W05-00589 | W05-00590 | W05-00591 | W05-00592 |
bstatus: Baseline Status
| n | missing | distinct |
|---|---|---|
| 37828 | 28 | 3 |
Value ARDS On Vent In Hospital Frequency 2828 10444 24556 Proportion 0.075 0.276 0.649
day: Day
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 37856 | 0 | 28 | 0.999 | 14.5 | 9.322 | 2.00 | 3.00 | 7.75 | 14.50 | 21.25 | 26.00 | 27.00 |
status
| n | missing | distinct |
|---|---|---|
| 37806 | 50 | 4 |
Value Dead Vent/ARDS In Hospital/Facility
Frequency 3749 3343 11128
Proportion 0.099 0.088 0.294
Value Home
Frequency 19586
Proportion 0.518
age: SCR age enrolled
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 37856 | 0 | 78 | 1 | 56.31 | 18.14 | 27.00 | 33.00 | 46.00 | 58.00 | 67.25 | 76.00 | 82.00 |
treatment
| n | missing | distinct |
|---|---|---|
| 37856 | 0 | 2 |
Value Placebo Vitamin D Frequency 18676 19180 Proportion 0.493 0.507
lips: Baseline LIPS Score
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 37856 | 0 | 28 | 0.996 | 5.175 | 3.399 | 0 | 0 | 3 | 5 | 7 | 9 | 10 |
charlson: Baseline Charlson Score
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 36680 | 1176 | 17 | 0.987 | 3.824 | 3.242 | 0 | 0 | 2 | 3 | 5 | 8 | 9 |
Value 0 1 2 3 4 5 6 7 8 9 10 11
Frequency 4816 4312 4648 4704 4760 4312 2800 2072 1708 896 644 280
Proportion 0.131 0.118 0.127 0.128 0.130 0.118 0.076 0.056 0.047 0.024 0.018 0.008
Value 12 13 14 15 18
Frequency 392 168 112 28 28
Proportion 0.011 0.005 0.003 0.001 0.001
sofa: SOFA Total Score
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 37856 | 0 | 19 | 0.993 | 5.382 | 4.028 | 0 | 1 | 3 | 5 | 8 | 10 | 12 |
Value 0 1 2 3 4 5 6 7 8 9 10 11
Frequency 2436 3444 3136 3808 4424 3752 3780 2968 2492 2128 1820 1540
Proportion 0.064 0.091 0.083 0.101 0.117 0.099 0.100 0.078 0.066 0.056 0.048 0.041
Value 12 13 14 15 16 17 18
Frequency 896 476 308 168 140 84 56
Proportion 0.024 0.013 0.008 0.004 0.004 0.002 0.001
vitD: LCMS Day 0
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 36400 | 1456 | 554 | 1 | 13.74 | 8.279 | 3.898 | 5.163 | 8.047 | 12.600 | 17.800 | 23.310 | 27.300 |
ddeath: Day of Death (29 if alive)
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 37856 | 0 | 28 | 0.375 | 26.23 | 4.918 | 5 | 13 | 29 | 29 | 29 | 29 | 29 |
dhome: Day Discharged to Home (NA if never)
| n | missing | distinct | Info | Mean | Gmd | .05 | .10 | .25 | .50 | .75 | .90 | .95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 26796 | 11060 | 28 | 0.994 | 8.199 | 6.851 | 2 | 2 | 4 | 6 | 11 | 18 | 25 |
Summarize deaths occurring after a patient arrives at home (there were no other events).
u <- subset(d, ! is.na(dhome) & day >= dhome)
np <- length(unique(u$id))
ud <- subset(u, status == 'Dead')
nd <- length(unique(ud$id))
cat(np, 'patients discharged to home\n',
nd, 'died post discharge\n')957 patients discharged to home
29 died post discharge
Event Chart for Random Sample of Patients
A status timeline is shown for each of 65 randomly chosen patients. The patients are sorted so that the worst outcomes at the last follow-up day are at the top. One day is subtract from the time variable to make follow-up start at day 0.
ssamp <- sample(unique(d$id), 65, FALSE)
dr <- subset(d, id %in% ssamp)
dr <- subset(dr, day <= ddeath)
dr$id <- as.integer(as.factor(dr$id))
dr$status <- factor(dr$status, levels=rev(levels(dr$status)))
dr$day <- dr$day - 1
multEventChart(status ~ day + id, data=dr,
absorb='Dead', sortbylast = TRUE) +
theme_classic() +
theme(legend.position='bottom')Summary of Successive State Transitions
propsTrans(status ~ day + id, data=d, maxsize=6) +
theme(legend.position='bottom', axis.text.x=element_text(angle=90, hjust=1))
# For a nice event chart for this type of data see https://livefreeordichotomize.com/2020/05/21/survival-model-detective-1Category Proportions Over Time and PO Assumption
The following plot shows how the mix of outcomes changes over time stratified also by treatment.
propsPO(status ~ treatment + day, data=subset(d, day < 15), nrow=1) +
theme(legend.position='bottom', axis.text.x=element_text(angle=90, hjust=1))propsPO(status ~ treatment + day, data=subset(d, day > 14), nrow=1) +
theme(legend.position='bottom', axis.text.x=element_text(angle=90, hjust=1))Ignoring treatment, compare the observed patterns with what would be expected had the proportional odds assumption been satisfied, fit a PO model containing only day as a predictor, and allow the day effect to be a flexible spline function. Then compute odds ratios against day 1 and apply those odds ratios to the observed proportions from day 1. This is for the original dataset with death carried forward.
f <- lrm(status ~ rcs(day, 5), data=d)
g <- Function(f) # derive predicted log odds as a function of day
# Make another function that gets the OR vs. day=1
dor <- function(day) exp(g(day) - g(1))
propsPO(status ~ day, odds.ratio=dor, data=d) +
theme(legend.position='bottom')Carrying death forward results in a devastating violation of the PO assumption with respect to time. For example, the incidence of death keeps increasing while the incidence of vent/ARDS is decreasing. Now we repeat the process but terminating follow-up at death.
u <- subset(d, day <= ddeath)
f <- lrm(status ~ rcs(day, 5), data=u)
g <- Function(f) # derive predicted log odds as a function of day
dor <- function(day) exp(g(day) - g(1))
propsPO(status ~ day, odds.ratio=dor, data=u) +
theme(legend.position='bottom')The non-PO with respect to time is less problematic when follow-up stops at death but continues for nonfatal events. Note that in the limiting case where death is the only event and the time intervals are small, such truncation results in a binary logistic odds ratio for treatment being almost exactly the hazard ratio in a Cox model analysis when interval risks are small. [However the absolute risk estimates from such a model as a function of time are hard to interpret.].
Note: The lower panel of the above graph is dependent on the choice of reference day. The proportions were estimated from day 1 alone. Instead let’s estimate them from day 4 and repeat.
dor <- function(day) exp(g(day) - g(4))
propsPO(status ~ day, odds.ratio=dor, ref=4, data=u) +
theme(legend.position='bottom')Now proportional odds holds with respect to time.
Now do a similar analysis for the second most important predictor: baseline status, still truncating at death. ARDS is taken as the reference group for computing proportions in the follow-up status categories for the purpose of applying the PO assumption.
f <- lrm(status ~ bstatus, data=u)
g <- Function(f) # derive predicted log odds as a function of bstatus
dor <- function(bstatus) exp(g(bstatus) - g('ARDS'))
propsPO(status ~ bstatus, odds.ratio=dor, ref='ARDS', data=u) Proportional odds is reasonably well satisfied with regard to baseline status except that for patients in hospital at baseline, without ARDS or vent, there is an overprediction of the proportion in the vent/ARDS category. Because these summaries are confounded with time, let’s repeat for day 3 only.
u3 <- subset(u, day == 3)
f <- lrm(status ~ bstatus, data=u3)
g <- Function(f) # derive predicted log odds as a function of bstatus
dor <- function(bstatus) exp(g(bstatus) - g('ARDS'))
propsPO(status ~ bstatus, odds.ratio=dor, ref='ARDS', data=u3) See here for assessment of PO for other variables.
GEE-Type Proportional Odds Modeling
This analysis uses a working independence proportional odds model, then the variance-covariance matrix is corrected for within-patient correlation using the robust cluster sandwhich covariance estimator. Covariates are allowed to have nonlinear effects through the use of restricted cubic spline functions with 4 knots. A dot charts shows the relative importance of the predictors. Note that the lrm function in the R rms package frames the model in terms of \(P(Y \geq y | X)\) whereas most software uses \(P(Y \leq y | X)\).
There are several patients excluded in the analysis below due to missing baseline vitamin D levels.
f <- lrm(status ~ bstatus + rcs(day, 5) + rcs(age, 5) + rcs(lips, 5) +
rcs(charlson, 4) + rcs(sofa, 5) + rcs(vitD, 5) + treatment,
data=d, tol=1e-13, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
plot(anova(g), trans=sqrt) We reallocate degrees of freedom for the terms in the model so that the predictors with the most potential from the dot chart are given more parameters. This is because complex relationships that are week will not suffer from underfitting. The likelihood ratio and score \(\chi^2\) statistics in the output below should be ignored because they are not adjusted for intra-cluster correlation.
f <- lrm(status ~ bstatus + rcs(day, 5) + rcs(age, 3) + rcs(lips, 3) +
rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD, 3) + treatment,
data=d, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
gLogistic Regression Model
lrm(formula = status ~ bstatus + rcs(day, 5) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD,
3) + treatment, data = d, x = TRUE, y = TRUE)
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
3423 3043 10467
Home
18353
Frequencies of Missing Values Due to Each Variable
|
Model Likelihood Ratio Test |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 35286 | LR χ2 9851.12 | R2 0.271 | C 0.749 |
Cluster on d$id
|
d.f. 19 | g 1.208 | Dxy 0.498 |
| Clusters 1261 | Pr(>χ2) <0.0001 | gr 3.348 | γ 0.498 |
| max |∂log L/∂β| 1×10-10 | gp 0.158 | τa 0.311 | |
| Brier 0.122 |
| β | S.E. | Wald Z | Pr(>|Z|) | |
|---|---|---|---|---|
| y≥Vent/ARDS | 0.5629 | 0.4329 | 1.30 | 0.1935 |
| y≥In Hospital/Facility | -0.3008 | 0.4376 | -0.69 | 0.4918 |
| y≥Home | -2.1195 | 0.4404 | -4.81 | <0.0001 |
| bstatus=On Vent | 0.4439 | 0.2116 | 2.10 | 0.0359 |
| bstatus=In Hospital | 1.4338 | 0.2179 | 6.58 | <0.0001 |
| day | 0.1833 | 0.0100 | 18.39 | <0.0001 |
| day’ | -0.3621 | 0.0446 | -8.12 | <0.0001 |
| day’’ | 0.5972 | 0.1172 | 5.10 | <0.0001 |
| day’’’ | -0.1138 | 0.1323 | -0.86 | 0.3897 |
| age | 0.0013 | 0.0081 | 0.16 | 0.8703 |
| age’ | -0.0153 | 0.0075 | -2.04 | 0.0414 |
| lips | -0.0397 | 0.0456 | -0.87 | 0.3837 |
| lips’ | -0.0151 | 0.0469 | -0.32 | 0.7483 |
| charlson | -0.1797 | 0.1106 | -1.63 | 0.1041 |
| charlson’ | 0.3888 | 0.5018 | 0.77 | 0.4384 |
| charlson’’ | -0.7933 | 0.9951 | -0.80 | 0.4253 |
| sofa | 0.0212 | 0.0756 | 0.28 | 0.7791 |
| sofa’ | -0.1943 | 0.2564 | -0.76 | 0.4485 |
| sofa’’ | 0.4016 | 1.0363 | 0.39 | 0.6984 |
| vitD | 0.0595 | 0.0175 | 3.41 | 0.0007 |
| vitD’ | -0.0584 | 0.0201 | -2.91 | 0.0037 |
| treatment=Vitamin D | 0.1169 | 0.0963 | 1.21 | 0.2249 |
anova(g)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| bstatus | 79.00 | 2 | <0.0001 |
| day | 482.46 | 4 | <0.0001 |
| Nonlinear | 282.09 | 3 | <0.0001 |
| age | 12.77 | 2 | 0.0017 |
| Nonlinear | 4.16 | 1 | 0.0414 |
| lips | 9.91 | 2 | 0.0071 |
| Nonlinear | 0.10 | 1 | 0.7483 |
| charlson | 26.63 | 3 | <0.0001 |
| Nonlinear | 0.66 | 2 | 0.7175 |
| sofa | 27.70 | 3 | <0.0001 |
| Nonlinear | 4.75 | 2 | 0.0932 |
| vitD | 12.27 | 2 | 0.0022 |
| Nonlinear | 8.44 | 1 | 0.0037 |
| treatment | 1.47 | 1 | 0.2249 |
| TOTAL NONLINEAR | 293.51 | 10 | <0.0001 |
| TOTAL | 786.13 | 19 | <0.0001 |
Partial effect plots below show the relationship between each predictor and log odds, holding other predictors to median or mode.
ggplot(Predict(g))A nomogram representation of the model is below. The nomogram can be enhanced to show the estimated probability or outcome better than any given level.
n <- nomogram(g, vnames='names')
plot(n)Fit With Only Linear Effects and Only for Day 14
d14 <- subset(d, day == 14)
f <- lrm(status ~ bstatus + age + lips +
charlson + sofa + treatment, data=d14, x=TRUE, y=TRUE)
fLogistic Regression Model
lrm(formula = status ~ bstatus + age + lips + charlson + sofa +
treatment, data = d14, x = TRUE, y = TRUE)
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
142 77 303
Home
786
Frequencies of Missing Values Due to Each Variable
status bstatus age lips charlson sofa treatment
2 1 0 0 42 0 0
|
Model Likelihood Ratio Test |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 1308 | LR χ2 252.94 | R2 0.200 | C 0.712 |
| max |∂log L/∂β| 9×10-7 | d.f. 7 | g 1.050 | Dxy 0.424 |
| Pr(>χ2) <0.0001 | gr 2.858 | γ 0.424 | |
| gp 0.139 | τa 0.242 | ||
| Brier 0.116 |
| β | S.E. | Wald Z | Pr(>|Z|) | |
|---|---|---|---|---|
| y≥Vent/ARDS | 3.1451 | 0.3644 | 8.63 | <0.0001 |
| y≥In Hospital/Facility | 2.5659 | 0.3605 | 7.12 | <0.0001 |
| y≥Home | 1.1570 | 0.3551 | 3.26 | 0.0011 |
| bstatus=On Vent | 0.4889 | 0.2205 | 2.22 | 0.0266 |
| bstatus=In Hospital | 1.3809 | 0.2197 | 6.28 | <0.0001 |
| age | -0.0115 | 0.0045 | -2.57 | 0.0103 |
| lips | -0.0487 | 0.0196 | -2.49 | 0.0129 |
| charlson | -0.1248 | 0.0241 | -5.19 | <0.0001 |
| sofa | -0.0947 | 0.0180 | -5.28 | <0.0001 |
| treatment=Vitamin D | 0.2483 | 0.1156 | 2.15 | 0.0317 |
anova(f)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| bstatus | 65.58 | 2 | <0.0001 |
| age | 6.59 | 1 | 0.0103 |
| lips | 6.19 | 1 | 0.0129 |
| charlson | 26.89 | 1 | <0.0001 |
| sofa | 27.85 | 1 | <0.0001 |
| treatment | 4.61 | 1 | 0.0317 |
| TOTAL | 225.54 | 7 | <0.0001 |
Evaluation of Baseline Measurement \(\times\) Time Interactions
In the following, allow time (simplified to 3 knots in the spline) to interact with each of the baseline variables, using fewer knots than before because of the much larger number of parameters being fitted.
f <- lrm(status ~ rcs(day, 3) * (bstatus + rcs(age, 3) + rcs(lips, 3) +
rcs(charlson, 3) + rcs(sofa, 3) + treatment),
data=d, tol=1e-13, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
anova(g)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| day (Factor+Higher Order Factors) | 560.38 | 24 | <0.0001 |
| All Interactions | 124.64 | 22 | <0.0001 |
| Nonlinear (Factor+Higher Order Factors) | 295.79 | 12 | <0.0001 |
| bstatus (Factor+Higher Order Factors) | 238.83 | 6 | <0.0001 |
| All Interactions | 4.41 | 4 | 0.3529 |
| age (Factor+Higher Order Factors) | 11.07 | 6 | 0.0861 |
| All Interactions | 8.80 | 4 | 0.0663 |
| Nonlinear (Factor+Higher Order Factors) | 4.21 | 3 | 0.2400 |
| lips (Factor+Higher Order Factors) | 22.96 | 6 | 0.0008 |
| All Interactions | 2.65 | 4 | 0.6174 |
| Nonlinear (Factor+Higher Order Factors) | 1.40 | 3 | 0.7059 |
| charlson (Factor+Higher Order Factors) | 35.46 | 6 | <0.0001 |
| All Interactions | 25.45 | 4 | <0.0001 |
| Nonlinear (Factor+Higher Order Factors) | 4.35 | 3 | 0.2265 |
| sofa (Factor+Higher Order Factors) | 53.37 | 6 | <0.0001 |
| All Interactions | 16.99 | 4 | 0.0019 |
| Nonlinear (Factor+Higher Order Factors) | 7.09 | 3 | 0.0692 |
| treatment (Factor+Higher Order Factors) | 5.64 | 3 | 0.1303 |
| All Interactions | 4.60 | 2 | 0.1001 |
| day × bstatus (Factor+Higher Order Factors) | 4.41 | 4 | 0.3529 |
| Nonlinear | 1.71 | 2 | 0.4261 |
| Nonlinear Interaction : f(A,B) vs. AB | 1.71 | 2 | 0.4261 |
| day × age (Factor+Higher Order Factors) | 8.80 | 4 | 0.0663 |
| Nonlinear | 7.32 | 3 | 0.0624 |
| Nonlinear Interaction : f(A,B) vs. AB | 7.32 | 3 | 0.0624 |
| f(A,B) vs. Af(B) + Bg(A) | 3.49 | 1 | 0.0618 |
| Nonlinear Interaction in day vs. Af(B) | 6.75 | 2 | 0.0343 |
| Nonlinear Interaction in age vs. Bg(A) | 4.12 | 2 | 0.1277 |
| day × lips (Factor+Higher Order Factors) | 2.65 | 4 | 0.6174 |
| Nonlinear | 1.72 | 3 | 0.6329 |
| Nonlinear Interaction : f(A,B) vs. AB | 1.72 | 3 | 0.6329 |
| f(A,B) vs. Af(B) + Bg(A) | 0.86 | 1 | 0.3528 |
| Nonlinear Interaction in day vs. Af(B) | 1.27 | 2 | 0.5309 |
| Nonlinear Interaction in lips vs. Bg(A) | 1.30 | 2 | 0.5230 |
| day × charlson (Factor+Higher Order Factors) | 25.45 | 4 | <0.0001 |
| Nonlinear | 5.33 | 3 | 0.1495 |
| Nonlinear Interaction : f(A,B) vs. AB | 5.33 | 3 | 0.1495 |
| f(A,B) vs. Af(B) + Bg(A) | 0.49 | 1 | 0.4833 |
| Nonlinear Interaction in day vs. Af(B) | 5.18 | 2 | 0.0752 |
| Nonlinear Interaction in charlson vs. Bg(A) | 0.70 | 2 | 0.7042 |
| day × sofa (Factor+Higher Order Factors) | 16.99 | 4 | 0.0019 |
| Nonlinear | 14.80 | 3 | 0.0020 |
| Nonlinear Interaction : f(A,B) vs. AB | 14.80 | 3 | 0.0020 |
| f(A,B) vs. Af(B) + Bg(A) | 1.38 | 1 | 0.2400 |
| Nonlinear Interaction in day vs. Af(B) | 12.02 | 2 | 0.0025 |
| Nonlinear Interaction in sofa vs. Bg(A) | 6.19 | 2 | 0.0453 |
| day × treatment (Factor+Higher Order Factors) | 4.60 | 2 | 0.1001 |
| Nonlinear | 4.01 | 1 | 0.0451 |
| Nonlinear Interaction : f(A,B) vs. AB | 4.01 | 1 | 0.0451 |
| TOTAL NONLINEAR | 305.41 | 20 | <0.0001 |
| TOTAL INTERACTION | 124.64 | 22 | <0.0001 |
| TOTAL NONLINEAR + INTERACTION | 366.25 | 27 | <0.0001 |
| TOTAL | 927.04 | 35 | <0.0001 |
From the ANOVA above you can see strong evidence for some form of interactions. Interactions between time and baseline SOFA score and time and the Charlson index stand out. The interactions indicate that the effect of these two baseline variables dissipates at later times. Let’s estimate the baseline covariate effects for days 1, 8, 15, 22 from the interaction model.
days <- c(1, 8, 15, 22)
ggplot(Predict(g, bstatus, day=days))
ggplot(Predict(g, age, day=days))
ggplot(Predict(g, lips, day=days))
ggplot(Predict(g, charlson, day=days))
ggplot(Predict(g, sofa, day=days))
ggplot(Predict(g, treatment, day=days))
ggplot(Predict(g, day, treatment))Checking Proportional Odds Assumption
Before getting into a more detailed analysis concerning the proportional odds assumption involving multiple predictors, let’s take a different look at time alone (the approach described earlier is more intuitive). For each day, compute all cumulative proportions, take their logit, and see how the spacing between successive logit cumulative proportions varies across days. Plotting symbols are defined in the code. This may be easier to see in a table of simple cell frequencies that is also shown.
d$yn <- as.integer(d$status) # numeric Y for easy dichotomization
table(d$status, d$yn)
1 2 3 4
Dead 3749 0 0 0
Vent/ARDS 0 3343 0 0
In Hospital/Facility 0 0 11128 0
Home 0 0 0 19586
ql <- function(y) {
p <- min(0.9999, max(0.0001, mean(y, na.rm=TRUE)))
qlogis(p)
}
sf <- function(y) c(
'y>=2'=ql(y >= 2), # box (alive)
'y>=3'=ql(y >= 3), # circle (not dead or Vent/ARDS)
'y>=4'=ql(y == 4)) # triangle (discharged)
s <- summary(yn ~ day, fun=sf, continuous=99, data=d)
plot(s, which=1:3, pch=0:4, xlab='logit Cumulative Prob', main='')
# g <- function(y)
# apply(y, 2, function(u) qlogis(mean(u)))
# s <- summary(cumcategory(yn) ~ day, continuous=99, data=d)
# plot(s, which=2:3, pch=1:5, xlab='logit Cumulative Prob.', main='')
with(d, print(table(day, status))) status
day Dead Vent/ARDS In Hospital/Facility Home
1 16 421 877 37
2 31 319 860 141
3 49 258 809 235
4 63 226 727 335
5 76 202 634 439
6 84 169 586 512
7 96 153 521 580
8 107 130 469 644
9 113 123 423 691
10 121 115 405 709
11 125 104 387 734
12 135 93 357 765
13 140 87 334 789
14 147 82 311 810
15 151 79 297 823
16 157 78 280 835
17 162 72 275 841
18 166 69 266 849
19 167 67 258 858
20 170 66 251 863
21 170 66 247 867
22 173 63 241 873
23 178 62 232 878
24 182 62 223 883
25 186 61 217 886
26 193 59 211 887
27 195 57 204 894
28 196 0 226 928
In the following we ignore intra-patient correlation and use an all-linear (except for time) PO model for purposes of assessing the PO assumption on all covariates including time. The assessment is done by comparing \(\beta\)s with those from the PO model overall fit and those from all dichotomizations of Y. The analysis is done twice. First all patient records are considered. Then days after the day of death are removed. We pay more attention to the more important variables: day, baseline status, SOFA, and Charlson (in descending order of outcome variation explained). The day effect is extremely nonlinear in the PO model, and day is modeled as a quadratic effect here so it has two \(\beta\)s.
for(inclall in c(TRUE, FALSE)) {
cat(if(inclall) '\nAll records\n\n' else '\nRecords until death\n\n')
u <- if(inclall) d else subset(d, day <= ddeath)
f <- lrm(status ~ bstatus + pol(day, 2) + age + lips + charlson + sofa +
treatment, data=u)
k <- matrix(NA, nrow=4, ncol=9)
poc <- coef(f)[-(1:3)]
colnames(k) <- names(poc)
rownames(k) <- c('PO', paste0('>=', 2:4))
k[1, ] <- poc
for(cut in c(2 : 4)) {
g <- lrm(yn >= cut ~ bstatus + pol(day, 2) + age + lips + charlson +
sofa + treatment, data=u)
k[cut, ] <- coef(g)[-1]
}
print(round(k, 3))
}
All records
bstatus=On Vent bstatus=In Hospital day day^2 age lips charlson
PO 0.464 1.465 0.171 -0.004 -0.009 -0.051 -0.113
>=2 0.582 1.053 -0.183 0.004 -0.004 -0.106 -0.207
>=3 0.410 2.334 0.096 -0.003 -0.001 -0.047 -0.160
>=4 0.364 1.170 0.322 -0.008 -0.014 -0.042 -0.105
sofa treatment=Vitamin D
PO -0.089 0.154
>=2 -0.123 0.022
>=3 -0.076 0.046
>=4 -0.098 0.205
Records until death
bstatus=On Vent bstatus=In Hospital day day^2 age lips charlson
PO 0.326 1.600 0.284 -0.006 -0.015 -0.021 -0.045
>=2 0.490 0.772 0.080 -0.001 -0.006 -0.098 -0.177
>=3 0.271 3.868 0.237 -0.005 -0.003 -0.003 -0.044
>=4 0.193 1.001 0.345 -0.008 -0.018 -0.021 -0.049
sofa treatment=Vitamin D
PO -0.075 0.217
>=2 -0.100 -0.035
>=3 -0.034 0.102
>=4 -0.085 0.255
Constancy of the \(\beta\)s vertically in the above tables, and hence equality with the PO \(\beta\)s in the first row, means the PO assumption is satisfied. Not that PO is not strictly satisfied for any dataset we encounter, and even when PO is not satisfied, the PO model can still work better than alternative approaches.
When all records are analyzed (even those with duplicated death status post death), the coefficients are slightly more constant, except for the coefficient of day. When death-carried-forward is not used, the coefficients are slightly less constant except for the effect of day. To help explore that, here is an analysis of when deaths are occuring (patients not dying are removed):
w <- subset(d, day == 1 & ddeath < 29)
hist(w$ddeath, breaks=0:28, main='', xlab='Day of Death')GEE-Like Analysis Repeated Without Carrying Death Forward
The last analysis with cluster correlation correction is repeated after deletion of patient records beyond the day of death. In other words, the death status is not repeated up to day 28 but the patient data are truncated at death.
d <- dnc <- subset(d, day <= ddeath)
f <- lrm(status ~ bstatus + rcs(day, 5) + rcs(age, 3) + rcs(lips, 3) +
rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD, 3) + treatment,
data=d, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
gLogistic Regression Model
lrm(formula = status ~ bstatus + rcs(day, 5) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD,
3) + treatment, data = d, x = TRUE, y = TRUE)
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
180 3043 10467
Home
18353
Frequencies of Missing Values Due to Each Variable
|
Model Likelihood Ratio Test |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 32043 | LR χ2 11418.02 | R2 0.354 | C 0.787 |
Cluster on d$id
|
d.f. 19 | g 1.506 | Dxy 0.574 |
| Clusters 1261 | Pr(>χ2) <0.0001 | gr 4.506 | γ 0.575 |
| max |∂log L/∂β| 1×10-7 | gp 0.119 | τa 0.319 | |
| Brier 0.069 |
| β | S.E. | Wald Z | Pr(>|Z|) | |
|---|---|---|---|---|
| y≥Vent/ARDS | 2.7293 | 0.4924 | 5.54 | <0.0001 |
| y≥In Hospital/Facility | -0.6462 | 0.5038 | -1.28 | 0.1996 |
| y≥Home | -3.2094 | 0.4970 | -6.46 | <0.0001 |
| bstatus=On Vent | 0.3845 | 0.2626 | 1.46 | 0.1430 |
| bstatus=In Hospital | 1.6675 | 0.2571 | 6.49 | <0.0001 |
| day | 0.3020 | 0.0127 | 23.72 | <0.0001 |
| day’ | -0.5754 | 0.0647 | -8.89 | <0.0001 |
| day’’ | 0.9879 | 0.1814 | 5.45 | <0.0001 |
| day’’’ | -0.2407 | 0.2103 | -1.14 | 0.2523 |
| age | 0.0018 | 0.0094 | 0.19 | 0.8477 |
| age’ | -0.0187 | 0.0083 | -2.26 | 0.0240 |
| lips | -0.0468 | 0.0519 | -0.90 | 0.3676 |
| lips’ | 0.0213 | 0.0469 | 0.45 | 0.6492 |
| charlson | -0.1732 | 0.1384 | -1.25 | 0.2106 |
| charlson’ | 0.6995 | 0.7050 | 0.99 | 0.3211 |
| charlson’’ | -1.6179 | 1.6182 | -1.00 | 0.3174 |
| sofa | 0.0392 | 0.1066 | 0.37 | 0.7129 |
| sofa’ | -0.3083 | 0.3890 | -0.79 | 0.4280 |
| sofa’’ | 0.6236 | 0.9470 | 0.66 | 0.5102 |
| vitD | 0.0413 | 0.0193 | 2.14 | 0.0322 |
| vitD’ | -0.0494 | 0.0229 | -2.16 | 0.0309 |
| treatment=Vitamin D | 0.1920 | 0.1063 | 1.81 | 0.0708 |
anova(g)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| bstatus | 108.29 | 2 | <0.0001 |
| day | 1401.68 | 4 | <0.0001 |
| Nonlinear | 391.54 | 3 | <0.0001 |
| age | 17.32 | 2 | 0.0002 |
| Nonlinear | 5.09 | 1 | 0.0240 |
| lips | 1.86 | 2 | 0.3949 |
| Nonlinear | 0.21 | 1 | 0.6492 |
| charlson | 6.47 | 3 | 0.0908 |
| Nonlinear | 1.00 | 2 | 0.6063 |
| sofa | 19.39 | 3 | 0.0002 |
| Nonlinear | 1.91 | 2 | 0.3856 |
| vitD | 4.79 | 2 | 0.0913 |
| Nonlinear | 4.66 | 1 | 0.0309 |
| treatment | 3.26 | 1 | 0.0708 |
| TOTAL NONLINEAR | 403.82 | 10 | <0.0001 |
| TOTAL | 1621.75 | 19 | <0.0001 |
ggplot(Predict(g))Let’s also look at the proportional odds assumption using these truncated records (death not carried forward).
s <- summary(yn ~ day, fun=sf, continuous=99, data=d)
plot(s, which=1:3, pch=0:4, xlab='logit Cumulative Prob', main='')When the absorbing state is not carried forward, the problem with non-proportional odds almost vanishes.
Finally, look at interactions with time in this model.
f <- lrm(status ~ rcs(day, 3) * (bstatus + rcs(age, 3) + rcs(lips, 3) +
rcs(charlson, 3) + rcs(sofa, 3) + treatment),
data=d, tol=1e-13, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
anova(g)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| day (Factor+Higher Order Factors) | 1195.35 | 24 | <0.0001 |
| All Interactions | 87.91 | 22 | <0.0001 |
| Nonlinear (Factor+Higher Order Factors) | 400.49 | 12 | <0.0001 |
| bstatus (Factor+Higher Order Factors) | 365.19 | 6 | <0.0001 |
| All Interactions | 19.95 | 4 | 0.0005 |
| age (Factor+Higher Order Factors) | 23.69 | 6 | 0.0006 |
| All Interactions | 20.58 | 4 | 0.0004 |
| Nonlinear (Factor+Higher Order Factors) | 5.92 | 3 | 0.1154 |
| lips (Factor+Higher Order Factors) | 26.36 | 6 | 0.0002 |
| All Interactions | 10.98 | 4 | 0.0268 |
| Nonlinear (Factor+Higher Order Factors) | 2.62 | 3 | 0.4542 |
| charlson (Factor+Higher Order Factors) | 15.46 | 6 | 0.0170 |
| All Interactions | 6.11 | 4 | 0.1914 |
| Nonlinear (Factor+Higher Order Factors) | 2.17 | 3 | 0.5381 |
| sofa (Factor+Higher Order Factors) | 46.36 | 6 | <0.0001 |
| All Interactions | 1.64 | 4 | 0.8011 |
| Nonlinear (Factor+Higher Order Factors) | 4.72 | 3 | 0.1931 |
| treatment (Factor+Higher Order Factors) | 4.66 | 3 | 0.1984 |
| All Interactions | 1.91 | 2 | 0.3852 |
| day × bstatus (Factor+Higher Order Factors) | 19.95 | 4 | 0.0005 |
| Nonlinear | 12.96 | 2 | 0.0015 |
| Nonlinear Interaction : f(A,B) vs. AB | 12.96 | 2 | 0.0015 |
| day × age (Factor+Higher Order Factors) | 20.58 | 4 | 0.0004 |
| Nonlinear | 8.33 | 3 | 0.0397 |
| Nonlinear Interaction : f(A,B) vs. AB | 8.33 | 3 | 0.0397 |
| f(A,B) vs. Af(B) + Bg(A) | 4.22 | 1 | 0.0399 |
| Nonlinear Interaction in day vs. Af(B) | 6.98 | 2 | 0.0305 |
| Nonlinear Interaction in age vs. Bg(A) | 5.87 | 2 | 0.0532 |
| day × lips (Factor+Higher Order Factors) | 10.98 | 4 | 0.0268 |
| Nonlinear | 2.81 | 3 | 0.4222 |
| Nonlinear Interaction : f(A,B) vs. AB | 2.81 | 3 | 0.4222 |
| f(A,B) vs. Af(B) + Bg(A) | 0.01 | 1 | 0.9409 |
| Nonlinear Interaction in day vs. Af(B) | 0.25 | 2 | 0.8805 |
| Nonlinear Interaction in lips vs. Bg(A) | 2.41 | 2 | 0.2997 |
| day × charlson (Factor+Higher Order Factors) | 6.11 | 4 | 0.1914 |
| Nonlinear | 4.78 | 3 | 0.1888 |
| Nonlinear Interaction : f(A,B) vs. AB | 4.78 | 3 | 0.1888 |
| f(A,B) vs. Af(B) + Bg(A) | 0.06 | 1 | 0.8138 |
| Nonlinear Interaction in day vs. Af(B) | 3.92 | 2 | 0.1405 |
| Nonlinear Interaction in charlson vs. Bg(A) | 1.31 | 2 | 0.5196 |
| day × sofa (Factor+Higher Order Factors) | 1.64 | 4 | 0.8011 |
| Nonlinear | 1.46 | 3 | 0.6922 |
| Nonlinear Interaction : f(A,B) vs. AB | 1.46 | 3 | 0.6922 |
| f(A,B) vs. Af(B) + Bg(A) | 0.01 | 1 | 0.9297 |
| Nonlinear Interaction in day vs. Af(B) | 1.42 | 2 | 0.4911 |
| Nonlinear Interaction in sofa vs. Bg(A) | 0.04 | 2 | 0.9792 |
| day × treatment (Factor+Higher Order Factors) | 1.91 | 2 | 0.3852 |
| Nonlinear | 1.86 | 1 | 0.1728 |
| Nonlinear Interaction : f(A,B) vs. AB | 1.86 | 1 | 0.1728 |
| TOTAL NONLINEAR | 420.41 | 20 | <0.0001 |
| TOTAL INTERACTION | 87.91 | 22 | <0.0001 |
| TOTAL NONLINEAR + INTERACTION | 455.33 | 27 | <0.0001 |
| TOTAL | 1637.55 | 35 | <0.0001 |
days <- c(1, 8, 15, 22)
ggplot(Predict(g, bstatus, day=days))
ggplot(Predict(g, age, day=days))
ggplot(Predict(g, lips, day=days))
ggplot(Predict(g, charlson, day=days))
ggplot(Predict(g, sofa, day=days))
ggplot(Predict(g, treatment, day=days))
ggplot(Predict(g, day, treatment))Assessment of Interaction Between Baseline Vitamin D and Treatment
We repeat the model above but allowing baseline vitamin D to interact with treatment.
f <- lrm(status ~ bstatus + rcs(day, 5) + rcs(age, 3) + rcs(lips, 3) +
rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD, 4) * treatment,
data=d, x=TRUE, y=TRUE)
g <- robcov(f, d$id)
gLogistic Regression Model
lrm(formula = status ~ bstatus + rcs(day, 5) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) + rcs(vitD,
4) * treatment, data = d, x = TRUE, y = TRUE)
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
180 3043 10467
Home
18353
Frequencies of Missing Values Due to Each Variable
|
Model Likelihood Ratio Test |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 32043 | LR χ2 11633.44 | R2 0.360 | C 0.790 |
Cluster on d$id
|
d.f. 23 | g 1.524 | Dxy 0.580 |
| Clusters 1261 | Pr(>χ2) <0.0001 | gr 4.592 | γ 0.580 |
| max |∂log L/∂β| 1×10-7 | gp 0.120 | τa 0.322 | |
| Brier 0.069 |
| β | S.E. | Wald Z | Pr(>|Z|) | |
|---|---|---|---|---|
| y≥Vent/ARDS | 2.3634 | 0.5685 | 4.16 | <0.0001 |
| y≥In Hospital/Facility | -1.0222 | 0.5765 | -1.77 | 0.0762 |
| y≥Home | -3.6015 | 0.5723 | -6.29 | <0.0001 |
| bstatus=On Vent | 0.4329 | 0.2622 | 1.65 | 0.0987 |
| bstatus=In Hospital | 1.7149 | 0.2571 | 6.67 | <0.0001 |
| day | 0.3041 | 0.0128 | 23.70 | <0.0001 |
| day’ | -0.5816 | 0.0650 | -8.94 | <0.0001 |
| day’’ | 1.0016 | 0.1823 | 5.49 | <0.0001 |
| day’’’ | -0.2506 | 0.2113 | -1.19 | 0.2355 |
| age | 0.0029 | 0.0094 | 0.31 | 0.7600 |
| age’ | -0.0193 | 0.0083 | -2.33 | 0.0197 |
| lips | -0.0507 | 0.0521 | -0.97 | 0.3312 |
| lips’ | 0.0260 | 0.0472 | 0.55 | 0.5823 |
| charlson | -0.1829 | 0.1393 | -1.31 | 0.1893 |
| charlson’ | 0.7225 | 0.7116 | 1.02 | 0.3099 |
| charlson’’ | -1.6651 | 1.6355 | -1.02 | 0.3086 |
| sofa | 0.0355 | 0.1074 | 0.33 | 0.7410 |
| sofa’ | -0.2841 | 0.3896 | -0.73 | 0.4659 |
| sofa’’ | 0.5528 | 0.9472 | 0.58 | 0.5595 |
| vitD | 0.0686 | 0.0505 | 1.36 | 0.1742 |
| vitD’ | -0.0298 | 0.2232 | -0.13 | 0.8937 |
| vitD’’ | -0.1455 | 0.5537 | -0.26 | 0.7928 |
| treatment=Vitamin D | 0.7066 | 0.5397 | 1.31 | 0.1905 |
| vitD × treatment=Vitamin D | -0.0303 | 0.0757 | -0.40 | 0.6894 |
| vitD’ × treatment=Vitamin D | -0.2233 | 0.3288 | -0.68 | 0.4971 |
| vitD’’ × treatment=Vitamin D | 0.8314 | 0.8141 | 1.02 | 0.3071 |
anova(g)
Wald Statistics for status
|
|||
| χ2 | d.f. | P | |
|---|---|---|---|
| bstatus | 110.06 | 2 | <0.0001 |
| day | 1405.28 | 4 | <0.0001 |
| Nonlinear | 388.96 | 3 | <0.0001 |
| age | 17.09 | 2 | 0.0002 |
| Nonlinear | 5.44 | 1 | 0.0197 |
| lips | 1.84 | 2 | 0.3994 |
| Nonlinear | 0.30 | 1 | 0.5823 |
| charlson | 7.13 | 3 | 0.0678 |
| Nonlinear | 1.04 | 2 | 0.5954 |
| sofa | 20.01 | 3 | 0.0002 |
| Nonlinear | 2.05 | 2 | 0.3594 |
| vitD (Factor+Higher Order Factors) | 19.97 | 6 | 0.0028 |
| All Interactions | 13.72 | 3 | 0.0033 |
| Nonlinear (Factor+Higher Order Factors) | 19.95 | 4 | 0.0005 |
| treatment (Factor+Higher Order Factors) | 17.48 | 4 | 0.0016 |
| All Interactions | 13.72 | 3 | 0.0033 |
| vitD × treatment (Factor+Higher Order Factors) | 13.72 | 3 | 0.0033 |
| Nonlinear | 13.68 | 2 | 0.0011 |
| Nonlinear Interaction : f(A,B) vs. AB | 13.68 | 2 | 0.0011 |
| TOTAL NONLINEAR | 407.50 | 13 | <0.0001 |
| TOTAL NONLINEAR + INTERACTION | 410.86 | 14 | <0.0001 |
| TOTAL | 1634.16 | 23 | <0.0001 |
There is evidence for interaction. Plot the interaction effect.
ggplot(Predict(g, vitD, treatment))To get the right confidence bands, form contrasts.
k <- contrast(g, list(treatment='Vitamin D', vitD=0:65),
list(treatment='Placebo', vitD=0:65))
k <- as.data.frame(k[c('vitD', 'Contrast', 'Lower', 'Upper')])
ggplot(k, aes(x=vitD, y=Contrast)) + geom_point() +
geom_errorbar(aes(ymin=Lower, ymax=Upper), width=0) There seems to be benefit of treatment in the very low range of baseline vitamin D and for those patients with high baseline vitamin D, but not in the middle.
Bayesian Random Effects Model Without Carrying Death Forward
Repeat the last model but using a Bayesian approach with normally distributed random effects for patient level intercepts. This is a compound symmetry type of correlation structure within patient. Before proceeding witih the full model try to find the smallest model that exhibits convergence problems that will be seen later with the full model.
stanSet()# This is fine:
bnocsnoc <- blrm(status ~ age, data=d, loo=FALSE, refresh=100,
file='bnocsnoc.rds')
stanDx(bnocsnoc)Iterations: 2000 on each of 4 chains, with 4000 posterior distribution samples saved
For each parameter, n_eff is a crude measure of effective sample size
and Rhat is the potential scale reduction factor on split chains
(at convergence, Rhat=1)
n_eff Rhat
y>=Vent/ARDS 4146 1.000
y>=In Hospital/Facility 4713 1.000
y>=Home 4700 0.999
age 4419 0.999
stanDxplot(bnocsnoc, which='ALL')# Problem with this one if rsdmean=0.3 or 0.08, minor prob if 0.005
bnocs <- blrm(status ~ age + cluster(id), psigma=1, rsdsd=0.075,
data=d, loo=FALSE, refresh=100, file='bnocs.rds')
# Previous: psigma=2 rsdmean=0.005; psigma=1 rsdmean=0.08
stanDx(bnocs)Iterations: 2000 on each of 4 chains, with 4000 posterior distribution samples saved
For each parameter, n_eff is a crude measure of effective sample size
and Rhat is the potential scale reduction factor on split chains
(at convergence, Rhat=1)
n_eff Rhat
y>=Vent/ARDS 421 1.003
y>=In Hospital/Facility 194 1.011
y>=Home 173 1.011
age 199 1.009
sigmag 385 1.008
stanDxplot(bnocs, which='ALL')
# Problematic even if binary for Home, but got slightly better with
# t(4, 0, 1) prior for sigma SD
# adding conc=0.5 rsdmean made things significanty worse
# b <- blrm(status ~ age + cluster(id), data=d, iter=1000, refresh=100)
# stanDx(b); stanDxplot(b, which='ALL')bnocsBayesian Proportional Odds Ordinal Logistic Model
Dirichlet Priors With Concentration Parameter 0.455 for Intercepts
blrm(formula = status ~ age + cluster(id), data = d, psigma = 1,
rsdsd = 0.075, refresh = 100, loo = FALSE, file = "bnocs.rds")
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
196 3343 11128
Home
19586
Frequencies of Missing Values Due to Each Variable
status age cluster(id)
50 0 0
|
Mixed Calibration/ Discrimination Indexes |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 34253 | B 0.006 [0.006, 0.006] | g 0.742 [0.574, 0.952] | C 0.582 [0.582, 0.582] |
| Draws 4000 | gp 0 [0, 0] | Dxy 0.163 [0.163, 0.163] | |
| Chains 4 | EV 0 [0, 0] | ||
| p 1 | v 0.435 [0.252, 0.7] | ||
Cluster on id
|
vp 0 [0, 0] | ||
| Clusters 1351 | |||
| σγ 3.2259 [3.0911, 3.3747] |
| Mean β | Median β | S.E. | Lower | Upper | Pr(β>0) | Symmetry | |
|---|---|---|---|---|---|---|---|
| y≥Vent/ARDS | 11.4263 | 11.4129 | 0.3425 | 10.7745 | 12.1094 | 1.0000 | 1.07 |
| y≥In Hospital/Facility | 6.3262 | 6.3142 | 0.3260 | 5.6944 | 6.9784 | 1.0000 | 1.04 |
| y≥Home | 1.9749 | 1.9653 | 0.3233 | 1.3710 | 2.6387 | 1.0000 | 1.03 |
| age | -0.0410 | -0.0408 | 0.0057 | -0.0533 | -0.0313 | 0.0000 | 0.95 |
bnocarry <- blrm(status ~ bstatus + rcs(day, 5) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) + treatment +
cluster(id), data=d, loo=FALSE, refresh=50, file='bnocarry.rds')
bnocarryBayesian Proportional Odds Ordinal Logistic Model
Dirichlet Priors With Concentration Parameter 0.455 for Intercepts
blrm(formula = status ~ bstatus + rcs(day, 5) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) + treatment +
cluster(id), data = d, refresh = 50, loo = FALSE, file = "bnocarry.rds")
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
189 3169 10862
Home
18988
Frequencies of Missing Values Due to Each Variable
status bstatus day age lips charlson
50 28 0 0 0 1045
sofa treatment cluster(id)
0 0 0
|
Mixed Calibration/ Discrimination Indexes |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 33208 | B 0.006 [0.006, 0.006] | g 4.077 [3.892, 4.272] | C 0.773 [0.77, 0.776] |
| Draws 4000 | gp 0 [0, 0.001] | Dxy 0.546 [0.54, 0.553] | |
| Chains 4 | EV 0.098 [0.015, 0.183] | ||
| p 17 | v 13.183 [11.97, 14.401] | ||
Cluster on id
|
vp 0 [0, 0] | ||
| Clusters 1309 | |||
| σγ 4.1683 [3.9875, 4.3536] |
| Mean β | Median β | S.E. | Lower | Upper | Pr(β>0) | Symmetry | |
|---|---|---|---|---|---|---|---|
| y≥Vent/ARDS | 8.2537 | 8.2419 | 0.9665 | 6.5110 | 10.2707 | 1.0000 | 1.01 |
| y≥In Hospital/Facility | -0.2323 | -0.2381 | 0.9608 | -2.0608 | 1.6383 | 0.4040 | 1.02 |
| y≥Home | -7.7042 | -7.7114 | 0.9637 | -9.6311 | -5.9360 | 0.0000 | 1.00 |
| bstatus=On Vent | 0.9488 | 0.9359 | 0.5272 | -0.0824 | 1.9521 | 0.9635 | 1.00 |
| bstatus=In Hospital | 4.7748 | 4.7693 | 0.5249 | 3.7904 | 5.8431 | 1.0000 | 1.07 |
| day | 0.6975 | 0.6970 | 0.0169 | 0.6649 | 0.7316 | 1.0000 | 0.98 |
| day’ | -1.1754 | -1.1746 | 0.1039 | -1.3757 | -0.9721 | 0.0000 | 1.01 |
| day’’ | 1.8060 | 1.8027 | 0.3214 | 1.1876 | 2.4208 | 1.0000 | 1.00 |
| day’’’ | -0.0027 | 0.0056 | 0.4316 | -0.8599 | 0.8159 | 0.5042 | 1.00 |
| age | -0.0003 | 0.0000 | 0.0186 | -0.0371 | 0.0366 | 0.4990 | 1.03 |
| age’ | -0.0287 | -0.0291 | 0.0166 | -0.0595 | 0.0053 | 0.0423 | 0.98 |
| lips | -0.0262 | -0.0269 | 0.1091 | -0.2349 | 0.1944 | 0.3985 | 1.07 |
| lips’ | -0.0787 | -0.0782 | 0.1009 | -0.2673 | 0.1185 | 0.2272 | 0.97 |
| charlson | -0.4306 | -0.4217 | 0.2920 | -1.0024 | 0.1340 | 0.0685 | 0.99 |
| charlson’ | 1.5518 | 1.5217 | 1.4831 | -1.5054 | 4.4033 | 0.8562 | 1.06 |
| charlson’’ | -3.6542 | -3.5987 | 3.4116 | -9.9032 | 3.5933 | 0.1395 | 0.94 |
| sofa | 0.0069 | 0.0120 | 0.1872 | -0.3533 | 0.3709 | 0.5212 | 0.89 |
| sofa’ | -0.3965 | -0.4190 | 0.7343 | -1.8090 | 1.0533 | 0.2828 | 1.11 |
| sofa’’ | 0.3921 | 0.4177 | 1.8166 | -3.0990 | 4.0762 | 0.5980 | 0.90 |
| treatment=Vitamin D | 0.4395 | 0.4486 | 0.2436 | -0.0398 | 0.9269 | 0.9575 | 0.98 |
a <- anova(bnocarry)
a
Relative Explained Variation for status. Approximate total model Wald χ2 used in denominators of REV:6411.9 [6129.9, 6754.7].
|
||||
| REV | Lower | Upper | d.f. | |
|---|---|---|---|---|
| bstatus | 0.029 | 0.023 | 0.039 | 2 |
| day | 0.977 | 0.968 | 0.983 | 4 |
| Nonlinear | 0.246 | 0.226 | 0.265 | 3 |
| age | 0.002 | 0.000 | 0.004 | 2 |
| Nonlinear | 0.000 | 0.000 | 0.002 | 1 |
| lips | 0.001 | 0.000 | 0.003 | 2 |
| Nonlinear | 0.000 | 0.000 | 0.001 | 1 |
| charlson | 0.002 | 0.000 | 0.005 | 3 |
| Nonlinear | 0.000 | 0.000 | 0.001 | 2 |
| sofa | 0.007 | 0.004 | 0.011 | 3 |
| Nonlinear | 0.001 | 0.000 | 0.003 | 2 |
| treatment | 0.001 | 0.000 | 0.002 | 1 |
| TOTAL NONLINEAR | 0.248 | 0.229 | 0.269 | 9 |
| TOTAL | 1.000 | 1.000 | 1.000 | 17 |
stanDx(bnocarry)Iterations: 2000 on each of 4 chains, with 4000 posterior distribution samples saved
For each parameter, n_eff is a crude measure of effective sample size
and Rhat is the potential scale reduction factor on split chains
(at convergence, Rhat=1)
n_eff Rhat
y>=Vent/ARDS 336 1.008
y>=In Hospital/Facility 138 1.026
y>=Home 101 1.038
bstatus=On Vent 110 1.042
bstatus=In Hospital 159 1.010
day 1357 1.000
day' 2714 1.001
day'' 3691 1.001
day''' 4264 1.000
age 141 1.032
age' 163 1.022
lips 121 1.038
lips' 52 1.076
charlson 126 1.027
charlson' 141 1.015
charlson'' 122 1.028
sofa 143 1.024
sofa' 140 1.024
sofa'' 159 1.017
treatment=Vitamin D 130 1.039
sigmag 264 1.005
stanDxplot(bnocarry)
ggplot(Predict(bnocarry))plot(a) Compute the posterior probability that treatment raises the chance of a patient having a given outcome or better (this is already in the coefficient table above).
P <- PostF(bnocarry, name='orig')
P(`treatment=Vitamin D` > 0)[1] 0.9575
For comparison, fit a similar Bayesian model adjusting only for time, and one not adjusting for any covariates.
bnocarry2 <- blrm(status ~ rcs(day, 5) + treatment +
cluster(id), data=d, loo=FALSE, refresh=50, file='bnocarry2.rds')
bnocarry2Bayesian Proportional Odds Ordinal Logistic Model
Dirichlet Priors With Concentration Parameter 0.455 for Intercepts
blrm(formula = status ~ rcs(day, 5) + treatment + cluster(id),
data = d, refresh = 50, loo = FALSE, file = "bnocarry2.rds")
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
196 3343 11128
Home
19586
Frequencies of Missing Values Due to Each Variable
status day treatment cluster(id)
50 0 0 0
|
Mixed Calibration/ Discrimination Indexes |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 34253 | B 0.006 [0.006, 0.006] | g 2.627 [2.547, 2.691] | C 0.711 [0.71, 0.711] |
| Draws 4000 | gp 0 [0, 0] | Dxy 0.422 [0.42, 0.423] | |
| Chains 4 | EV 0 [0, 0] | ||
| p 5 | v 5.784 [5.503, 6.074] | ||
Cluster on id
|
vp 0 [0, 0] | ||
| Clusters 1351 | |||
| σγ 5.0107 [4.7918, 5.2634] |
| Mean β | Median β | S.E. | Lower | Upper | Pr(β>0) | Symmetry | |
|---|---|---|---|---|---|---|---|
| y≥Vent/ARDS | 9.2229 | 9.2242 | 0.2474 | 8.7477 | 9.7103 | 1.0000 | 0.99 |
| y≥In Hospital/Facility | 0.7985 | 0.7963 | 0.2049 | 0.4063 | 1.1985 | 1.0000 | 0.94 |
| y≥Home | -6.5560 | -6.5525 | 0.2136 | -6.9970 | -6.1586 | 0.0000 | 0.93 |
| day | 0.6986 | 0.6988 | 0.0163 | 0.6660 | 0.7290 | 1.0000 | 1.02 |
| day’ | -1.2033 | -1.2027 | 0.1006 | -1.4030 | -1.0111 | 0.0000 | 0.96 |
| day’’ | 1.8840 | 1.8821 | 0.3113 | 1.2824 | 2.4896 | 1.0000 | 1.02 |
| day’’’ | -0.0628 | -0.0655 | 0.4169 | -0.8835 | 0.7454 | 0.4395 | 1.02 |
| treatment=Vitamin D | 0.2469 | 0.2403 | 0.2630 | -0.3019 | 0.7672 | 0.8315 | 1.11 |
bnocarry3 <- blrm(status ~ treatment + cluster(id),
data=d, loo=FALSE, refresh=50, file='bnocarry3.rds')
bnocarry3Bayesian Proportional Odds Ordinal Logistic Model
Dirichlet Priors With Concentration Parameter 0.455 for Intercepts
blrm(formula = status ~ treatment + cluster(id), data = d, refresh = 50,
loo = FALSE, file = "bnocarry3.rds")
Frequencies of Responses
Dead Vent/ARDS In Hospital/Facility
196 3343 11128
Home
19586
Frequencies of Missing Values Due to Each Variable
status treatment cluster(id)
50 0 0
|
Mixed Calibration/ Discrimination Indexes |
Discrimination Indexes |
Rank Discrim. Indexes |
|
|---|---|---|---|
| Obs 34253 | B 0.006 [0.006, 0.006] | g 0.088 [0, 0.226] | C 0.511 [0.473, 0.527] |
| Draws 4000 | gp 0 [0, 0] | Dxy 0.023 [-0.053, 0.053] | |
| Chains 4 | EV 0 [0, 0] | ||
| p 1 | v 0.012 [0, 0.051] | ||
Cluster on id
|
vp 0 [0, 0] | ||
| Clusters 1351 | |||
| σγ 3.2963 [3.1478, 3.4361] |
| Mean β | Median β | S.E. | Lower | Upper | Pr(β>0) | Symmetry | |
|---|---|---|---|---|---|---|---|
| y≥Vent/ARDS | 9.0687 | 9.0673 | 0.1694 | 8.7362 | 9.3921 | 1.0000 | 1.00 |
| y≥In Hospital/Facility | 3.9605 | 3.9591 | 0.1361 | 3.7138 | 4.2406 | 1.0000 | 1.06 |
| y≥Home | -0.3899 | -0.3909 | 0.1324 | -0.6394 | -0.1336 | 0.0008 | 0.99 |
| treatment=Vitamin D | 0.1152 | 0.1155 | 0.1948 | -0.2774 | 0.4813 | 0.7225 | 0.94 |
Adjusting only for time and not other baseline covariates, the between-patient outcome heterogeneity is greater as makes sense, and the treatment effect remains diminished. When not even adjusting for time, the value of \(\sigma_\gamma\) ironically becomes lower than from the model with full covariate adjustment, and the treatment effect becomes very small.
Bayesian PO Random Effects Model With Time by Treatment Interaction
We go back to adjusting for the full set of covariates, and allow time to nonlinearly interact with treatment.
btxtime <- blrm(status ~ bstatus + treatment * rcs(day, 4) + rcs(age, 3) +
rcs(lips, 3) + rcs(charlson, 4) + rcs(sofa, 4) +
cluster(id), data=d, loo=FALSE, refresh=50, file='btxtime.rds')
stanDx(btxtime)Iterations: 2000 on each of 4 chains, with 4000 posterior distribution samples saved
For each parameter, n_eff is a crude measure of effective sample size
and Rhat is the potential scale reduction factor on split chains
(at convergence, Rhat=1)
n_eff Rhat
y>=Vent/ARDS 309 1.013
y>=In Hospital/Facility 149 1.022
y>=Home 120 1.023
bstatus=On Vent 142 1.027
bstatus=In Hospital 143 1.020
treatment=Vitamin D 154 1.011
day 1979 1.005
day' 3281 1.000
day'' 3943 1.001
age 131 1.026
age' 119 1.031
lips 67 1.064
lips' 149 1.012
charlson 144 1.038
charlson' 155 1.033
charlson'' 79 1.066
sofa 168 1.017
sofa' 164 1.011
sofa'' 104 1.053
treatment=Vitamin D * day 3919 1.000
treatment=Vitamin D * day' 3880 1.000
treatment=Vitamin D * day'' 4018 1.000
sigmag 298 1.010
stanDxplot(btxtime)