【问题标题】:How to access the source data when manipulating/updating fitted models操作/更新拟合模型时如何访问源数据
【发布时间】:2017-06-26 21:59:49
【问题描述】:

我正在尝试编写一些函数来简化多个模型的改装,但发现它很痛苦,因为当 R 深入评估树时,它无法找到正确的 data。 尽管努力将公式环境存储在模型中,但我想确实没有办法明确地指向原始数据对象。 使用survfit 拟合生存曲线变得更加困难,其中没有存储terms 对象。

我真的需要每次都重新输入数据/公式作为参数吗?

例子:

# model-fitting wrapper function
fn <- function(fn_formula, fn_data) {
    lm(formula = fn_formula, data = fn_data)
}
# specify exemplary data and formula
data <- data.frame(
    y = rnorm(100),
    x1 = rnorm(100),
    x2 = rnorm(100))
formula <- y ~ x1

# try to create and update the fit with different parameters
fn_fit <- fn(formula, data)
update(fn_fit, ~ x2)
# Error in is.data.frame(data) : object 'fn_data' not found
terms(fn_fit) %>% attr('.Environment')
# <environment: R_GlobalEnv>
terms(fn_fit$model) %>% attr('.Environment')
# <environment: R_GlobalEnv>
getCall(fn_fit)
# lm(formula = fn_formula, data = fn_data)

【问题讨论】:

    标签: r functional-programming regression nse


    【解决方案1】:

    对于同名的lm()update(),存储数据的变量应该在相同的范围内。不确定你真正想要完成什么,如果你想要一个创建可以在全局环境中使用的签名的函数,你可以做这样的事情

    fn <- function(fn_formula, fn_data) {
      do.call("lm", list(fn_formula, data=substitute(fn_data)))
    }
    fn_fit <- fn(formula, data)
    update(fn_fit, ~ x2)
    

    否则,如果您真的想在本地函数范围内捕获该变量,您可以创建一个帮助程序来在正确的环境中进行有趣的更新。

    fn <- function(fn_formula, fn_data) {
      environment(fn_formula) <- environment()
      lm(formula = fn_formula, data = fn_data)
    }
    
    fn_update <- function(object, ...) {
      mc<-match.call(definition = update)
      mc[[1]] <- quote(update)
      eval(mc, envir=environment(terms(object)))
    }
    
    fn_fit <- fn(formula, data)
    fn_update(fn_fit, ~x2)
    

    【讨论】:

    • 我知道可以通过非标准评估和操作调用来捕获相关变量,但我发现它不直观,因为它需要多个包装器,假设模型尚未拟合使用标准调用并高度依赖于实际调用堆栈。我真正不明白的是在terms 中维护y ~ x1 调用的整个调用环境的意义,它不保证存储原始数据,但可能包括在包装器的同一次调用期间创建的其他内存消耗变量功能——有什么简单的解释吗?
    【解决方案2】:

    当您传递公式时,存储在 ['model'] 子列表中的唯一项目是那些需要的项目。

    > names(fn_fit$model)
    [1] "y"  "x1"
    

    但该对象中没有任何名称为“数据”或“fn_data”。 MrFlick 的第二个建议对帧调用树中的修改更具弹性:

    > fn <- function(fn_formula, fn_data) {
    +   do.call("lm", list(fn_formula, data=substitute(fn_data)))
    + }
    > fn_fit <- fn(formula, data); rm(data)  # mess with the calling environment
    > update(fn_fit, ~ x2)
    Error in terms.formula(formula, data = data) : 
      'data' argument is of the wrong type
    

    出现这个错误是因为 R 解释器只找到了名为 data 的函数;相反,如果您部署您得到的第二个选项:

    > data <- data.frame(
    +     y = rnorm(100),
    +     x1 = rnorm(100),
    +     x2 = rnorm(100))
    
    > fn <- function(fn_formula, fn_data) {
    +   environment(fn_formula) <- environment()
    +   lm(formula = fn_formula, data = fn_data)
    + }
    > 
    > fn_update <- function(object, ...) {
    +   mc<-match.call(definition = update)
    +   mc[[1]] <- quote(update)
    +   eval(mc, envir=environment(terms(object)))
    + }
    
    > 
    > fn_fit <- fn(formula, data) ; rm(data)
    > fn_update(fn_fit, ~x2)
    
    Call:
    lm(formula = y ~ x2, data = fn_data)
    
    Coefficients:
    (Intercept)           x2  
        0.01117     -0.13004  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2013-01-25
      • 1970-01-01
      相关资源
      最近更新 更多