在瑞士数据中,我尝试对不同范围的农业进行逐步线性回归,所以我尝试了:
data <- swiss
splits <- split(data, cut(data$Agriculture, breaks=c(0, 50, Inf), right=FALSE))
select <- function(x) {
null <- lm(Fertility~1, data=splits[[x]])
full <- lm(Fertility~., data=splits[[x]])
step(null, scope=list(lower=null, upper=full, direction='forward'))
}
select(2)
这会起作用,但以下情况并非如此:
null_list <- lapply(splits, function(x) {lm(Fertility~1, data=x)})
full_list <- lapply(splits, function(x) {lm(Fertility~., data=x)})
select <- function(x) {
null <- null_list[[x]]
full <- full_list[[x]]
step(null, scope=list(lower=null, upper=full, direction='forward'))
}
select(2)
第二个版本抛出错误:
Error in eval(expr, envir, enclos) : object 'Fertility' not found
但是当我检查时
lm(Fertility~1, data=splits[[2]])
null_list[[2]]
和
lm(Fertility~., data=splits[[2]])
full_list[[2]]
它们看起来都一样。有什么区别?有什么愚蠢的错误吗?
答案 0 :(得分:2)
好吧,如果你看两个版本的调用,你会发现它们不完全相同
lm(Fertility~1, data=splits[[2]])$call
# lm(formula = Fertility ~ 1, data = splits[[2]])
null_list[[2]]$call
# lm(formula = Fertility ~ 1, data = x)
注意每个data=
参数的不同之处。前者仍指向有效的全局变量,后者指向x
,后者不再存在。 step()
函数尝试在调用它的上下文中计算公式。在那种情况下x
是你的循环计数器。如果您将select()
功能更改为
select <- function(z) {
null <- null_list[[z]]
full <- full_list[[z]]
step(null, scope=list(lower=null, upper=full, direction='forward'))
}
select(2)
你会得到一个不同的错误
Error in is.data.frame(data) : object 'x' not found
这基本上意味着step()
无法回到包含可用于重新拟合添加或减去协变量的模型的数据的变量。
一种解决方法是将数据嵌入lm()
调用本身。你可以用
null_list <- lapply(splits, function(x) {do.call("lm", list(Fertility~1, data=x))})
full_list <- lapply(splits, function(x) {do.call("lm", list(Fertility~., data=x))})
但是你会看到这会产生一个“看起来很混乱”的电话,但结果应该是一样的。
遗憾的是,这是非标准评估的副作用。如果step()
在完整模型的$model
属性中查找数据会很好,但我相信当你有NA值时这不匹配所以R别无选择,只能尝试在某些情况下重新评估data=
参数。