piecewiseSEM icon indicating copy to clipboard operation
piecewiseSEM copied to clipboard

multigroup fails for lme4

Open jslefche opened this issue 4 years ago • 5 comments

library(piecewiseSEM)
library(lme4)

# Generate data
data <- data.frame(
  x1 = rnorm(100),
  y1 = rnorm(100),
  y2 = rnorm(100),
  groups = LETTERS[1:2],
  random = rep(letters[1:4], each = 25)
)

model <- psem(
  lmer(y1 ~ x1 + (1 | random), data),
  lmer(y2 ~ y1 + (1 | random), data),
  data = data)

multigroup(model, group = "groups")

jslefche avatar Jun 16 '20 13:06 jslefche

Hi Jon,

The problem arises from a section in the multigroup() function where the new models with the interaction with 'group' is created.

Line 39 of multigroup.R:

rhs2 <- paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + ")

creates the new models by pasting the fixed terms and adding an interaction with 'group'. The problem is that in lme4 the random factors should be included as part of the formula too.

I managed to fix the problem by changing that line of code to:

rhs2 <- ifelse(class(i) == "lmerMod", paste(paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + "), "+ (", findbars(formula(i)),")"), paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + "))

This fixed the problem for me.

However, in this case, the data always has to be added as part of the psem() model, otherwise the function cannot find the 'group' variable. I believe this is due to lme4 models not storing the data as part of their output.

elisalonso avatar Jun 16 '20 16:06 elisalonso

I realise now that the solution above only works if the model is of class "lmerMod", which is only applicable to lme4::lmer() models. For the code to also work with other model types from the lme4 package, the code should read:

rhs2 <- ifelse(grepl("merMod", class(i)) == T, paste(paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + "), "+ (", findbars(formula(i)),")"), paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + "))

elisalonso avatar Jun 18 '20 10:06 elisalonso

Hi,

I tried multigroup function with lme4 for "lmerMod" class object after changed the line 39 rhs2 <- paste(paste(all.vars_trans(i)[-1], "", group), collapse = " + ") to rhs2 <- ifelse(class(i) == "lmerMod", paste(paste(paste(all.vars_trans(i)[-1], "", group), collapse = " + "), "+ (", findbars(formula(i)),")"), paste(paste(all.vars_trans(i)[-1], "*", group), collapse = " + "))

according to the previous post.

Then, I got the new error message saying:

Error in removeData(modelList, formulas = 1) : could not find function "removeData"

I ran the following function to make sure "removeData" is in the R.

removeData <- function(modelList, formulas = 0) {

remove <- c("character", "matrix", "data.frame", "SpatialPointsDataFrame", "comparative.data")

if(formulas == 1) remove <- c(remove, "formula", "formula.cerror")

if(formulas == 2) remove <- c(remove, "formula")

if(formulas == 3) remove <- c(remove, "formula.cerror")

modelList[!sapply(modelList, function(x) any(class(x) %in% remove))]

}

After that, when I ran multigroup, I got another error message below.

Error in all.vars_trans(i) : could not find function "all.vars_trans"

Then I ran the following function

all.vars_trans <- function(formula.) {

if(!all(class(formula.) %in% c("formula", "formula.cerror"))) formula. <- formula(formula.)

if(class(formula.) == "formula") {

if(formula.[[3]] == 1) deparse(formula.[[2]]) else {
  
  if(any(grepl("\\|", formula.))) formula. <- lme4::nobars(formula.)
  
  c(rownames(attr(terms(formula.), "factors"))[1], labels(terms(formula.)))
  
}

} else unlist(strsplit(formula., " ~~ "))

}

Then I got the error message below.

Error in [.data.frame(data, , group) : undefined columns selected

Sorry, I am not so good at R yet and have no clue what is the problem.

I am using R version 4.1.2, piesewiseSEM 2.1.2 (I am a bit confused about the piesewiseSEM version because I installed the latest version, 2.1.2, and it says 2.1.2 in the package description in R studio but in the R console, when I load the package, it says 2.1.0. But even if my piesewiseSEM is 2.1.0, it should have removeData function).

Thank you.

misatoda avatar Nov 19 '21 09:11 misatoda

I have also been trying to make the proposed change to the code so that I can run multigroup() with a lme4 model, but have run into the same problems as the previous commenter. Are there any plans to fix this in the package or can you suggest a way for a relative beginner to make the change?

MBGarfinkel avatar Apr 13 '23 16:04 MBGarfinkel

I have been tried to run multigroup() with a lm model, but have run into the same problems as the previous commenter. 1.Error in [.data.frame(data, , group) : undefined columns selected 2.Error in removeData(modelList, formulas = 1) :could not find function "removeData"

JCZ9527 avatar Apr 16 '24 14:04 JCZ9527