【问题标题】:Use a weights argument in a list of lm lapply calls [duplicate]在 lm lapply 调用列表中使用权重参数 [重复]
【发布时间】:2016-02-02 11:15:04
【问题描述】:

这是我的问题(虚构数据以便重现):

set.seed(42)
df<-data.frame("x"=rnorm(1000),"y"=rnorm(1000),"z"=rnorm(1000))
df2<-data.frame("x"=rnorm(100),"y"=rnorm(100),"z"=rnorm(100))
breaks<-c(-1000,-0.68,-0.01315,0.664,1000)
divider<-cut(df$x,breaks)
divider2<-cut(df2$x,breaks)
subDF<-by(df,INDICES=divider,data.frame)
subDF2<-by(df2,INDICES=divider2,data.frame)
reg<-lapply(subDF,lm,formula=x~.)
pre<-lapply(1:4,function(x){predict(reg[[x]],subDF2[[x]])})
lapply(1:4,function(x){summary(reg[[x]])$r.squared})

上面的代码工作正常。我正在做的事情如下:根据x的值,我将df分成4个数据帧并对每个数据帧运行回归,以便能够预测其他数据集的值。数据框的拆分是为了更好地预测,因为x的范围对实际数据有很大的影响。

我想要做的是为回归添加一个权重参数,以更加重视最新数据。我的权重参数是:weights&lt;-0.999^seq(250,1,by=-1)如果有 250 个数据。种子为 42 和之前的中断,所有 4 个维度都是 250。

当我尝试做reg&lt;-lapply(subDF,lm,formula=x~.,weights=0.999^seq(250,1,by=-1)) 时,我得到了这个错误:

Error in eval(expr, envir, enclos) : 
  ..2 used in an incorrect context, no ... to look in

这很奇怪,因为lapply有一个...argument,这里用于formula,但它不接受weights

所以我真的不知道如何添加这些权重。我应该在我的代码中更正什么,或者我应该(几乎)完全改变它以能够使用权重?

对于这个例子,为了使它(也许)更容易,我切断了中断,以便 4 个子集具有相同的维度,但理想情况下,即使 4 个子集的维度不同(因此与例如,breaks&lt;-c(-1000,-0.75,0,0.75,1000) 的中断)

This CrossValidated 上的帖子也有同样的问题,但没有有效的解决方案,所以这对我没有帮助。

【问题讨论】:

    标签: r lapply lm


    【解决方案1】:

    不幸的是,您亲身经历了 R 中可以说是最严重的错误。所谓的非标准评估 (NSE) 错误。

    在对代码进行了一些挖掘之后,我想我找到了罪魁祸首。让我们一件一件来:

    首先让我们看看traceback()

    weights <- 0.999^seq(250,1,by=-1)
    
    lapply(subDF, lm, formula=x~., weights=weights)
    Error in eval(expr, envir, enclos) : 
      ..2 used in an incorrect context, no ... to look in
    > traceback()
    8: eval(expr, envir, enclos)
    7: eval(extras, data, env)
    6: model.frame.default(formula = ..1, data = X[[1L]], weights = ..2, 
           drop.unused.levels = TRUE)
    5: stats::model.frame(formula = ..1, data = X[[1L]], weights = ..2, 
           drop.unused.levels = TRUE)
    4: eval(expr, envir, enclos)
    3: eval(mf, parent.frame())
    2: FUN(X[[1L]], ...)
    1: lapply(subDF, lm, formula = x ~ ., weights = weights)
    

    看起来问题出现在model.frame.default 内部。那么,让我们看一下源代码。我不会发布整个源代码,但是如果你在控制台中输入model.frame.default,你会看到中间的某处:

    extras <- substitute(list(...))
    extranames <- names(extras[-1L])
    extras <- eval(extras, data, env)
    

    最后一行是失败的地方。第一行是所谓的 NSE,由substitute 创建。 substitute 将创建一个所谓的 expression,也就是说,让我们说一个稍后在 eval 内部评估(即创建)的对象。正如您在eval 中看到的那样,extras 将在data 中进行评估,然后如果在env 中找不到。对于公式是可以的,因为它是在数据中评估的,x~. 将告诉eval 使用data 中的所有列。 weights 虽然不在data 中。因此,eval 将在env 中查找它。但是env 是什么?

    显然,env 是一个环境,是在model.frame.default 中创建的:

    env <- environment(formula$terms)
    

    那么,这是什么意思?再看一个例子:

    xtest <- function(x) {
      new_func <- function(x) {
        env <- environment(x)
        print(env)
      }
      new_func(x)
    } 
    
    > xtest(x~z)
    <environment: R_GlobalEnv>
    

    在上面的函数中,我尝试用更少的行复制env 将在model.frame.default 中的内容。如您所见,environment(formula) 指向全局环境。

    所以,env 试图找到..2 即在... 中传递的第二个参数(即weights),但由于在全局环境中没有...,所以你得到了一个错误。希望现在清楚了!

    最好的解决方案,我要做的是使用@Heroka 的答案来解决它(或者您可以在不使用 NSE 的情况下从头开始重写整个 model.frame.defaultlm,但我认为第一个更合理:)) .

    【讨论】:

    • 非常感谢!我也尝试做w&lt;-0.99^seq(1000,1,by=-1) df&lt;-cbind(df,w),以便在数据中获得权重,但它仍然失败。鉴于权重现在在数据中,您知道为什么吗?
    • 那么您的lapply 通话怎么样?
    • lapply(subDF,lm,formula=x~y+z,weights=w)
    • 您是如何创建subDF 以包含w 的?
    • 鉴于w现在在dfsubDF只是拆分df它也有w在每个4 subDF[[i]]
    【解决方案2】:

    我不知道你为什么得到你得到的错误(我认为....-argument 是为此而设计的。但是,我找到了一个轻微的解决方法,这是你需要的方向吗?我有什么done 在 lapply 中创建了一个“匿名”函数,它计算权重(取决于数据的维度)并返回一个模型。

    reg2 <- lapply(subDF, function(chunk){
      #calculate weights (!dependent on data ordering)
      weights <- 0.999^seq(nrow(chunk),1,by=-1)
    
      #fit model
      fit <- lm(x~., data=chunk, weights=weights)
      return(fit)
    })
    

    【讨论】:

    • 这真是太棒了!也许有人会知道问题出在哪里,但您的答案正是我想要的
    • 不客气!请注意,您当前的权重基于数据框的顺序。这总是让我有点紧张,做类似 `weights
    猜你喜欢
    • 2018-06-03
    • 2017-01-11
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2021-10-30
    • 2018-12-11
    • 1970-01-01
    相关资源
    最近更新 更多