rsaslme4proc

R to SAS: from glmer to PROC NLMIXED


I know my question might not be exactly on the usual SO topics, but I'm really desperate. I've been trying to find what's wrong with my code for months.

I need the SAS equivalent with PROC NLMIXED to get the complete variance-covariance matrix of this model, written on R with lme4::glmer :

(after "poissonizing" my survival data with the library surrosurv, it looks like the snippet below. var1, var2 and cov are factor variables)

 data_pois = surrosurv::poissonize(data, interval.width = interval.width, factors = c ('var1', 'var2', 'cov'), compress = FALSE)
head(data_pois)
     id event  var1    var2 cov         time interval
1225  1     0 -0.5       13   1 0.0005669899        0
822   2     1 -0.5        9   1 0.0947011826        0
611   3     1 -0.5        7   1 0.0951096974        0
235   4     1 -0.5        3   0 0.1028146920        0
1847  5     0 -0.5       19   1 0.1122793044        0
1321  6     1 -0.5       14   1 0.1298256694        0
    mod    =  lme4::glmer(
      formula = event ~ -1 + interval : factor(var1) + cov + offset(log(time))+ (0 + var1 | var2 ) + (1 | var2 ),
      data = data_pois, 
      family = poisson(link = "log"),
      control=glmerControl(optCtrl=list(maxfun=2e5), optimizer="bobyqa"))

The details of the covariate are:


Solution

  • I'm assuming you want an overall independent random intercept and another set of correlated ones for each non-reference level of var1.

    From the information that you provided and with my admittedly pretty superficial knowledge of both languages and the underlying statistics, I think the matching NLMIXED call could look something like this:

    proc nlmixed data=data_pois;
       /* Create dummies as needed/desired - more will be required if >2 levels exist. */
       dummy_var1 = (var1 eq -0.5);
       dummy_cov = (cov eq 0);
    
       /* Random effects, see caveats below. */
       random r1 r2 ~ normal([0, 0], [rsig1, 0, rsig2]) subject=var2;
    
       /* Linear predictor. */
       eta = b1*interval + b2*dummy_var1*interval + b3*dummy_cov1 + r1*dummy_var1 + r2 + log(time);
       mu = exp(eta);
    
       /* Option 1: use built-in distribution. */
       model event ~ poisson(mu);
       /* Option 2: write out log-likelihood by hand. */
       ll = event * log(mu) - mu - lgamma(event + 1);
       model event ~ general(ll); /* The DV can be anything here, its value doesn't matter. */
    run;
    

    This is quite bare-bones, I would almost certainly add a parms statement to initialize model parameters to more sensible values such as those precomputed from a fixed effects-only model. It's usually also a good idea to express your variances in the log scale (which will double as a bounds statement) and add extra boundary checks before making any transformations. You'll probably want to include additional tuning and/or convergence options in the NLMIXED call as well.

    Finally, returning to the random effects, it really depends on what you want to do here exactly. A limitation of PROC NLMIXED is that random effects have to be nested if you're adding more than one - this is not an issue here if you're using a single blocking level. It's still up to you to define how the additional levels of r1 (to be added) covary if there's more than 2 levels of var1, I believe glmer makes this unstructured by default.