在 lm lapply 调用列表中使用权重参数
Use a weights argument in a list of lm lapply calls
这是我的问题(虚构数据以便于重现):
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<-0.999^seq(250,1,by=-1)
如果有 250 个数据。使用 42 的种子和之前的中断,所有 4 个维度都是 250。
当我尝试执行 reg<-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
有一个 ...
参数,这里用于 formula
但它不接受 weights
.
所以我真的不知道该怎么做才能增加这些权重。我应该在我的代码中更正什么,或者我应该(几乎)完全改变它以便能够使用权重?
对于这个例子,为了让它(可能)更容易,我切断了断点,使 4 个子集具有相同的维度,但理想情况下,即使 4 个子集的维度不同,答案也会有效(例如 breaks<-c(-1000,-0.75,0,0.75,1000)
的中断)
This post 在 CrossValidated 上有完全相同的问题,但没有有效的解决方案,所以这对我没有帮助。
我不知道你为什么会收到这个错误(我认为 ....
-argument 是为此而设计的。但是,我找到了一个小的解决方法,这是在你需要的方向上吗? 我所做的是在 lapply 中创建一个 'anonymous' 函数,它计算权重(取决于数据的维度)和 returns 一个模型。
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)
})
不幸的是,您亲身经历了 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
内部。那么,让我们看一下源代码。我不会 post 整个源代码,但如果您在控制台中键入 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 的答案来解决它(或者你可以从头开始重写整个 model.frame.default
和 lm
,而不使用 NSE,但我认为第一个更合理:))。
这是我的问题(虚构数据以便于重现):
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<-0.999^seq(250,1,by=-1)
如果有 250 个数据。使用 42 的种子和之前的中断,所有 4 个维度都是 250。
当我尝试执行 reg<-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
有一个 ...
参数,这里用于 formula
但它不接受 weights
.
所以我真的不知道该怎么做才能增加这些权重。我应该在我的代码中更正什么,或者我应该(几乎)完全改变它以便能够使用权重?
对于这个例子,为了让它(可能)更容易,我切断了断点,使 4 个子集具有相同的维度,但理想情况下,即使 4 个子集的维度不同,答案也会有效(例如 breaks<-c(-1000,-0.75,0,0.75,1000)
的中断)
This post 在 CrossValidated 上有完全相同的问题,但没有有效的解决方案,所以这对我没有帮助。
我不知道你为什么会收到这个错误(我认为 ....
-argument 是为此而设计的。但是,我找到了一个小的解决方法,这是在你需要的方向上吗? 我所做的是在 lapply 中创建一个 'anonymous' 函数,它计算权重(取决于数据的维度)和 returns 一个模型。
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)
})
不幸的是,您亲身经历了 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
内部。那么,让我们看一下源代码。我不会 post 整个源代码,但如果您在控制台中键入 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 的答案来解决它(或者你可以从头开始重写整个 model.frame.default
和 lm
,而不使用 NSE,但我认为第一个更合理:))。