0

I am analyzing the ratio of (biomass of one part of a plant community) vs. (total plant community biomass) across different treatments in time (i.e. repeated measures) in R. Hence, it seems natural to use beta regression with a mixed component (available with the glmmTMB package) in order to account for repeated measures.

My problem is about computing post hoc comparisons across my treatments with the function lsmeans from the lsmeans package. glmmTMB objects are not handled by the lsmeans function so Ben Bolker on recommended to add the following code before loading the packages {glmmTMB} and {lsmeans}:

recover.data.glmmTMB <- function(object, ...) {
   fcall <- getCall(object)
   recover.data(fcall,delete.response(terms(object)),
             attr(model.frame(object),"na.action"), ...)}
lsm.basis.glmmTMB <- function (object, trms, xlev, grid, vcov.,
                           mode = "asymptotic", component="cond", ...) {
    if (mode != "asymptotic") stop("only asymptotic mode is available")
    if (component != "cond") stop("only tested for conditional component")
    if (missing(vcov.)) 
        V <- as.matrix(vcov(object)[[component]])
    else V <- as.matrix(.my.vcov(object, vcov.))
    dfargs = misc = list()
    if (mode == "asymptotic") {
       dffun = function(k, dfargs) NA
    }
    ## use this? misc = .std.link.labels(family(object), misc)
    contrasts = attr(model.matrix(object), "contrasts")
    m = model.frame(trms, grid, na.action = na.pass, xlev = xlev)
    X = model.matrix(trms, m, contrasts.arg = contrasts)
    bhat = fixef(object)[[component]]
    if (length(bhat) < ncol(X)) {
        kept = match(names(bhat), dimnames(X)[[2]])
        bhat = NA * X[1, ]
        bhat[kept] = fixef(object)[[component]]
        modmat = model.matrix(trms, model.frame(object), contrasts.arg = contrasts)
        nbasis = estimability::nonest.basis(modmat)
     }
    else nbasis = estimability::all.estble
    list(X = X, bhat = bhat, nbasis = nbasis, V = V, dffun = dffun, 
        dfargs = dfargs, misc = misc)
}

Here is my code and data:

trt=c(rep("T5",13),rep("T4",13),
  rep("T3",13),rep("T1",13),rep("T2",13),rep("T1",13),
  rep("T2",13),rep("T3",13),rep("T5",13),rep("T4",13))
 year=rep(2005:2017,10)
 plot=rep(LETTERS[1:10],each=13)
  ratio=c(0.0046856237844411,0.00100861922394448,0.032516291436091,0.0136507743972955,0.0940240065096705,0.0141337428305094,0.00746709315018945,0.437009092691189,0.0708021091805216,0.0327952505849285,0.0192685194751524,0.0914696394299481,0.00281889216102303,0.0111928453399615,0.00188119596836005,NA,0.000874623692966351,0.0181192859074754,0.0176635391424644,0.00922358069727823,0.0525280029990213,0.0975006760149882,0.124726170684951,0.0187132600944396,0.00672592365451266,0.106399234215126,0.0401776844073239,0.00015382736648373,0.000293356424756535,0.000923659501144292,0.000897412901472504,0.00315930225856196,0.0636501228611642,0.0129422445492391,0.0143526630252398,0.0136775931834926,0.00159292971508751,0.0000322313783211749,0.00125352390811532,0.0000288862579879126,0.00590690336494395,0.000417043974238875,0.0000695808216192379,0.001301299696752,0.000209355138230326,0.000153151660178623,0.0000646279598274632,0.000596704590065324,9.52943306579156E-06,0.000113476446629278,0.00825405312309618,0.0001025984082064,0.000887617767039489,0.00273668802742924,0.00469409165130462,0.00312377000134233,0.0015579322817235,0.0582615988387306,0.00146933878743163,0.0405139497779372,0.259097955479886,0.00783997376383192,0.110638003652979,0.00454029511918275,0.00728290246595241,0.00104674197030363,0.00550563937846687,0.000121380392484705,0.000831904606687671,0.00475778829159394,0.000402799910756391,0.00259524300745195,0.000210249875492504,0.00550104485802363,0.000272849546913495,0.0025389089622392,0.00129370075116459,0.00132810234020792,0.00523285954007915,0.00506230599388357,0.00774104695265855,0.00098348404576587,0.174079173227248,0.0153486840317039,0.351820365452281,0.00347674458928481,0.147309225196026,0.0418825705903947,0.00591271021100856,0.0207139520537443,0.0563647804012055,0.000560012457272534,0.00191564842393647,0.01493480083524,0.00353400674061077,0.00771828473058641,0.000202009136938048,0.112695841130448,0.00761492172670762,0.038797330459115,0.217367765362878,0.0680958660605668,0.0100870294641921,0.00493875324236991,0.00136539944656238,0.00264262100866192,0.0847732305020654,0.00460985241335143,0.235802638543116,0.16336020383325,0.225776236687456,0.0204568107372349,0.0455390585228863,0.130969863489582,0.00679523322812889,0.0172325334280024,0.00299970176999806,0.00179347656925317,0.00721658257996989,0.00822443690003783,0.00913096724026346,0.0105920192618379,0.0158013204589482,0.00388803567197835,0.00366268607026078,0.0545418725650633,0.00761485067129418,0.00867583194858734,0.0188232707241144,0.018652666214789)
dat=data.frame(trt,year,plot,ratio)
require(glmmTMB)
require(lsmeans)
mod=glmmTMB(ratio~trt*scale(year)+(1|plot),family=list(family="beta",link="logit"),data=dat)
summary(mod)
ls=lsmeans(mod,pairwise~trt)`

Finally, I get the following error message that I've never encountered and on which I could find no information:

In model.matrix.default(trms, m, contrasts.arg = contrasts) : variable 'plot' is absent, its contrast will be ignored

Could anyone shine their light? Thanks!

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453

1 Answers1

2

This is not an error message, it's a (harmless) warning message. It occurs because the hacked-up method I wrote doesn't exclude factor variables that are only used in the random effects. You should worry more about this output:

NOTE: Results may be misleading due to involvement in interactions

which is warning you that you are evaluating main effects in a model that contains interactions; you have to think about this carefully to make sure you're doing it right.

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Hi Ben. First of all, thank you very much for your answer. It is reassuring :) Second, I was also surprised by this message "Results may be misleading due to involvement in interactions" because when I compare the model with interaction (year x trt, AIC=-742) against the additive model (year+trt, AIC=-748), I get Pr(>Chisq)=0.78. Hence I conclude that I can do the posthoc lsmeans(mod,pairwise~trt) instead of lsmeans(mod,pairwise~trt*year). Thank you again for you implication. – Guillaume A2 Feb 05 '18 at 08:12
  • 1
    Well, `lsmeans` doesn't make a determination about the importance of the interaction; that is up to the user. If you don't think the interaction is important, consider leaving it out of the model (in which case you won't get the warning message), or leaving it as-is and ignoring the warning message -- your choice. – Russ Lenth Feb 05 '18 at 19:02
  • 1
    Unrelated comment. It'd be better to use the **emmeans** package to do this, as **lsmeans** will be deprecated in another year or so. It'd require simple adaptations to @BenBolker 's code (replacing `recover.data` with `recover_data` and `lsm.basis` with `emm_basis`). Ideally, that code could be incorporated and exported in **glmmTMB** so that it is already available to users. – Russ Lenth Feb 05 '18 at 19:07
  • 1
    agree. It's already in a branch in glmmTMB [here](https://github.com/glmmtmb/glmmTMB/tree/effects), but I was waiting to merge it with the master branch until it was farther along. But since the version on GH is a development version anyway, maybe I should err on the side of making it visible/usable so we get more feedback. – Ben Bolker Feb 05 '18 at 21:34
  • @BenBolker I’ll take a look. Seems like there’s potential for more options with zero- inflated models, along the lines of existing support for the pscl package. But the calculus needed for the delta method is a pain. – Russ Lenth Feb 06 '18 at 01:21
  • thanks. I wonder if it's worth doing any of the delta method stuff by machine rather than by hand? (inefficient in computer time, but maybe worth it anyway). – Ben Bolker Feb 06 '18 at 01:26