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

时间:2016-09-30 17:55:51

标签: r nlme

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

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)

1 个答案:

答案 0 :(得分:3)

这不是(正如你和我都预料的那样)在不同的框架内进行评估的问题;相反,它是公式和数据之间变量名称之间一致性的问题。 R区分大小写,因此无论您使用value还是Valueid还是ID等都很重要。此外,公式解释使用非标准评估(NSE) ),所以如果你的变量value等于符号Value,那么value ~ 1会将神奇地转换为Value ~ 1。我在下面概述的内容是将响应,时间和ID变量的名称传递给函数,因为它是最简单的方法。如果您使用非标准评估,它对最终用户来说会更优雅,但编程有点困难(因此理解,调试等)。

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

请注意,您的示例并未返回任何内容;使用R,表示在完成功能时将丢弃所有结果。您可能希望将结果作为列表返回(或者您的真实函数可能会对拟合模型执行其他操作,例如一系列模型测试,并将这些答案作为结果返回...)

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)