4

I've fitted a mixed model using the lme4 package. I transformed my independent variables with the scale() function prior to fitting the model. I now want to display my results on a graph using predict(), so I need the predicted data to be back on the original scale. How do I do this?

Simplified example:

database <- mtcars

# Scale data
database$wt <- scale(mtcars$wt)
database$am <- scale(mtcars$am)

# Make model
model.1 <- glmer(vs ~ scale(wt) + scale(am) + (1|carb), database, family = binomial, na.action = "na.fail")

# make new data frame with all values set to their mean
xweight <- as.data.frame(lapply(lapply(database[, -1], mean), rep, 100))

# make new values for wt
xweight$wt <- (wt = seq(min(database$wt), max(database$wt), length = 100))

#  predict from new values
a <- predict(model.1, newdata = xweight, type="response", re.form=NA)

# returns scaled prediction

I've tried using this example to back-transform the predictions:

# save scale and center values
scaleList <- list(scale = attr(database$wt, "scaled:scale"),
              center = attr(database$wt, "scaled:center"))

# back-transform predictions
a.unscaled <- a * scaleList$scale + scaleList$center

# Make model with unscaled data to compare
un.model.1 <- glmer(vs ~ wt + am + (1|carb), mtcars, family = binomial, na.action = "na.fail")

# make new data frame with all values set to their mean
un.xweight <- as.data.frame(lapply(lapply(mtcars[, -1], mean), rep, 100))

# make new values for wt
un.xweight$wt <- (wt = seq(min(mtcars$wt), max(mtcars$wt), length = 100))

#  predict from new values
b <- predict(un.model.1, newdata = xweight, type="response", re.form=NA)

all.equal(a.unscaled,b)
# [1] "Mean relative difference: 0.7223061"

This doesn't work - there shouldn't be any difference. What have I done wrong?

I've also looked at a number of similar questions but not managed to apply any to my case (How to unscale the coefficients from an lmer()-model fitted with a scaled response, unscale and uncenter glmer parameters, Scale back linear regression coefficients in R from scaled and centered data, https://stats.stackexchange.com/questions/302448/back-transform-mixed-effects-models-regression-coefficients-for-fixed-effects-f).

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
Thomas
  • 392
  • 5
  • 18

1 Answers1

4

The problem with your approach is that it only "unscales" based on the wt variable, whereas you scaled all of the variables in your regression model. One approach that works is to adjust all of the variables in your new (prediction) data frame using the centering/scaling values that were used on the original data frame:

## scale variable x using center/scale attributes
## of variable y
scfun <- function(x,y) {
    scale(x, 
          center=attr(y,"scaled:center"), 
          scale=attr(y,"scaled:scale"))
}
## scale prediction frame
xweight_sc <- transform(xweight,
                        wt = scfun(wt, database$wt),
                        am = scfun(am, database$am))
## predict
p_unsc <- predict(model.1, 
                  newdata=xweight_sc, 
                  type="response", re.form=NA)

Comparing this p_unsc to your predictions from the unscaled model (b in your code), i.e. all.equal(b,p_unsc), gives TRUE.

Another reasonable approach would be to

  • unscale/uncenter all of your parameters using the "unscaling" approaches presented in one of the linked question (such as this one), generating a coefficient vector beta_unsc
  • construct the appropriate model matrix from your prediction frame:
X <- model.matrix(formula(model,fixed.only=TRUE), 
         newdata=pred_frame)
  • compute the linear predictor and back-transform:
pred <- plogis(X %*% beta_unsc)
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Thanks @BenBolker, that's brilliant. The reason I wanted to unscale the data was to display it in a plot, I'm still having issues with this. I'm not sure if the error is in the code I've used in this question or in the code I'm using to plot. I've asked this question in another post (https://stackoverflow.com/questions/53193940/plotting-results-of-logistic-regression-with-binomial-data-from-mixed-effects-mo), now updated to include your unscale fix. Any ideas what I've done wrong? – Thomas Dec 13 '18 at 09:12
  • 1
    In Python there are StandarScaler Transform and Inverse_Tranform functions which make this process very easy, keeping track automatically of everything. Is there anything similar in R? – skan May 18 '23 at 15:36
  • Not that I'm immediately aware of. A shown here `scale()` attaches attributes to the scaled data that give the centering and scaling constants and so can be used for unscaling, but these attributes aren't necessarily preserved in the information available from the model fit. It would not be hard to write such machinery in R; the only slightly tricky part is that mutable objects are slightly non-idiomatic in R (i.e., you would want to make sure that the `scaler` had an environment associated with it and stored scaling info in its environment ...) – Ben Bolker May 18 '23 at 19:59