在函数中创建 lme 对象
Create lme object within a function
背景
我正在尝试根据某些参数在函数中拟合混合模型。如果我想使用 library(contrast)
中的 contrast
,我必须使用变通方法,因为 contrast
使用 lme
对象中的 call
槽来确定 data
、fixed
或 random
参数传递给函数中的 lme
(参见代码)。顺便说一句,lm
对象不是这种情况。
数据
set.seed(1)
dat <- data.frame(x = runif(100), y1 = rnorm(100), y2 = rnorm(100),
grp = factor(sample(2, 100, replace = TRUE)))
代码
library(contrast)
library(nlme)
makeMixedModel1 <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
mod <- lme(mF, random = ~ 1 | grp, data = mdat)
mC <- mod$call
mC$fixed <- mF
mC$data <- mdat
mod$call <- mC
mod
}
makeMixedModel2 <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
lme(mF, random = ~ 1 | grp, data = mdat)
}
mm1 <- makeMixedModel1("y1")
mm2 <- makeMixedModel2("y1")
contrast(mm1, list(x = 1)) ## works as expected
# lme model parameter contrast
#
# Contrast S.E. Lower Upper t df Pr(>|t|)
# 0.1613734 0.2169281 -0.2692255 0.5919722 0.74 96 0.4588
contrast(mm2, list(x = 1)) ## gives an error
# Error in eval(expr, envir, enclos) : object 'mF' not found
问题
我已将错误追踪到 contrast
计算 mm2
的 call
槽中的 fixed
槽等于 mF
的部分这在顶层当然是未知的,因为它只在我的函数 makeMixedModel2
中定义。 makeMixedModel1
中的解决方法通过显式覆盖 call
中的相应插槽来补救。
显然,对于 lm
对象,这是以更聪明的方式解决的,因为不需要手动覆盖,因为 contrast
似乎在正确的上下文中评估所有部分,当然mF
和 mdat
也不为人知:
makeLinearModel <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
lm(mF, data = mdat)
}
contrast(makeLinearModel("y1"), list(x = 1))
因此,我假设 lm
将 formula
和 data
的值存储在某处,以便在不同的环境中也可以检索到。
我可以接受我的解决方法,尽管它有一些丑陋的副作用,因为 print(mm1)
显示所有数据而不是简单的名称。所以我的问题是,是否有其他一些策略可以实现我的意图?或者我是否必须写信给 contrast
的维护者并询问他是否可以更改 lme
对象的代码,这样他就不再依赖 call
插槽,而是尝试以其他方式解决问题(就像 lm
所做的那样)?
我认为您所反对的只是 lme
对象的 contrast()
的错误实现。我会联系作者来修复它(这可能是最近使用 nlme
更改的结果)。但与此同时,您可以通过在 contrast.lme()
函数而不是模型构造函数中实施变通方法来避免副作用:
contrast.lme <- function(fit, ...) {
mC <- fit$call
mC$fixed <- formula(fit)
mC$data <- fit$data
fit$call <- mC
library(nlme)
contrast:::contrastCalc(fit, ...)
}
assignInNamespace("contrast.lme", contrast.lme, "contrast")
mm2 <- makeMixedModel2("y1")
contrast(mm2, list(x = 1))
产量:
lme model parameter contrast
Contrast S.E. Lower Upper t df Pr(>|t|)
0.1613734 0.2169281 -0.2692255 0.5919722 0.74 96 0.4588
并且:
print(mm2)
产量:
Linear mixed-effects model fit by REML
Data: mdat
Log-restricted-likelihood: -136.2472
Fixed: mF
(Intercept) x
-0.1936347 0.3550081
Random effects:
Formula: ~1 | grp
(Intercept) Residual
StdDev: 0.131666 0.9365614
Number of Observations: 100
Number of Groups: 2
背景
我正在尝试根据某些参数在函数中拟合混合模型。如果我想使用 library(contrast)
中的 contrast
,我必须使用变通方法,因为 contrast
使用 lme
对象中的 call
槽来确定 data
、fixed
或 random
参数传递给函数中的 lme
(参见代码)。顺便说一句,lm
对象不是这种情况。
数据
set.seed(1)
dat <- data.frame(x = runif(100), y1 = rnorm(100), y2 = rnorm(100),
grp = factor(sample(2, 100, replace = TRUE)))
代码
library(contrast)
library(nlme)
makeMixedModel1 <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
mod <- lme(mF, random = ~ 1 | grp, data = mdat)
mC <- mod$call
mC$fixed <- mF
mC$data <- mdat
mod$call <- mC
mod
}
makeMixedModel2 <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
lme(mF, random = ~ 1 | grp, data = mdat)
}
mm1 <- makeMixedModel1("y1")
mm2 <- makeMixedModel2("y1")
contrast(mm1, list(x = 1)) ## works as expected
# lme model parameter contrast
#
# Contrast S.E. Lower Upper t df Pr(>|t|)
# 0.1613734 0.2169281 -0.2692255 0.5919722 0.74 96 0.4588
contrast(mm2, list(x = 1)) ## gives an error
# Error in eval(expr, envir, enclos) : object 'mF' not found
问题
我已将错误追踪到 contrast
计算 mm2
的 call
槽中的 fixed
槽等于 mF
的部分这在顶层当然是未知的,因为它只在我的函数 makeMixedModel2
中定义。 makeMixedModel1
中的解决方法通过显式覆盖 call
中的相应插槽来补救。
显然,对于 lm
对象,这是以更聪明的方式解决的,因为不需要手动覆盖,因为 contrast
似乎在正确的上下文中评估所有部分,当然mF
和 mdat
也不为人知:
makeLinearModel <- function(resp, mdat = dat) {
mF <- formula(paste(resp, "x", sep = "~"))
mdat <- mdat[resp > 0, ]
lm(mF, data = mdat)
}
contrast(makeLinearModel("y1"), list(x = 1))
因此,我假设 lm
将 formula
和 data
的值存储在某处,以便在不同的环境中也可以检索到。
我可以接受我的解决方法,尽管它有一些丑陋的副作用,因为 print(mm1)
显示所有数据而不是简单的名称。所以我的问题是,是否有其他一些策略可以实现我的意图?或者我是否必须写信给 contrast
的维护者并询问他是否可以更改 lme
对象的代码,这样他就不再依赖 call
插槽,而是尝试以其他方式解决问题(就像 lm
所做的那样)?
我认为您所反对的只是 lme
对象的 contrast()
的错误实现。我会联系作者来修复它(这可能是最近使用 nlme
更改的结果)。但与此同时,您可以通过在 contrast.lme()
函数而不是模型构造函数中实施变通方法来避免副作用:
contrast.lme <- function(fit, ...) {
mC <- fit$call
mC$fixed <- formula(fit)
mC$data <- fit$data
fit$call <- mC
library(nlme)
contrast:::contrastCalc(fit, ...)
}
assignInNamespace("contrast.lme", contrast.lme, "contrast")
mm2 <- makeMixedModel2("y1")
contrast(mm2, list(x = 1))
产量:
lme model parameter contrast
Contrast S.E. Lower Upper t df Pr(>|t|)
0.1613734 0.2169281 -0.2692255 0.5919722 0.74 96 0.4588
并且:
print(mm2)
产量:
Linear mixed-effects model fit by REML
Data: mdat
Log-restricted-likelihood: -136.2472
Fixed: mF
(Intercept) x
-0.1936347 0.3550081
Random effects:
Formula: ~1 | grp
(Intercept) Residual
StdDev: 0.131666 0.9365614
Number of Observations: 100
Number of Groups: 2