lme 模型拟合的用户定义函数:错误

User-Defined Function for lme model fits: error

我开始编写一个函数,用 nlme 构建线性混合模型。我遇到错误:Error in eval(expr, envir, enclos) : object 'value' not found,我认为这是由于 R 不知道在哪里可以找到数据框变量(例如,value)。如果这实际上是错误发生的原因,我如何告诉函数 valuetimepoint 属于下面(可重现)代码中 Dat 中的变量?

require(nlme)
Dat <- data.frame(
    id = sample(10:19),
    Time = sample(c("one", "two"), 10, replace = T),
    Value = sample(1:10)
)
nlme_rct_lmm <- function (data, value, timepoint,
                      ID) {

    #base_level intercept only model
    bl_int_only <- gls(value ~ 1, 
                       data = data, 
                       method = "ML", 
                       na.action="na.omit")        
    #vary intercept across participants
    randomIntercept <- lme(value ~ 1, 
                           data = data, 
                           random = ~1|ID, 
                           method = "ML", 
                           na.action = "na.omit")       
    #add timepoint as a fixed effect
    timeFE <- lme(value ~ timepoint, 
                  data = data, 
                  random = ~1|ID, 
                  method = "ML", 
                  na.action = "na.omit")
}
nlme_rct_lmm(Dat, Value, Time, id)

这不是(如你我所料)不同框架内的评估问题;相反,这是公式和数据之间变量名称之间的一致性问题。 R 是区分大小写的,所以使用 valueValueidID 等很重要。此外,公式解释使用非标准评估(NSE ),所以如果你有一个等于符号 Value 的变量 valuevalue ~ 1 确实 而不是 神奇地变成了 Value ~ 1。我在下面概述的内容通过将响应、时间和 ID 变量的 names 传递给函数来工作,因为这是最简单的方法。如果您使用非标准评估,它对最终用户来说会更优雅一点,但编程会有点困难(因此理解、调试等)。

在easy/boneheaded方法下面,我还讨论了如何实现NSE方法(一直向下滚动...)

请注意,您的示例没有 return 任何内容;对于 R,这意味着当它完成函数时,所有结果都将被丢弃。您可能希望 return 将结果作为列表(或者您的真实函数可能会对拟合模型做一些其他事情,例如一系列模型测试,并且 return 这些答案作为结果。 ..)

require(nlme)

Dat <- data.frame(
    ID = sample(10:19),
    Time = sample(c("one", "two"), 10, replace = T),
    Value = sample(1:10)
)

nlme_rct_lmm <- function (data, value, timepoint,
                      ID) {

    nullmodel <- reformulate("1",response=value)
    fullmodel <- reformulate(c("1",timepoint),response=value)
    remodel <- reformulate(paste("1",ID,sep="|"))

    #base_level intercept only model
    bl_int_only <- gls(nullmodel,
                       data = data, 
                       method = "ML", 
                       na.action="na.omit")

    #vary intercept across participants
    randomIntercept <- lme(nullmodel,
                           data = data, 
                           random = remodel,
                           method = "ML", 
                           na.action = "na.omit")

    #add timepoint as a fixed effect
    timeFE <- lme(fullmodel,
                  data = data, 
                  random = remodel,
                  method = "ML", 
                  na.action = "na.omit")
}

nlme_rct_lmm(Dat, "Value", "Time", "ID")

如果你想要更优雅的东西(但内部晦涩难懂),你可以用下面几行来定义模型。内部 substitute() 调用检索作为参数传递给函数的 符号 ;外部 substitute() 调用将这些符号插入到公式中。

nullmodel <- formula(substitute(v~1,list(v=substitute(value))))
fullmodel <- formula(substitute(v~t,list(v=substitute(value),
                                 t=substitute(timepoint))))
remodel <- formula(substitute(~1|i,list(i=substitute(ID))))

现在这可以工作了,无需像您预期的那样将变量指定为字符串:nlme_rct_lmm(Dat, Value, Time, ID)