How do I extract lmer fixed effects by observation?

前端 未结 2 1597
时光说笑
时光说笑 2021-02-03 14:45

I have a lme object, constructed from some repeated measures nutrient intake data (two 24-hour intake periods per RespondentID):

Male.lme2 <- lmer(BoxCoxXY ~          


        
相关标签:
2条回答
  • 2021-02-03 15:12

    Below is how I've always found it easiest to extract the individuals' fixed effects and random effects components in the lme4-package. It actually extracts the corresponding fit to each observation. Assuming we have a mixed-effects model of form:

    y = Xb + Zu + e
    

    where Xb are the fixed effects and Zu are the random effects, we can extract the components (using lme4's sleepstudy as an example):

    library(lme4)
    fm1 <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)
    
    # Xb 
    fix <- getME(fm1,'X') %*% fixef(fm1)
    # Zu
    ran <- t(as.matrix(getME(fm1,'Zt'))) %*% unlist(ranef(fm1))
    # Xb + Zu
    fixran <- fix + ran
    

    I know that this works as a generalized approach to extracting components from linear mixed-effects models. For non-linear models, the model matrix X contains repeats and you may have to tailor the above code a bit. Here's some validation output as well as a visualization using lattice:

    > head(cbind(fix, ran, fixran, fitted(fm1)))
             [,1]      [,2]     [,3]     [,4]
    [1,] 251.4051  2.257187 253.6623 253.6623
    [2,] 261.8724 11.456439 273.3288 273.3288
    [3,] 272.3397 20.655691 292.9954 292.9954
    [4,] 282.8070 29.854944 312.6619 312.6619
    [5,] 293.2742 39.054196 332.3284 332.3284
    [6,] 303.7415 48.253449 351.9950 351.9950
    
    # Xb + Zu
    > all(round((fixran),6) == round(fitted(fm1),6))
    [1] TRUE
    
    # e = y - (Xb + Zu)
    > all(round(resid(fm1),6) == round(sleepstudy[,"Reaction"]-(fixran),6))
    [1] TRUE
    
    nobs <- 10 # 10 observations per subject
    legend = list(text=list(c("y", "Xb + Zu", "Xb")), lines = list(col=c("blue", "red", "black"), pch=c(1,1,1), lwd=c(1,1,1), type=c("b","b","b")))
    require(lattice)
    xyplot(
        Reaction ~ Days | Subject, data = sleepstudy,
        panel = function(x, y, ...){
            panel.points(x, y, type='b', col='blue')
            panel.points(x, fix[(1+nobs*(panel.number()-1)):(nobs*(panel.number()))], type='b', col='black')
            panel.points(x, fixran[(1+nobs*(panel.number()-1)):(nobs*(panel.number()))], type='b', col='red')
        },
        key = legend
    )
    

    enter image description here

    0 讨论(0)
  • 2021-02-03 15:23

    It is going to be something like this (although you really should have given us the results of str(Male.Data) because model output does not tell us the factor levels for the baseline values:)

    #First look at the coefficients
    fixef(Male.lme2)
    
    #Then do the calculations
    fixef(Male.lme2)[`(Intercept)`] + 
    c(0,fixef(Male.lme2)[2:4])[
              match(Male.Data$AgeFactor, c("1to3", "4to8", "9to13","14to18") )] + 
    c(0,fixef(Male.lme2)[5])[
              match(Male.Data$IntakeDay, c("Day1Intake","Day2Intake") )]
    

    You are basically running the original data through a match function to pick the correct coefficient(s) to add to the intercept ... which will be 0 if the data is the factor's base level (whose spelling I am guessing at.)

    EDIT: I just noticed that you put a "-1" in the formula so perhaps all of your AgeFactor terms are listed in the output and you can tale out the 0 in the coefficient vector and the invented AgeFactor level in the match table vector.

    0 讨论(0)
提交回复
热议问题