トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

SEM

構造方程式モデル

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)

      • Measurement invariance models
      • Model 1 : fit.configural  パラメーターの制約無し
      • Model 2 : fit.loadings   測定方程式のパス係数λ等値 (弱い測定の不変性)
      • Model 3 : fit.intercepts  さらに測定方程式(観測変数)の切片(平均値)等値 (強い測定の不変性)
      • Model 4 : fit.residuals  さらに残差を等値
      • Model 5 : fit.means    さらに潜在変数の切片(平均値)等値

 

      •      Chi Square Difference Test
      •       Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
      • fit.configural 48 7484.4 7706.8 115.85
      • fit.loadings 54 7480.6 7680.8 124.04 8.192 6 0.22436 制約してもモデルの適合度は有意には低下しない
      • fit.intercepts 60 7508.6 7686.6 164.10 40.059 6 4.435e-07 *** 有意に低下→このように制約しないほうがよい
      • fit.residuals 69 7508.1 7652.6 181.51 17.409 9 0.04269 *
      • fit.means 72 7541.9 7675.3 221.34 39.824 3 1.161e-08 ***  すべての等値制約が成立していれば、分けて推定する必要は無い
      • ---

 ***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") #エラー、、、、関数廃止

    • 推定結果がEQS Mplusなどと一致するかは確認していないが、同プロジェクトのHPでは、一致することを確認したとある。