R言語で構造方程式モデリング その1
行動科学などの領域では、重さや長さのように直接観測可能な特性だけでなく、「先高感」「知能」「ブランドイメージ」のように直接測定出来ない特性である構成概念(潜在変数)を扱う必要がある。
構造方程式モデリングは、構成概念や観測変数の性質を調べるために集めた多くの観測変数を同時に分析するための統計的方法。
構造方程式モデリング
- 多変量解析の1手法
- 第2世代の多変量解析
- 伝統的な統計手法を下位モデルとして実行可能
- 因子分析法
- 多変量解析
- パス解析法
- 時系列解析
- etc...
変数の分類
方程式モデルには、様々な種類の変数が登場するため、ここでは、3つの観点から分類しその性質を確認する
- 観測変数と潜在変数
- 観測変数 : 直接観測出来る変数。
- 潜在変数 : モデルに導入した直接観測出来ない変数。構成概念
- 構造変数と誤差変数
- 構造変数 : 考察の対象となっている構成概念を含んでいる変数
- 誤差変数 : 考察の対象となっている構成概念では説明出来ない結果側の変数の変動を生み出す要因としてモデルに導入された変数
- 外生変数と内生変数
- 外生変数 : モデルの中で1度も他の変数の結果にならない変数
- 内生変数 : モデルの中で生成される変数
方程式モデルの可視化
パス図を使って、方程式モデルを可視化する。
- 観測変数は四角で囲む
- 潜在変数(構成概念)は楕円で囲む
- 誤差変数は囲まない
- 影響を与える変数から、与えられる変数に単方向の矢印を書き、矢印に因果の影響力を示す数値を付与
- 共変動を示す2つの外生変数に因果関係を仮定しない時には双方向の矢印を書き、矢印に共分散を示す数値を付与
モデルの記述
構造方程式モデリングでは、手元のデータの性質や分析社の仮説に基づいてオリジナルの分析モデルをあつらえたり、従来型の多変量解析の多くのモデルを下位モデルとして実行することが出来る。
ここでは、3つのモデルをやってみる
MIMICモデル(Multiple Indicator MultIple Cause Model)
下図のように、複数の観測指標によって、構成概念が規定され、その構成概念が観測変数の原因となっているモデル。
実行例
以下、3つのモデルについて、R言語での実行例を書く。
準備
パッケージのインストール及び読み込み
> install.packages("sem") > library(sem)
2次因子分析モデル
- モデルが識別されるように、いくつかの母数を固定する
- f1 : 外生変数なので、, a1, a2, a3のうちどれかを1つを固定。
- f2 : 内生変数なので、b1,b2のどちらか1つを固定。
- f3 : 内生変数なので、b3,b4のどちらか1つを固定。
- f4 : 内生変数なので、b5,b6のどちらか1つを固定。
- データ
- 以下のような6つのテストの相関行列
TEST1 | 1.00 |
TEST2 | 0.703 1.00 |
TEST3 | 0.432 0.469 1.00 |
TEST4 | 0.424 0.461 0.738 1.00 |
TEST5 | 0.330 0.303 0.471 0.427 1.00 |
TEST6 | 0.348 0.388 0.433 0.490 0.717 1.00 |
- 実行
相関行列を入力
> TEST.cor <- read.moments(names = c("TEST1", "TEST2", "TEST3", "TEST4","TEST5", "TEST6")) 1: 1.00 2: 0.703 1.00 4: 0.432 0.469 1.00 7: 0.424 0.461 0.738 1.00 11: 0.330 0.303 0.471 0.427 1.00 16: 0.348 0.388 0.433 0.490 0.717 1.00 22: Read 21 items > TEST.cor TEST1 TEST2 TEST3 TEST4 TEST5 TEST6 TEST1 1.000 0.000 0.000 0.000 0.000 0 TEST2 0.703 1.000 0.000 0.000 0.000 0 TEST3 0.432 0.469 1.000 0.000 0.000 0 TEST4 0.424 0.461 0.738 1.000 0.000 0 TEST5 0.330 0.303 0.471 0.427 1.000 0 TEST6 0.348 0.388 0.433 0.490 0.717 1
モデルを指定
> TEST.model <- specify.model() 知能 -> 動作知能, a1, NA 知能 -> 記憶力, a2, NA 知能 -> 数理知能, a3, NA 動作知能 -> TEST1, NA, 1 動作知能 -> TEST2, b2, NA 記憶力 -> TEST3, NA, 1 記憶力 -> TEST4, b4, NA 数理知能 -> TEST5, NA, 1 数理知能 -> TEST6, b6, NA 知能 <-> 知能, NA, 1 動作知能 <-> 動作知能, d2, NA 記憶力 <-> 記憶力, d3, NA 数理知能 <-> 数理知能, d4, NA TEST1 <-> TEST1, e1, NA TEST2 <-> TEST2, e2, NA TEST3 <-> TEST3, e3, NA TEST4 <-> TEST4, e4, NA TEST5 <-> TEST5, e5, NA TEST6 <-> TEST6, e6, NA Read 19 records
モデル構築
> TEST.sem <- sem(ram = TEST.model, S = TEST.cor, N = 1000) > summary(TEST.sem) Model Chisquare = 55.935 Df = 6 Pr(>Chisq) = 3.0007e-10 Chisquare (null model) = 2918.6 Df = 15 Goodness-of-fit index = 0.98236 Adjusted goodness-of-fit index = 0.93827 RMSEA index = 0.091273 90% CI: (0.0703, 0.11386) Bentler-Bonnett NFI = 0.98083 Tucker-Lewis NNFI = 0.957 Bentler CFI = 0.9828 SRMR = 0.015852 BIC = 14.488 Normalized Residuals Min. 1st Qu. Median Mean 3rd Qu. Max. -1.25000 -0.11500 0.00001 -0.00386 0.24000 0.97900 Parameter Estimates Estimate Std Error z value Pr(>|z|) a1 0.56105 0.034836 16.1055 0.0000e+00 動作知能 <--- 知能 a2 0.76424 0.036971 20.6712 0.0000e+00 記憶力 <--- 知能 a3 0.57208 0.034329 16.6645 0.0000e+00 数理知能 <--- 知能 b2 1.07429 0.052826 20.3363 0.0000e+00 TEST2 <--- 動作知能 b4 1.00951 0.040304 25.0478 0.0000e+00 TEST4 <--- 記憶力 b6 1.06620 0.051607 20.6599 0.0000e+00 TEST6 <--- 数理知能 d2 0.33961 0.033132 10.2501 0.0000e+00 動作知能 <--> 動作知能 d3 0.14698 0.038053 3.8625 1.1224e-04 記憶力 <--> 記憶力 d4 0.34521 0.034049 10.1385 0.0000e+00 数理知能 <--> 数理知能 e1 0.34561 0.031352 11.0237 0.0000e+00 TEST1 <--> TEST1 e2 0.24478 0.033320 7.3463 2.0384e-13 TEST2 <--> TEST2 e3 0.26896 0.026163 10.2802 0.0000e+00 TEST3 <--> TEST3 e4 0.25498 0.026277 9.7034 0.0000e+00 TEST4 <--> TEST4 e5 0.32752 0.031346 10.4486 0.0000e+00 TEST5 <--> TEST5 e6 0.23553 0.033210 7.0921 1.3205e-12 TEST6 <--> TEST6 Iterations = 50
因子得点の算出
> fscores(TEST.sem, data=df, centering=T, scale=F) #今回はデータがないため未実行
パス図の描画(graphvizで出力する)
> con <- file("TEST1.dot", encoding="UTF-8") > capture.output(file = con, path.diagram(TEST.sem, ignore.double=F, edge.labels = "both", standardize = F, node.font = c("Osaka", 12), edge.font = c("Osaka", 10), rank.direction = "TB")) > system("dot -Tpng TEST.dot -o TEST.png")
MIMICモデル
- モデルが識別されるように、母数を固定する
- f1: 内生変数なので、αb41,αb51,αb61のうちどれか一つを固定
- データ
- 以下のような相関行列
収入 | 1.00 |
学歴 | 0.434 1.00 |
職業威信 | 0.508 0.459 1.00 |
人脈 | 0.359 0.142 0.248 1.00 |
知名度 | 0.220 0.234 0.215 0.816 1.00 |
社会参加 | 0.259 0.299 0.220 0.868 0.779 1.00 |
- 実行
相関行列の入力
> social.cor <- read.moments(names = c("収入", "学歴", "職業威信", "人脈","知名度", "社会参加")) 1.00 0.434 1.00 0.508 0.459 1.00 0.359 0.142 0.248 1.00 0.220 0.234 0.215 0.816 1.00 0.259 0.299 0.220 0.868 0.779 1.00 22: Read 21 items
モデルの指定
> social.model <- specify.model() 収入 -> 社会的地位, αd1 学歴 -> 社会的地位,αd2 職業威信 -> 社会的地位, αd3 社会的地位 -> 人脈, NA, 1 社会的地位 -> 知名度,αb51, NA 社会的地位 -> 社会参加,αb61, NA 社会的地位 <-> 社会的地位,d1, NA 収入 <-> 学歴, σ21, NA 収入 <-> 職業威信,σ31, NA 学歴 <-> 職業威信,σ32, NA 人脈 <-> 人脈, e4, NA 知名度 <-> 知名度, e5, NA 社会参加 <-> 社会参加, e6, NA 収入 <-> 収入, NA, 1 学歴 <-> 学歴, NA, 1 職業威信 <-> 職業威信, NA, 1 17: Read 16 records
モデル構築
> social.sem <- sem(ram = social.model, S = social.cor, N = 1000) > summary(social.sem) Model Chisquare = 324.19 Df = 9 Pr(>Chisq) = 0 Chisquare (null model) = 3610.8 Df = 15 Goodness-of-fit index = 0.9131 Adjusted goodness-of-fit index = 0.79722 RMSEA index = 0.18723 90% CI: (0.17006, 0.20498) Bentler-Bonnett NFI = 0.91022 Tucker-Lewis NNFI = 0.8539 Bentler CFI = 0.91234 SRMR = 0.035230 BIC = 262.02 Normalized Residuals Min. 1st Qu. Median Mean 3rd Qu. Max. -2.0100 -0.0436 0.0000 0.0413 0.1460 3.3300 Parameter Estimates Estimate Std Error z value Pr(>|z|) αd1 0.253322 0.036540 6.9327 4.1296e-12 社会的地位 <--- 収入 αd2 0.050914 0.036033 1.4130 1.5767e-01 社会的地位 <--- 学歴 αd3 0.091187 0.035735 2.5518 1.0718e-02 社会的地位 <--- 職業威信 αb51 0.889684 0.021464 41.4504 0.0000e+00 知名度 <--- 社会的地位 αb61 0.946008 0.019856 47.6432 0.0000e+00 社会参加 <--- 社会的地位 d1 0.804465 0.040311 19.9563 0.0000e+00 社会的地位 <--> 社会的地位 σ21 0.434000 0.023368 18.5726 0.0000e+00 学歴 <--> 収入 σ31 0.508000 0.020846 24.3696 0.0000e+00 職業威信 <--> 収入 σ32 0.459000 0.022561 20.3446 0.0000e+00 職業威信 <--> 学歴 e4 0.081529 0.011974 6.8089 9.8324e-12 人脈 <--> 人脈 e5 0.272995 0.015040 18.1518 0.0000e+00 知名度 <--> 知名度 e6 0.178031 0.012924 13.7755 0.0000e+00 社会参加 <--> 社会参加 Iterations = 35
因子得点の算出
> fscores(social.sem, data=df, centering=T, scale=F) #今回はデータがないため未実行
パス図の描画(graphvizで出力する)
> con <- file("social.dot", encoding="UTF-8") > capture.output(file = con, path.diagram(social.sem, ignore.double=F, edge.labels = "both", standardize = F, node.font = c("Osaka", 12), edge.font = c("Osaka", 10), rank.direction = "LR")) > system("dot -Tpng social.dot -o social.png")
縦断的モデル
- モデルが識別されるように、いくつかの母数を固定する
- f1 : 外生変数なので、, a1, a2, a3のうちどれかを1つを固定。
- f2 : 内生変数なので、αb32,αb42のどちらか1つを固定。
- f3 : 内生変数なので、αb53,αb63のどちらか1つを固定。
- データ
- 以下のような相関行列
検査1 | 1.00 |
面接1 | 0.610 1.00 |
検査2 | 0.422 0.297 1.00 |
面接2 | 0.268 0.419 0.660 1.00 |
検査3 | 0.466 0.223 0.400 0.228 1.00 |
面接3 | 0.221 0.458 0.241 0.412 0.585 1.00 |
- 実行
相関行列を入力
> kensa.cor <- read.moments(names = c("検査1", "面接1", "検査2", "面接2","検査3", "面接3")) 1.00 0.610 1.00 0.422 0.297 1.00 0.268 0.419 0.660 1.00 0.466 0.223 0.400 0.228 1.00 0.221 0.458 0.241 0.412 0.585 1.00 22: Read 21 items
モデルを指定
> kensa.model <- specify.model() 初期自己像 -> 検査1, NA, 1 初期自己像 -> 面接1, αb21, NA 中期自己像 -> 検査2, NA, 1 中期自己像 -> 面接2, αb41, NA 終期自己像 -> 検査3, NA, 1 終期自己像 -> 面接3, αb61, NA 初期自己像 -> 中期自己像, αa21, NA 中期自己像 -> 終期自己像, αa32, NA 初期自己像 <-> 初期自己像, NA, 1 中期自己像 <-> 中期自己像, d2, NA 終期自己像 <-> 終期自己像, d3, NA 検査1 <-> 検査1, e1, NA 面接1 <-> 面接1, e2, NA 検査2 <-> 検査2, e3, NA 面接2 <-> 面接2, e4, NA 検査3 <-> 検査3, e5, NA 面接3 <-> 面接3, e6, NA 18: Read 17 records
モデル構築
> kensa.sem <- sem(ram = kensa.model, S = kensa.cor, N = 1000) > summary(kensa.sem) Model Chisquare = 788.47 Df = 8 Pr(>Chisq) = 0 Chisquare (null model) = 2627.1 Df = 15 Goodness-of-fit index = 0.7859 Adjusted goodness-of-fit index = 0.43798 RMSEA index = 0.3125 90% CI: (0.29426, 0.33114) Bentler-Bonnett NFI = 0.69987 Tucker-Lewis NNFI = 0.43976 Bentler CFI = 0.7012 SRMR = 0.11342 BIC = 733.21 Normalized Residuals Min. 1st Qu. Median Mean 3rd Qu. Max. -3.330 -1.620 -0.209 0.766 1.820 10.200 Parameter Estimates Estimate Std Error z value Pr(>|z|) αb21 0.68102 0.044440 15.3243 0.0000e+00 面接1 <--- 初期自己像 αb41 0.80549 0.050278 16.0209 0.0000e+00 面接2 <--- 中期自己像 αb61 0.76603 0.078965 9.7009 0.0000e+00 面接3 <--- 終期自己像 αa21 0.48021 0.038657 12.4223 0.0000e+00 中期自己像 <--- 初期自己像 αa32 0.49902 0.041492 12.0269 0.0000e+00 終期自己像 <--- 中期自己像 d2 0.59471 0.061660 9.6449 0.0000e+00 中期自己像 <--> 中期自己像 d3 0.56325 0.081439 6.9162 4.6381e-12 終期自己像 <--> 終期自己像 e1 0.10789 0.052846 2.0416 4.1189e-02 検査1 <--> 検査1 e2 0.57738 0.038787 14.8860 0.0000e+00 面接1 <--> 面接1 e3 0.19515 0.047282 4.1274 3.6685e-05 検査2 <--> 検査2 e4 0.47780 0.034629 13.7979 0.0000e+00 面接2 <--> 面接2 e5 0.23632 0.075062 3.1484 1.6418e-03 検査3 <--> 検査3 e6 0.55187 0.050110 11.0133 0.0000e+00 面接3 <--> 面接3 Iterations = 33
因子得点の算出
> fscores(kensa.sem, data=df, centering=T, scale=F) #今回はデータがないため未実行
パス図の描画(graphvizで出力する)
> con <- file("kensa.dot", encoding="UTF-8") > capture.output(file = con, path.diagram(kensa.sem, ignore.double=F, edge.labels = "both", standardize = F, node.font = c("Osaka", 12), edge.font = c("Osaka", 10), rank.direction = "TB")) > system("dot -Tpng kensa.dot -o kensa.png")