1

I was wondering what is the most efficient way to extract (not print like HERE) only the Std.Dev. column from the vc object below as a vector?

library(lme4)
library(nlme)

data(Orthodont, package = "nlme")
fm1 <- lmer(distance ~ age + (age|Subject), data = Orthodont)

vc <- VarCorr(fm1) ## extract only the `Std.Dev.` column as a vector
rnorouzian
  • 7,397
  • 5
  • 27
  • 72
  • If you check `getAnywhere("as.data.frame.VarCorr.merMod")`, it is doing the extraction of the components to create the data.frame `vcov <- c(diag(v), v[lt.v <- lower.tri(v, diag = FALSE)]);sdcor <- c(attr(v, "stddev"), attr(v, "correlation")[lt.v])` – akrun May 21 '20 at 03:41
  • It is internally doing the same thing `r <- rbind(r, data.frame(grp = "Residual", var1 = NA, var2 = NA, vcov = ss^2, sdcor = ss)` in the code. So, it may be efficient to extract the sd and do the `^` instead of going over the as.data.frame and do all the steps which may not be needed for you – akrun May 21 '20 at 03:46

2 Answers2

1

The structure of 'vc' suggests it is a list with single element 'Subject' and the 'stddev' is an attribute

str(vc)
#List of 1
# $ Subject: num [1:2, 1:2] 6.3334 -0.3929 -0.3929 0.0569
#  ..- attr(*, "dimnames")=List of 2
#  .. ..$ : chr [1:2] "(Intercept)" "age"
#  .. ..$ : chr [1:2] "(Intercept)" "age"
#  ..- attr(*, "stddev")= Named num [1:2] 2.517 0.239  ####

So, extract the attribute directly

attr(vc$Subject, "stddev")

and the residual standard deviation is an outside attribute

attr(vc, "sc")
#[1] 1.297364

If we combine them with c, we get a single vector

c(attr(vc$Subject, "stddev"), attr(vc, "sc"))
#   (Intercept)         age             
#  2.5166317   0.2385853   1.2973640 

Wrap with as.numeric/as.vector to remove the names as it is a named vector

Or use attributes

c(attributes(vc)$sc, attributes(vc$Subject)$stddev)
akrun
  • 874,273
  • 37
  • 540
  • 662
1

If you want the three elements in the column, you can use:

as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))
Crimc
  • 195
  • 17