我经常通过粘贴我需要的部分来指定公式参数来模拟拟合函数,如lm
或lme
,如@ DWin对此问题的回答:Understanding lm and environment。
在实践中,这看起来像这样:
library(nlme)
set.seed(5)
ns <- 5; ni <- 5; N <- ns*ni
d <- data.frame(y=rnorm(N),
x1=rnorm(N),
x2=factor(rep(1:ni, each=ns)),
id=factor(rep(1:ns, ni)))
getm <- function(xs) {
f <- paste("y ~", paste(xs, collapse="+"))
lme(as.formula(f), random=~1|id, data=d, method="ML")
}
m1 <- getm("x1")
m2 <- getm(c("x1", "x2"))
但是,使用lme
包中的nlme
,比较使用anova
的方式构建的两个模型不起作用,因为anova.lme
查看已保存的公式参数确保模型适合相同的响应,并且保存的公式参数只是as.formula(f)
。错误是:
> anova(m1, m2)
Error in inherits(object, "formula") : object 'f' not found
以下是anova
命令应该做的事情(重新安装模型以使其有效):
> m1 <- lme(y~x1, random=~1|id, data=d, method="ML")
> m2 <- lme(y~x1+x2, random=~1|id, data=d, method="ML")
> anova(m1, m2)
Model df AIC BIC logLik Test L.Ratio p-value
m1 1 4 76.83117 81.70667 -34.41558
m2 2 8 72.69195 82.44295 -28.34597 1 vs 2 12.13922 0.0163
有什么建议吗?
答案 0 :(得分:13)
Ben的答案有效,但do.call
提供了他希望的更一般的解决方案。
getm <- function(xs) {
f <- as.formula(paste("y ~", paste(xs, collapse="+")))
do.call("lme", args = list(f, random=~1|id, data=d, method="ML"))
}
它起作用是因为(默认情况下)args =
中的参数在传递给lme之前被计算。
答案 1 :(得分:3)
这是一个似乎有效的黑客攻击:
getm <- function(xs) {
f <- paste("y ~", paste(xs, collapse="+"))
m <- lme(as.formula(f), random=~1|id, data=d, method="ML")
m$call$fixed <- eval(m$call$fixed)
m
}
但我完全不喜欢它。我非常希望看到这个问题的更原则性的答案,因为我在尝试扩展bbmle
包时遇到了这类问题。