Skip to content

Convert RE variances from cov to cor/sd #536

Open

Description

@strengejacke

you see that correlations are not bounded between [-1, 1]. This is something to be fixed in bayestestR, I think, but do you have any idea how to transform the posterior in order to have a proper "point estimate" here?

I think the values from m1 are covariances and variances, not correlations and standard deviation. So you would have to:

library(rstanarm)
library(lme4)
data(cake)
set.seed(123)

m1 <- stan_lmer(angle ~ temp + (temp | replicate),
                data = cake,
                chains = 1)

bayestestR::describe_posterior(m1, effects = "all")
#> ...
#> 
#> # Random effects SD/Cor: replicate
#> 
#> Parameter          |   Median |         95% CI |     pd |          ROPE | % in ROPE |  Rhat |    ESS
#> ----------------------------------------------------------------------------------------------------
#> (Intercept)        | 2.90e-03 | [ 0.00,  0.70] |   100% | [-0.82, 0.82] |      100% | 0.999 | 612.00
#> temp ~ (Intercept) | 1.86e-04 | [-0.01,  0.01] | 59.20% | [-0.82, 0.82] |      100% | 0.999 | 395.00
#> temp               | 1.12e-03 | [ 0.00,  0.00] |   100% | [-0.82, 0.82] |      100% | 1.000 | 325.00
#> 
#> ...


posteriors <- as.data.frame(m1)

rho <- with(posteriors, {
  `Sigma[replicate:temp,(Intercept)]` / 
    (sqrt(`Sigma[replicate:temp,temp]`) * sqrt(`Sigma[replicate:(Intercept),(Intercept)]`))
})

# Cor
bayestestR::describe_posterior(rho)
#> Summary of Posterior Distribution
#> 
#> Parameter | Median |        95% CI |     pd |          ROPE | % in ROPE
#> -----------------------------------------------------------------------
#> Posterior |   0.19 | [-0.92, 0.95] | 59.20% | [-0.10, 0.10] |     9.05%


# Slopes
a <- with(posteriors, sqrt(`Sigma[replicate:temp,temp]`))

bayestestR::describe_posterior(a)
#> Summary of Posterior Distribution
#> 
#> Parameter | Median |       95% CI |   pd |          ROPE | % in ROPE
#> --------------------------------------------------------------------
#> Posterior |   0.03 | [0.02, 0.05] | 100% | [-0.10, 0.10] |      100%


# Compare to:
lme4::lmer(angle ~ temp + (temp | replicate),
           data = cake) |> 
  lme4::VarCorr()
#>  Groups    Name        Std.Dev. Corr 
#>  replicate (Intercept) 2.604527      
#>            temp        0.027073 0.134
#>  Residual              4.825927

Originally posted by @mattansb in easystats/parameters#720 (comment)

Activity

  1. strengejacke commented on Oct 2, 2024

    @strengejacke
    MemberAuthor

    This only affects stanreg, not brms. And we may have to revise the wording in insight::clean_parameters(), and change "SD/COR" to "var/cov" for stanreg-models.

  2. jmgirard commented on Oct 13, 2026

    @jmgirard
    Contributor

    The relabeling suggested above is done. Since insight 1.0.0, clean_parameters() groups the stanreg Sigma[...] parameters as "Var/Cov: <group>" instead of "SD/Cor: <group>", so describe_posterior(effects = "all") no longer presents covariances as correlations.

    The conversion itself is still not done: for stanreg models, nothing returns SDs and correlations computed per draw, as in the example above. Neither bayestestR, insight, nor parameters does this at the moment. Do we close this issue, or keep it open for that conversion?

  3. strengejacke commented on Oct 15, 2026

    @strengejacke
    MemberAuthor

    Let's keep it open for now. The labelling is correct, so it's no longer a "bug", but we may implement a conversion in the future - SD is probably the more intuitive metric here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Consistency 🍏 🍎Expected output across functions could be more similar

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions