モデルリストでstepAICを使用する

私は線形モデルのリスト上でAICを使って段階的回帰をしたい。線形モデルのリストを使用して、各リスト要素に対してstepAICを適用することです。それは失敗する。

こんにちは、私は問題を追跡しようとした。 私は問題を見つけたと思う。しかし、私は原因を理解していません。 3つのケースの違いを確認するコードを試してください。

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()には元のデータフレームを渡すことができるパラメータはありません。明らかに、リストにラップされていない普通のモデルでは、モデルを渡すだけで十分です。 (コードの最後の3行)だから私は不思議です:
Q1:stepAICは元のデータ "dat"(パラメータとして渡されたモデルデータだけでなく)をどこに見つけるかを知っていますか?
Q2:stepAIC()のヘルプページに明示的に記載されていない別のパラメータがあることをどうやって知ることができますか? (多分私の英語は見つけられないかもしれません)
Q3:どのようにstepAIC()にそのパラメータを渡すことができますか?

これは、apply関数の環境のどこかにあり、データを渡す必要があります。 lm()またはstepAIC()と生のデータへのポインタ/リンクはどこかで失われます。私は、Rの環境が何をしているかをよく理解していません。私にとっては、グローバル変数からローカルを隔離することができました。しかし、もっと複雑なことかもしれません。上記の問題に関して私にそれを説明できる人は誰ですか?正直なところ、 Rドキュメントをご覧ください。より良い理解が私を助けるだろう。ありがとうございました。

OLD: I have data in a dataframe df that can be split into several subgroups. For that purpose I created a groupID called df$id. lm() returns the coefficent as expected for the first subgroup. I want to do a stepwise regression using AIC as criterion for each subgroup separately. I use lmList {lme4} which results in a model for each subgroup (id). But if I use stepAIC{MASS} for the list elements it throws an error. see below.

だから問題は:私の手続き/構文に間違いはありますか?私は単一のモデルの結果を得るが、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
                        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
                        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
                         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
                        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  

I read from the output I should use the model: Scherkraft.N ~ Voidflaeche.px because this is the minimal AIC. Well, it would be nice if someone could shortly describe the output. My understanding of the stepwise regression (assuming backwards elimination) is all regressors are included in the initial model. Then the least important one is eliminated. The criterion to decide is the AIC. and so forth... Somehow I have problems to get the tables interpreted right. It would be nice if someone could confirm my interpretation. The "-"(minus) stands for the eliminated regressor. On top is the "start" model and in the table table below the RSS and AIC are calculated for possible eliminations. So the first row in the first table says a model Scherkraft.N~Gap.um+Standoff.um+Voidflaeche.px - Standoff.um would result in an AIC 293.14. Choose the one without Standoff.um: Scherkraft.N~Gap.um+Voidflaeche.px

EDIT:
I replaced the lmList{lme4} with dlply() to create the list of models. Still stepAIC is not coping with the list. It throws another error. Actually, I believe it is a problem with the data stepAIC needs to run through. I was wondering how it calculates the AIC-value for each step just from the model data. I would take the original data to construct the models leaving one regressor out each time. Thereof I would calculate the AIC and compare. So how stepAIC is working if it has not access to the original data. (I cant see a parameter where I pass the original data to stepAIC). Still, I have no clue why it works with a plain model but not with the model wrapped in a list.

>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
                        7184.4 295.12
- Voidflaeche.px  1    604.38 7788.8 297.97
Error in is.data.frame(data) : object 'x' not found
3
私は(現在の)最初のセクションでエラーを再現することができません。どのようなアウトプットを手に入れますか?そして、どのバージョンのRを実行していますか?
追加された 著者 Aaron,
おそらく理由はありませんが、 df も関数なので、データフレームに別の名前を付ける方が良いでしょう。
追加された 著者 James,
AICは、偏差の説明とモデルのオーバーフィットのトレードオフです。パラメータを追加したり、偏差を増やしたりすると、ペナルティが発生します
追加された 著者 James,
そのウィラの前に。 > stepAIC(dat.lin.model.lst [1]]の後でエラーが発生することがあります。AICプロシージャから始まりますが、次のように文句を言います:inherits(x、 "data.frame")のエラー:object 'd'見つかりません。私は2.13のためにそれを使用しました。しかし、2.14.2では問題はありません
追加された 著者 Sebastian,
Aehm待つ。私はそれが私が提供するデータに依存すると思う。コードを再実行してもエラーは消えてしまいました。だから、それはランダムに生成された数に依存していると思います。見つからないオブジェクトに苦情を言ってもまだ変なエラーメッセージです。
追加された 著者 Sebastian,
そして、同じデータを処理する際にエラーが発生しても、問題なく適用機能を実行するので、私はさらに混乱しています。どのように?
追加された 著者 Sebastian,

2 答え

デバッグを非常に困難にするためにバージョン管理で何が変わったのかよく分かりませんが、実行する前に呼び出しの式を評価する do.call を使用するのが1つの解決策です。これは、 update stepAIC d に移動する必要があるように、単に d 作業を行うために、データフレーム自体の完全な表現を保存します。

つまり、do

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 をもう一度実行してください。

4
追加された
この関連の質問もご覧ください。
追加された 著者 Aaron,
私はそれをすべて追いかけることはできませんでしたが、それはあなたが重要な問題を検討しているように妥当と思えます。間違いなく本当に面倒です。 update stepAIC のようなものは、関数に含めるのが非常に難しいです。
追加された 著者 Aaron,
私が持っていた問題は、提供されたデータに依存するのではなく、Rバージョンに依存していなかったと思います。 set.seed(seed)を試してみてください。 x1 <-rnorm(n、平均= 0、sd = 1)。 set.seed(seed + 1); x2 <-rnorm(n、平均= 1、sd = 1)。 set.seed(seed + 2); x3 <-rnorm(n、平均= 2、sd = 1)。 set.seed(seed + 3);種子<-100および種子<-99のイプシロン<-rnorm(n、平均= 0、sd = 1)。しかし、提供されたデータにかかわらず、do.callは動作するようです。それで私は何かが正しくないと思うようになります。
追加された 著者 Sebastian,
そうですね、データでアイデアを得ました。私は完全なモデルから始め、段階的に減らします。最初の削減選択肢のどれもがより良いAICをもたらさない場合、手順は停止し、結果として完全なモデルが得られます。私が縮小して私のモデルを改善することができる場合は、stepAIC手続きは検索スペースに見つからない初期データ= dを使用する必要があります。したがって、データに依存する削減ステップがある場合にのみ、エラーがスローされます。サンプルデータはスムーズに実行されるかもしれないが、実際のデータではプロシージャを終了できるので、これは本当に面倒です。もう一度do.call()を使うと、
追加された 著者 Sebastian,

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")
}))
3
追加された
ありがとう、これが私の誤りの理由でした。グローバルスコープで利用できるように、代わりに<<には見つからない変数の割り当てを変更しました。
追加された 著者 xiankai,