4

I have a multilevel repeated measures dataset of around 300 patients each with up to 10 repeated measures predicting troponin rise. There are other variables in the dataset, but I haven't included them here. I am trying to use nlme to create a random slope, random intercept model where effects vary between patients, and effect of time is different in different patients. When I try to introduce a first-order covariance structure to allow for the correlation of measurements due to time I get the following error message.

Error in `coef<-.corARMA`(`*tmp*`, value = value[parMap[, i]]) : Coefficient matrix not invertible

I have included my code and a sample of the dataset, and I would be very grateful for any words of wisdom.

#baseline model includes only the intercept. Random slopes - intercept varies across patients
randomintercept <- lme(troponin ~ 1,
                       data = df, random = ~1|record_id, method = "ML", 
                       na.action = na.exclude, 
                       control = list(opt="optim"))

#random intercept and time as fixed effect
timeri <- update(randomintercept,.~. + day)
#random slopes and intercept: effect of time is different in different people
timers <- update(timeri, random = ~ day|record_id)
#model covariance structure. corAR1() first order autoregressive covariance structure, timepoints equally spaced
armodel <- update(timers, correlation = corAR1(0, form = ~day|record_id))
Error in `coef<-.corARMA`(`*tmp*`, value = value[parMap[, i]]) : Coefficient matrix not invertible

Data:

record_id   day troponin
1   1   32  
2   0     NA  
2   1   NA  
2   2   NA  
2   3   8  
2   4   6  
2   5   7  
2   6   7  
2   7   7  
2   8   NA  
2   9   9  
3   0   14  
3   1   1167  
3   2   1935  
4   0   19  
4   1   16  
4   2   29  
5   0   NA  
5   1   17  
5   2   47  
5   3   684  
6   0   46  
6   1   45440  
6   2   47085  
7   0   48  
7   1   87  
7   2   44  
7   3   20  
7   4   15  
7   5   11  
7   6   10  
7   7   11  
7   8   197  
8   0   28  
8   1   31  
9   0   NA  
9   1   204  
10  0   NA  
10  1   19  
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
Annemarie
  • 123
  • 1
  • 8

1 Answers1

5

You can fit this if you change your optimizer to "nlminb" (or at least it works with the reduced data set you posted).

armodel <- update(timers, 
              correlation = corAR1(0, form = ~day|record_id),
              control=list(opt="nlminb"))

However, if you look at the fitted model, you'll see you have problems - the estimated AR1 parameter is -1 and the random intercept and slope terms are correlated with r=0.998.

I think the problem is with the nature of the data. Most of the data seem to be in the range 10-50, but there are excursions by one or two orders of magnitude (e.g. individual 6, up to about 45000). It might be hard to fit a model to data this spiky. I would strongly suggest log-transforming your data; the standard diagnostic plot (plot(randomintercept)) looks like this:

fitted vs residual

whereas fitting on the log scale

rlog <- update(randomintercept,log10(troponin) ~ .)
plot(rlog)

enter image description here

is somewhat more reasonable, although there is still some evidence of heteroscedasticity.

The AR+random-slopes model fits OK:

ar.rlog <- update(rlog,
              random = ~day|record_id,
              correlation = corAR1(0, form = ~day|record_id))
## Linear mixed-effects model fit by maximum likelihood
## ...
## Random effects:
##  Formula: ~day | record_id
##  Structure: General positive-definite, Log-Cholesky parametrization
##             StdDev    Corr  
## (Intercept) 0.1772409 (Intr)
## day         0.6045765 0.992 
## Residual    0.4771523       
##
##  Correlation Structure: ARMA(1,0)
##  Formula: ~day | record_id 
##  Parameter estimate(s):
##       Phi1 
## 0.09181557 
## ...

A quick glance at intervals(ar.rlog) shows that the confidence intervals on the autoregressive parameter are (-0.52,0.65), so it may not be worth keeping ...

With the random slopes in the model the heteroscedasticity no longer seems problematic ...

plot(rlog,sqrt(abs(resid(.)))~fitted(.),type=c("p","smooth"))

enter image description here

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Thank you very much for your help. Yes, the data is this spiky, and you're entirely right, log transforming it does make it look better. I can't work out how to add the images into these comments, but the whole dataset residuals broadly looks like yours. I've changed the optimiser to nlminb, but now I can't get the model to converge. Would you have any further advice? Many thanks, Annemarie nlminb problem, convergence error code = 1 message = iteration limit reached without convergence (10) – Annemarie Sep 02 '16 at 12:34
  • see `?lmeControl`, (especially `maxIter`, `msMaxIter`), although it may not solve the problem. – Ben Bolker Sep 02 '16 at 13:16
  • Thanks very much @Ben Bolker – Annemarie Sep 02 '16 at 18:00
  • While the sentiment is appreciated, StackOverflow deprecates [using comments to say "thank you"](http://meta.stackoverflow.com/questions/258004/should-thank-you-comments-be-flagged?lq=1); if this answer was useful you can upvote it (if you have sufficient reputation), and in any case if it answers your question satisfactorily you are encouraged to click the check-mark to accept it. – Ben Bolker Sep 02 '16 at 18:16