我想在线性模型列表上使用AIC进行逐步回归。想法是使用e线性模型列表,然后在每个列表元素上应用stepAIC。它失败了。
大家好,我试着追查问题。 我想我发现了这个问题。但是,我不明白原因。 尝试使用代码来查看三种情况之间的区别。
require(MASS)
n<-30
x1<-rnorm(n, mean=0, sd=1) #create rv x1
x2<-rnorm(n, mean=1, sd=1)
x3<-rnorm(n, mean=2, sd=1)
epsilon<-rnorm(n,mean=0,sd=1) # random error variable
dat<-as.data.frame(cbind(x1,x2,x3,epsilon)) # combine to a data frame
dat$id<-c(rep(1,10),rep(2,10),rep(3,10))
# y is combination from all three x and a random uniform variable
dat$y<-x1+x2+x3+epsilon
# apply lm() only resulting in a list of models
dat.lin.model.lst<-lapply(split(dat,dat$id),function(d) lm(y~x1+x2+x3,data=d))
stepAIC(dat.lin.model.lst[[1]]) # FAIL!!!
# apply function stepAIC(lm())- works
dat.lin.model.stepAIC.lst<-lapply(split(dat,dat$id),function(d) stepAIC(lm(y~x1+x2+x3,data=d)))
# create model for particular group with id==1
k<-which(dat$id==1) # manually select records with id==1
lin.model.id1<-lm(dat$y[k]~dat$x1[k]+dat$x2[k]+dat$x3[k])
stepAIC(lin.model.id1) # check stepAIC - works!
我很确定stepAIC()需要来自data.frame“dat”的原始数据。这就是我之前想到的。 (希望我是对的)
但是stepAIC()中没有参数可以传递原始数据帧。显然,对于未包含在列表中的普通模型,它足以通过模型。 (代码中的最后三行)所以我想知道:
Q1:stepAIC如何知道在哪里可以找到原始数据“dat”(不仅仅是作为参数传递的模型数据)?
Q2:我怎么可能知道stepAIC()中还有另一个参数没有在帮助页面中明确说明? (也许我的英语太难找了)
问题3:如何将该参数传递给stepAIC()?
它必须位于apply函数的环境中并传递数据。 lm()或stepAIC()和指向原始数据的链接必须在某处丢失。我不太清楚R中的环境是什么。对我来说,它有点将局部与全局变量隔离开来。但也许它更复杂。有谁可以向我解释上述问题?老实说,我从R documentation那里读得不多。任何更好的理解都会帮助我。谢谢。
OLD: 我有一个数据帧df中的数据,可以分成几个子组。为此,我创建了一个名为df $ id的groupID。 lm()返回第一个子组的预期系数。我想分别使用AIC作为每个子组的标准进行逐步回归。我使用lmList {lme4}导致每个子组(id)的模型。但是,如果我对list元素使用stepAIC {MASS},则会抛出错误。见下文。
所以问题是:我的程序/语法有什么错误?我获得了单个模型的结果,但没有使用lmList创建的结果。 lmList()是否在模型上存储的信息与lm()不同? 但在帮助中它说: class“lmList”:具有通用模型的类lm的对象列表。
>lme4.list.lm<-lmList(formula=Scherkraft.N~Gap.um+Standoff.um+Voidflaeche.px |df$id,data = df)
>lme4.list.lm[[1]]
Call: lm(formula = formula, data = data)
Coefficients:
(Intercept) Gap.um Standoff.um Voidflaeche.px
62.306133 -0.009878 0.026317 -0.015048
>stepAIC(lme4.list.lm[[1]], direction="backward")
#stepAIC on first element on the list of linear models
Start: AIC=295.12
Scherkraft.N ~ Gap.um + Standoff.um + Voidflaeche.px
Df Sum of Sq RSS AIC
- Standoff.um 1 2.81 7187.3 293.14
- Gap.um 1 29.55 7214.0 293.37
<none> 7184.4 295.12
- Voidflaeche.px 1 604.38 7788.8 297.97
Error in terms.formula(formula, data = data) :
'data' argument is of the wrong type
显然某些内容不适用于列表。但我不知道它可能是什么。 因为我试图对创建相同模型的基础包执行相同的操作(至少相同的系数)。结果如下:
>lin.model<-lm(Scherkraft.N ~ Gap.um + Standoff.um + Voidflaeche.px,df[which(df$id==1),])
# id is in order, so should be the same subgroup as for the first list element in lmList
Coefficients:
(Intercept) Gap.um Standoff.um Voidflaeche.px
62.306133 -0.009878 0.026317 -0.015048
嗯,这是我在linear.model上使用stepAIC返回的内容。 据我所知,akaike信息准则可以用来估计哪些模型在给定一些数据的情况下更好地平衡拟合和泛化。
>stepAIC(lin.model,direction="backward")
Start: AIC=295.12
Scherkraft.N ~ Gap.um + Standoff.um + Voidflaeche.px
Df Sum of Sq RSS AIC
- Standoff.um 1 2.81 7187.3 293.14
- Gap.um 1 29.55 7214.0 293.37
<none> 7184.4 295.12
- Voidflaeche.px 1 604.38 7788.8 297.97
Step: AIC=293.14
Scherkraft.N ~ Gap.um + Voidflaeche.px
Df Sum of Sq RSS AIC
- Gap.um 1 28.51 7215.8 291.38
<none> 7187.3 293.14
- Voidflaeche.px 1 717.63 7904.9 296.85
Step: AIC=291.38
Scherkraft.N ~ Voidflaeche.px
Df Sum of Sq RSS AIC
<none> 7215.8 291.38
- Voidflaeche.px 1 795.46 8011.2 295.65
Call: lm(formula = Scherkraft.N ~ Voidflaeche.px, data = df[which(df$id == 1), ])
Coefficients:
(Intercept) Voidflaeche.px
71.7183 -0.0151
我从输出中读到我应该使用的模型: Scherkraft.N~Voidflaeche.px 因为这是最小的AIC。好吧,如果有人能够很快描述输出,那就太好了。我对逐步回归(假设向后消除)的理解是所有回归量都包含在初始模型中。然后消除最不重要的一个。决定的标准是AIC。等等...不知怎的,我有问题让表格解释正确。如果有人能证实我的解释,那就太好了。 “ - ”(减号)代表消除的回归量。最重要的是“开始”模型,在下表中,RSS和AIC计算可能的抵消。所以第一个表中的第一行表示模型 Scherkraft.N~Gap.um + Standoff.um + Voidflaeche.px - Standoff.um 会导致AIC 293.14 。选择没有Standoff.um的那个: Scherkraft.N~Gap.um + Voidflaeche.px
修改
我用dlply()替换了lmList {lme4}以创建模型列表。
仍然stepAIC没有处理该列表。它会抛出另一个错误。实际上,我认为这是数据stepAIC需要运行的问题。我想知道它是如何根据模型数据计算每个步骤的AIC值。 我会采用原始数据来构建模型,每次都会留下一个回归量。我会计算AIC并进行比较。那么如果stepAIC无法访问原始数据,它是如何工作的。 (我无法看到将原始数据传递给stepAIC的参数)。尽管如此,我还是不知道为什么它适用于普通模型,而不是包含在列表中的模型。
>model.list.all <- dlply(df, .id, function(x)
{return(lm(Scherkraft.N~Gap.um+Standoff.um+Voidflaeche.px,data=x)) })
>stepAIC(model.list.all[[1]])
Start: AIC=295.12
Scherkraft.N ~ Gap.um + Standoff.um + Voidflaeche.px
Df Sum of Sq RSS AIC
- Standoff.um 1 2.81 7187.3 293.14
- Gap.um 1 29.55 7214.0 293.37
<none> 7184.4 295.12
- Voidflaeche.px 1 604.38 7788.8 297.97
Error in is.data.frame(data) : object 'x' not found
答案 0 :(得分:4)
我不确定版本控制中可能发生了什么变化以使调试变得如此困难,但是一种解决方案是使用do.call
,它在执行之前评估调用中的表达式。这意味着,不是仅在调用中存储d
,而是update
和stepAIC
需要查找d
才能完成工作,它会存储完整的表示数据框本身。
即,
do.call("lm", list(y~x1+x2+x3, data=d))
而不是
lm(y~x1+x2+x3, data=d)
您可以通过查看模型的call
元素来查看它正在尝试做什么,也许是这样:
dat.lin.model.lst <- lapply(split(dat, dat$id), function(d)
do.call("lm", list(y~x1+x2+x3, data=d)) )
dat.lin.model.lst[[1]]$call
还可以在全局环境中创建数据框列表,然后构建调用,以便update
和stepAIC
依次查找每个数据框,因为它们的环境链总是会引导回来走向全球环境;像这样:
dats <- split(dat, dat$id)
dat.lin.model.list <- lapply(seq_along(dats), function(d)
do.call("lm", list(y~x1+x2+x3, data=call("[[", quote(dats),i))) )
要查看更改内容,请再次运行dat.lin.model.lst[[1]]$call
。
答案 1 :(得分:3)
由于似乎stepAIC离开循环环境(即在全局环境中)以寻找它所需的数据,我使用assign函数来欺骗它:
results <- do.call(rbind, lapply(response, function (i) {
assign("i", response, envir = .GlobalEnv)
mdl <- gls(as.formula(paste0(i,"~",paste(expvar, collapse = "+")), data= parevt, correlation = corARMA(p=1,q=1,form= ~as.integer(Year)), weights= varIdent(~1/Linf_var), method="ML")
mdl <- stepAIC(mdl, direction ="backward")
}))