【问题标题】:Create lme object within a function在函数中创建 lme 对象
【发布时间】:2015-08-03 13:27:27
【问题描述】:

背景

我正在尝试根据某些参数在函数中拟合混合模型。如果我想使用来自library(contrast)contrast,我必须使用一种解决方法,因为contrast 使用来自lme 对象的call 插槽来确定datafixedrandom 参数传递给函数中的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 评估mm2call 插槽内的fixedslot 等于mF 的部分,这在顶层当然是未知的,因为它仅在我的函数makeMixedModel2 中定义。 makeMixedModel1 中的解决方法通过显式覆盖 call 中的相应插槽来补救。

显然,对于lm 对象,这是以更智能的方式解决的,因为不需要手动覆盖,因为contrast 似乎在正确的上下文中评估所有部分,当然mF 和@987654345 @ 也不知道:

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))

所以,我假设lmformuladata 的值存储在某处,这样在不同的环境中也可以检索到。

我可以接受我的解决方法,尽管它有一些丑陋的副作用,因为 print(mm1) 显示所有数据而不是简单的名称。所以我的问题是,是否还有其他策略可以实现我的意图?还是我必须写信给contrast 的维护者,问他是否可以更改lme 对象的代码,这样他就不再依赖call 插槽,而是尝试以其他方式解决问题(就像为lm 所做的那样?

【问题讨论】:

  • 我认为这可能是 this question 的副本,答案显示如何通过 do.call 执行此操作(尽管可能与您的解决方案具有相同的副作用)。
  • 是的,我已经看到了。问题不是我无法解决,而是如何避免副作用。

标签: r lm nlme


【解决方案1】:

我认为你正在战斗的只是 contrast() 的错误实现 lme 对象。我会联系作者来修复它(这可能是最近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

【讨论】:

  • 谢谢,这确实是诀窍,我也学到了一些新东西 (assignInNamespace)。不仅仅是值得赏金:) 谢谢。
  • 嘿,乐于助人。在您的情况下这不太可能,但是在包命名空间中乱搞可能会导致一些意想不到的后果(例如,如果出于某种原因contrastCalc() 重新调用contrast.lme())。但它偶尔会非常有用,特别是如果您正在测试微小的更改并且不想处理整个包的源代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多