Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ggpredict shows inaccurate results for models based on lme #297

Open
ndsubison2178 opened this issue Mar 21, 2023 · 12 comments
Open

ggpredict shows inaccurate results for models based on lme #297

ndsubison2178 opened this issue Mar 21, 2023 · 12 comments
Labels
nlme 💾 Issue related to certain packages reprex 💾 An example (and data) to reproduce the issue is needed to waiting for response 💌 Response from users awaited

Comments

@ndsubison2178
Copy link

ndsubison2178 commented Mar 21, 2023

There is a flaw in this ggeffects library.

  1. ggeffect shows erroneous and incorrect results if you try to predict values using estimates from lme model from nlme package.
    However if you use lme4 instead of lme, everything works fine.

  2. The x-axis labels are not accurate. the x-axis lables are marked 1,2,3....n observation number instead of actual x values.

@strengejacke
Copy link
Owner

Do you have a reproducible example? This one, e.g. works:

library(ggeffects)
library(nlme)

m <- lme(
  distance ~ age, data = Orthodont,
 random = ~ 1 | Sex)
ggpredict(m, "age")
#> # Predicted values of distance
#> 
#> age | Predicted |         95% CI
#> --------------------------------
#>   8 |     21.84 | [19.46, 24.21]
#>  10 |     23.16 | [20.85, 25.47]
#>  12 |     24.48 | [22.17, 26.79]
#>  14 |     25.80 | [23.42, 28.17]
#> 
#> Adjusted for:
#> * Sex = 0 (population-level)
plot(ggpredict(m, "age"))

Created on 2023-03-21 with reprex v2.0.2

@strengejacke strengejacke added the reprex 💾 An example (and data) to reproduce the issue is needed to label Mar 21, 2023
@ndsubison2178
Copy link
Author

ndsubison2178 commented Mar 21, 2023

@strengejacke

Dear S, I am using a dataset in a controlled environment which cannot be exported. However this dataset is very close to the issue I experienced.

This is my example,

library(lme4)
data(Soybean)
library(plyr)
library(nlme)
library(ggplot2)
library(ggeffects)
library(lemon)

LME_Model <- dlply(Soybean,
"Year",
function(x)
lme(fixed = weight ~ Time,
random = ~ 1 |Variety ,
data=x, na.action=na.exclude))

preds <- purrr::map(LME_Model ,
function(x) ggpredict(x,
c("Time[all]", "Variety "), type="re") %>% as.data.frame())
preds <- bind_rows(preds, .id="Year")

image

ggplot(preds, aes(x=x, y=predicted,
color=group, fill=group)) +
geom_line() +
facet_grid(Year~ .)

image

@strengejacke
Copy link
Owner

From your example, I can't see any error with lme. Can you elaborate a bit more on which error you experience?
Furthermore, I can't see any issues with the x-labels. Please provide a reproducible example, so I can try to find any errors.

@strengejacke strengejacke added the waiting for response 💌 Response from users awaited label Apr 30, 2023
@DHLocke
Copy link

DHLocke commented Oct 2, 2023

Sorry if this is the wrong issue to add this reprex... ggpredict does not provide confidence intervals for gamlss model (which is calling nlme::lme) but sjPlot:: does provide confidence intervals.

library(tidyverse)
library(palmerpenguins)
library(gamlss)
library(broom)
library(sjPlot)
library(ggeffects)
library(broom.mixed)

# add proportion outcome, drop NAs
penguins <- 
  penguins |> 
  mutate(prop = rBE(nrow(penguins), mu = 0.5, sigma = 0.2)) |> 
  drop_na() |> 
  droplevels()

# fit model
mod <- 
  gamlss::gamlss(prop ~ sex*body_mass_g + year + re(random = list(~1 | species, ~1 | island))
                 , family = BE()
                 , data = penguins)

# examine outputs
# broom
mod |> broom.mixed::tidy(conf.int = TRUE) # nice confidence intervals (CIs), some warnings

# sjPlot
mod |> sjPlot::plot_model() # CIs present, no warnings
mod |> sjPlot::tab_model() # CIs present, no warnings


# ggeffects
mod |> ggeffects::ggpredict() # warnings and no CIs
mod |> ggeffects::ggpredict(terms = c('sex', 'body_mass_g')) # warnings and no CIs
mod |> ggeffects::ggeffect(terms = c('sex', 'body_mass_g')) # warnings and no output
mod |> ggeffects::ggemmeans(terms = c('sex', 'body_mass_g')) # warnings and no output

# end.  

@strengejacke
Copy link
Owner

I think the issue is that standard errors for coefficients are returned, but not for predictions. That's why plot_model() or parameters::model_parameters() include SE and CI (like summary()), but predictions probably don't. I'll look into this to confirm. You may try ggemmeans(), which relies on emmean(), not predict().

@DHLocke
Copy link

DHLocke commented Oct 16, 2023

Thank you. The last line is calling ggpmeans.

An additional issue I have noticed is that the tab_model() seems to be using exp() on the estimates, but the link function is logit (not log). I therefore think the appropriate transformation is the inverse logit like

inv_logit <- function(p) exp(p) / (1 + exp(p))

summary(mod) #shows the mu intercept is 9.080e+00

mod |> sjPlot::tab_model() # produces 8774.88
exp(9.080e+00) # 8774.88 non-sensical given the outcome is a proportion with mu = 0.5, sigma = 0.2

but
inv_logit(9.080e+00) # 0.9998861

same for the other intercept (sigma)
summary(mod) #shows the sigma intercept is -1.39712 with a logit link
exp(-1.39712) # 0.2473082 matching tab_model's .25
inv_logit(-1.39712) # 0.1982735, this is the original sigma given in the made up example. The model recovers the parameter correctly.

Maybe this is an error? Wrong transformation?
My broader (personal) issue is trying to get anything interpretable out of a gamlss model with random effects with family = BEINF(). I love the sjPlot / ggpredict infrastructure and workflow so much. But I am struggling to extract interpretable (coefficients, means, predictions) for this complex model. Thanks for such great software, I use it all of the time.

@strengejacke
Copy link
Owner

strengejacke commented Oct 16, 2023

I'm not sure about the plogis() transformation for the coefficient table. For ggpredict() (i.e. predictions), the link-inverse is used since we predict the response and want the predictions to be on the response-scale (probabilities).

But for coefficients, like in logistic regression, where we also have a logit-link, the coefficients are also reported as exp(coefficient), which is an odds ratio. I have never seen that coefficients (not: predictions!) are back-converted using plogis() in such cases - but just because I haven't seen it doesn't mean that it's not common practice for GAMs.

I also tried packages emmeans and marginaleffects, but no success. Pinging @vincentarelbundock for marginaleffects.

@vincentarelbundock
Copy link
Contributor

Personally, I would just use marginaleffects::avg_comparisons(model) to get interpretable estimates of the effect size on the response scale, but YMMV.

@DHLocke
Copy link

DHLocke commented Oct 16, 2023

Thanks. marginaleffects looks fantastic!

marginaleffects::avg_comparisons(mod, what = 'mu')
Error in get_coef.gamlss(model) :
Argument what indicating the parameter of interest is missing.

Given the repex, that Error is unexpected and I'm not sure how best to resolve it.
What about a what = 'all' option to combine mu, sigma, nu.. what ever the case might be?

@vincentarelbundock
Copy link
Contributor

Thanks for testing it @DHLocke . You found a bug and I just fixed it in the development version of the package.

You’ll find instructions for installation and an example at this separate issue, which I opened to discuss marginaleffects-specific issues. (We don’t want to clutter Daniel’s issue tracker.)

vincentarelbundock/marginaleffects#933

@DHLocke
Copy link

DHLocke commented Oct 16, 2023

Thanks so much and sorry for submitting the error to the wrong place.
What about a what = 'all' argument that combines the mu and sigma?

@vincentarelbundock
Copy link
Contributor

see the other thread for a response

@strengejacke strengejacke added the nlme 💾 Issue related to certain packages label May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
nlme 💾 Issue related to certain packages reprex 💾 An example (and data) to reproduce the issue is needed to waiting for response 💌 Response from users awaited
Projects
None yet
Development

No branches or pull requests

4 participants