構造方程式モデル
install.packages(c("lavaan","semTools","semPlot")) #としてインストールしておく
以下、実行例
library(lavaan) library(semTools) library(semPlot) #パス図表 を描く data(HolzingerSwineford1939) #サンプルデータ head(HolzingerSwineford1939) ?HolzingerSwineford1939 plot(HolzingerSwineford1939[,7:15]) cor(HolzingerSwineford1939[,7:15]) factanal(HolzingerSwineford1939[,7:15],factors=3,rotation="promax") #3因子で探索的因子分析
#測定方程式 因子名は適当につけてok。それと観測される変数を関連づける HS.model.cfa <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 ' #確認的因子分析 fit <- lavaan(HS.model.cfa, data=HolzingerSwineford1939, auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE) summary(fit, fit.measures=TRUE,standardized=T,rsquare=T) #結果出力 modindices(fit,sort=T) #修正指数 大きい順に出力
#参考 まちがって次のように指定したらどうなるか x3とx6を入れ替え HS.model.cfa2 <- ' visual =~ x1 + x2 + x6 textual =~ x4 + x5 + x3 speed =~ x7 + x8 + x9 ' #lavaan 関数に 上で定義したモデル名、データ名などを渡して推定 fit2 <- lavaan(HS.model.cfa2, data=HolzingerSwineford1939,auto.var=TRUE,auto.fix.first=TRUE,auto.cov.lv.x=TRUE) summary(fit2, fit.measures=TRUE,standardized=T,rsquare=T) modindices(fit2,sort=T) #修正指数
#上の確認的因子分析についてパスを入れる #測定方程式 因子名は適当につけてok。それと観測される変数を関連づける HS.model.sem <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 #構造方程式 因子間の関係は下記のように指定 speed ~visual + textual ' fit.sem <- lavaan(HS.model.sem, data=HolzingerSwineford1939, auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE) summary(fit.sem, fit.measures=TRUE,standardized=T,rsquare=T) #結果出力 modindices(fit.sem,sort=T) #修正指数
#別のモデル 空間認知→言語認知→処理速度 HS.model.sem2 <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 #構造方程式 因子間の関係は下記のように指定 speed ~ textual textual ~ visual ' fit.sem2 <- lavaan(HS.model.sem2, data=HolzingerSwineford1939, auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE) summary(fit.sem2, fit.measures=TRUE,standardized=T,rsquare=T) #結果出力 modindices(fit.sem2,sort=T) #修正指数
#参考}測定方程式のパスをすべて1に固定 HS.model.sem3 <- ' visual =~ 1*x1 + 1*x2 + 1*x3 textual =~ 1*x4 + 1*x5 + 1*x6 speed =~ 1*x7 + 1*x8 + 1*x9 #構造方程式 因子間の関係は下記のように指定 speed ~ textual textual ~ visual ' fit.sem3 <- lavaan(HS.model.sem3, data=HolzingerSwineford1939, auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE) summary(fit.sem3, fit.measures=TRUE,standardized=T,rsquare=T) #結果出力 modindices(fit.sem3,sort=T) #修正指数
#このデータは複数のschoolで測定されたもの。複数母集団で推定してみる school別に推定 table(HolzingerSwineford1939$school) #探索的因子分析をschool別に factanal(HolzingerSwineford1939[HolzingerSwineford1939$school=="Grant-White",7:15],factors=3,rotation="promax") #探索的因子分析 3因子指定
factanal(HolzingerSwineford1939[HolzingerSwineford1939$school=="Pasteur",7:15],factors=3,rotation="promax") #探索的因子分析 3因子指定
#2母集団でcfa 指定しなければ同時推定するだけでパラメータは自由 fit.g <- lavaan(HS.model.cfa, data=HolzingerSwineford1939,auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE,group="school") summary(fit.g, fit.measures=TRUE)
par(mfrow=c(1,2)) #2グループを並べてプロット
## semPaths(fit.g,whatLabels= "par") #パラメータを
?measurementInvariance #まずは測定の不変性を確認 measurementInvariance(model=HS.model.cfa, data=HolzingerSwineford1939,group="school",strict = TRUE)
***Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#測定方程式の負荷量λを等値制約 fit.g2 <- lavaan(model=HS.model.cfa, data=HolzingerSwineford1939,auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE,group="school",group.equal=c("loadings")) summary(fit.g2, fit.measures=TRUE,standardized=T,rsquare=T) modindices(fit.g2,sort=T) # par(mfrow=c(1,2)) #2グループを並べてプロット
## semPaths(fit.g2,whatLabels= "par") #パラメータを
#λを等値制約したパス図表 で概念間のパスも入れる fit.g.s <- lavaan(model=HS.model.sem, data=HolzingerSwineford1939,auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE,group="school",group.equal=c("loadings")) summary(fit.g.s, fit.measures=TRUE,standardized=T,rsquare=T) #regressionの係数が同じになりそうか確認 modindices(fit.g.s,sort=T) # par(mfrow=c(1,2)) #2グループを並べてプロット
## semPaths(fit.g.s,whatLabels= "par") #エラー、、、、
#λを等値制約したパス図表 で概念間のパスも入れる(等値制約 fit.g.s2 <- lavaan(model=HS.model.sem, data=HolzingerSwineford1939,auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE,group="school",group.equal=c("loadings","regressions")) summary(fit.g.s2, fit.measures=TRUE,standardized=T,rsquare=T) modindices(fit.g.s2,sort=T) # par(mfrow=c(1,2)) #2グループを並べてプロット
## semPaths(fit.g.s2,whatLabels= "par") #エラー、、、、
#二つのグループで一部の係数が異なるとしたいとき HS.model.sem2 <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 #構造方程式 因子間の関係は下記のように指定 #group.equal=c("loadings","regressions"))としたので回帰部分の係数はグループ間で等値とされる。 #ただし、下のように指定すると、visualへの係数はグループで異なると推定される。 speed ~c(b11,b12)*visual + textual ' fit.g.2 <- lavaan(model=HS.model.sem2, data=HolzingerSwineford1939,auto.var=TRUE, auto.fix.first=TRUE,auto.cov.lv.x=TRUE,group="school",group.equal=c("loadings","regressions")) summary(fit.g.2, fit.measures=TRUE,standardized=T,rsquare=T) #regressionの出力部分を比較して、そのようになっていることを確認。AIC,BICなどで、適合度の高いモデルを選択 modindices(fit.g.2,sort=T) # par(mfrow=c(1,2)) #2グループを並べてプロット
## semPaths(fit.g.2,whatLabels= "par") #エラー、、、、関数廃止