判断公式是否包含随机效应的最佳方法?

Best way to tell if a formula contains a random effect?

我有一个公式列表,我想使用函数将其放入循环中。其中一些公式是随机效应模型,而另一些则是简单的线性模型。我希望函数检测模型是否包含随机效应,如果是,则使用 lmer() 来拟合模型。否则,它应该使用 lm()。有关如何检查此条件的任何建议(除了将公式转换为字符串并检查括号外)?在这个阶段,他们有相同的 class 所以我不能只检查一下。我还可以使用错误处理来捕获 lmer() returns 模型中没有随机效应的错误并重新路由到常规 lm(),但这似乎也不必要地混乱。

示例如下:

fit_models <- function(formula_list) {
  models <- list()
    for(ii in seq_along(formula_list)) {
      if(formula_list[[ii]] is lmer) { # Enter condition here
        print("lmer")
      } else {
        print("lm")
      }
  }
}

f1 <- formula(y ~ x)
f2 <- formula(y ~ 1 + x + (1 + x | z))
formulas <- c(f1, f2)

fit_models(formulas)

您可以将公式转换为字符并查找竖线运算符 |:

f1 <- formula(y ~ x)
f2 <- formula(y ~ 1 + x + (1 + x | z))
formulas <- c(f1, f2)

sapply(formulas, function(x) any(grepl("\|", as.character(x))))
#> [1] FALSE  TRUE

公式中的符号没有内在含义。函数可以将符号重新解释为他们喜欢的任何意思。所以仅仅因为有一个“|”,并不一定意味着这是一个具有随机效果的公式。这就是 lmer 选择解释该符号的方式。

鉴于公式基本上只是未计算符号的有序集合,除了对仅在公式本身上运行的符号进行基本相等性检查外,您无能为力。您可以使用 all.names 而不是直接向上字符转换。所以像

f2 <- formula(y ~ 1 + x + (1 + x | z))
all.names(f2)
#  [1] "~" "y" "+" "+" "x" "(" "|" "+" "x" "z"
"|" %in% all.names(f2)
# [1] TRUE

如果您有类似 formula(`a|b` ~ x) 的内容,其中 a|b 是一个(糟糕的)列名,这不会被愚弄。

我会说

length(lme4::findbars(f))>0

应该可靠地检测包含随机效应成分的公式(在 lme4 意义上)。

From the right hand side of a formula for a mixed-effects model, determine the pairs of expressions that are separated by the vertical bar operator.

这是(隐含地)在 lme4 代码中完成的测试,here ...