多変量解析_07_構造方程式モデリング

10.8K Views

July 25, 23

スライド概要

神戸大学経営学研究科で2022年度より担当している「統計的方法論特殊研究(多変量解析)」の講義資料「07_構造方程式モデリング」です。
2025/2/5: 全体的に内容に手を入れました。RmarkdownからQuartoに変更しました。

profile-image

神戸大学経営学研究科准教授 分寺杏介(ぶんじ・きょうすけ)です。 主に心理学的な測定・教育測定に関する研究を行っています。 講義資料や学会発表のスライドを公開していきます。 ※スライドに誤りを見つけた方は,炎上させずにこっそりお伝えいただけると幸いです。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Chapter 7 構造方程式モデリング Chapter 7 構造方程式モデリング 複数の観測変数間の関係性について柔軟なモデルをあてはめて分析を行う構造方程式モデリング について,前半では理論的な考え方と lavaan でのやり方を説明し,後半では実践上のいくつかの トピック(モデル適合度・モデル修正・多母集団同時分析・PLS-SEM など)を解説しています。 本資料は,神戸大学経営学研究科で 2022 年度より担当している「統計的方法論特殊研究(多 変量解析) 」の講義資料です。CC BY-NC 4.0 ライセンスの下に提供されています。 作成者連絡先 神戸大学大学院経営学研究科 分寺杏介(ぶんじ・きょうすけ) mail: [email protected] website: https://www2.kobe-u.ac.jp/~bunji/ 今回からは構造方程式モデリング (Structural Equation Modeling; SEM) の話です。は じめに SEM の基本的な考え方を紹介し,R で実際に実行してみます。 R での SEM は lavaan というパッケージを用いるのが最もメジャーです。事前にインストー ル&読み込みをしておきましょう。合わせて,このチャプターで使用するいくつかのパッケージ もインストールしておきます。 事前準備 1 2 3 4 5 6 7 # まだインストールしていない人は # install.packages("lavaan") # install.packages("lavaanPlot") # install.packages("semTools") # 前半ではlavaanのみ使います。 library(lavaan) 1

2.
[beta]
7.1 因子分析の見方を変える

8

2

dat <- readRDS("chapter04.rds")

7.1 因子分析の見方を変える
7.1.1 1 因子モデル

図 7.1: 因子分析モデル
まずは 図 7.1 のような1因子3項目の因子分析モデルを考えてみます。このモデルでは,各
観測変数はそれぞれ

⎧𝐲1 = 𝐟 𝑏1 + 𝜺1
{
𝐲 = 𝐟 𝑏 2 + 𝜺2
⎨ 2
{𝐲 = 𝐟 𝑏 + 𝜺
⎩ 3
3
3

(7.1)

と表されました。したがって,3つの観測変数のモデル上の共分散行列 𝚺 は

𝑏12 + 𝜎𝜺21
⎡
𝚺 = ⎢ 𝑏2 𝑏1
⎣ 𝑏3 𝑏1

𝑏1 𝑏2
𝑏22 + 𝜎𝜺22
𝑏3 𝑏2

𝑏1 𝑏3
𝑏2 𝑏3 ⎤
⎥
2
𝑏3 + 𝜎𝜺23 ⎦

(7.2)

となります。また,3つの観測変数のデータでの共分散行列も

𝜎𝑦21
⎡
𝐒 = ⎢𝜎𝑦2 ,𝑦1
⎣𝜎𝑦3 ,𝑦1

𝜎𝑦1 ,𝑦2
𝜎𝑦22
𝜎𝑦3 ,𝑦2

𝜎𝑦1 ,𝑦3
𝜎𝑦2 ,𝑦3 ⎤
⎥
𝜎𝑦23 ⎦

(7.3)

と表すことができ,これは実際にデータから計算が可能です。例えば Q1_1 から Q1_3 の3項目

3.

7.1 因子分析の見方を変える 3 のみを考えれば cov(dat[,paste0("Q1_",1:3)]) によって*1 具体的に 1.976 0.581 𝐒=⎡ ⎢0.581 1.375 ⎣0.504 0.762 0.504 0.762⎤ ⎥ 1.706⎦ という値が得られます。構造方程式モデリングでは,𝚺 の値が 𝐒 にできるだけ近づくように母数 (パラメータ)を推定します。実際に (7.2) 式の 𝚺 と (7.3) 式の 𝐒 の同じ項をイコールで結ぶと, 2 2 2 ⎧ 𝜎𝑦1 = 𝑏1 + 𝜎𝜺1 { { 𝜎𝑦22 = 𝑏22 + 𝜎𝜺22 { { 𝜎 2 = 𝑏2 + 𝜎 2 𝑦3 𝜺3 3 ⎨𝜎 = 𝑏 𝑏 1 2 { 𝑦1 ,𝑦2 {𝜎 = 𝑏 𝑦 ,𝑦 1 𝑏3 { 1 3 { ⎩𝜎𝑦2 ,𝑦3 = 𝑏2 𝑏3 (7.4) と い う 連 立 方 程 式 を 得 る こ と が 出 来 ま す。 こ の モ デ ル で 推 定 す る べ き パ ラ メ ー タ は (𝑏1 , 𝑏2 , 𝑏3 , 𝜎𝜺21 , 𝜎𝜺22 , 𝜎𝜺23 ) の6つです。そして式も6つあるため,このケースでは明確な解を求め ることが出来ます。例えば Q1_1 から Q1_3 の3項目であれば 2 2 ⎧1.976 = 𝑏1 + 𝜎𝜺1 { {1.375 = 𝑏22 + 𝜎𝜺22 { {1.706 = 𝑏2 + 𝜎2 𝜺3 3 ⎨0.581 = 𝑏 𝑏 1 2 { {0.504 = 𝑏 𝑏 { 1 3 { 0.762 = 𝑏 ⎩ 2 𝑏3 となり,これを解くと ⎧ 𝑏1 = 0.620 { 𝑏 = 0.937 { 2 { { 𝑏3 = 0.813 ⎨𝜎𝜺21 = 1.591 { {𝜎2 = 0.497 { 𝜺2 { 2 ⎩𝜎𝜺3 = 1.045 という解が得られます。図 7.1 に書き加えたならば図 7.2 のようになります。 グラフィカルモデルでは,観測変数を四角形で,潜在変数を楕円で表していました。図 7.2 と パラメータの関係を見てみると,2 つの観測変数の共分散は,2 つの四角形を結ぶ矢印にかかる 係数の積になっていることがわかります。つまり,グラフィカルモデル上で経路が存在する観測 変数間には非ゼロの共分散があることを仮定していたわけです。また,1 つの観測変数の分散は, その四角形に向かっている矢印の係数の二乗和になっています。なお,独自因子には自分自身に 対する両方向の矢印が引かれています。グラフィカルモデルでは両方向の矢印で共分散を表すの *1 実際には cov() 関数で得られるのは不偏共分散行列です。𝐒 は標本共分散行列なので,𝑃 /𝑃 − 1 倍する必要が あったりするのですが,今回は 2000 人以上いるので気にしないことにします。

4.

7.1 因子分析の見方を変える 4 図 7.2: 因子分析モデルの解 で,これは自分自身との共分散=分散を表していることになります。 先程の結果は観測変数を標準化していない状態での解でした。そのため,独自因子の分散が 1 を超えたり,因子負荷の二乗との合計が 1 にならなかったりしています。例えば項目 𝐲1 につい て見てみると,因子負荷の二乗と独自因子の分散の和は 0.6202 + 1.591 ≃ 1.976 となります。こ れは,𝐲1 の分散 𝜎𝑦21 の値 1.976 に対応しているわけです。ここで前回までの因子分析と同じよ うに全ての観測変数を標準化した状態,つまり 𝐒 に共分散行列ではなく相関行列を与えて推定を した場合に得られる解のことを標準化解や標準化推定値などと呼びます。そして SEM では多く の場合,結果には標準化解を載せています。絶対のルールでは無いのですが,特に潜在変数があ る場合には単位の影響を受けない標準化解を用いたほうがしっくり来る,ということなのでしょ う。ということでこの先も,潜在変数が含まれるモデルを扱う場合には 𝐒 には相関行列を想定し た,標準化解を考えることにします。 実 際 に 先 程 の 例 で 標 準 化 解 を 計 算 し て み る と, デ ー タ に お け る 相 関 行 列 𝐒 は cor(dat[,paste0("Q1_",1:3)]) によって具体的に*2 1 0.353 0.274 0.353 1 0.497⎤ 𝐒=⎡ ⎢ ⎥ 1 ⎦ ⎣0.274 0.497 *2 もちろんこれも厳密にはポリコリック相関のほうが良い可能性が高いですが,ここでは深く考えずにとりあえず ピアソンの積率相関係数で話を進めます。

5.

7.1 因子分析の見方を変える 5 という値が得られるため,連立方程式は 1 = 𝑏12 + 𝜎𝜺21 ⎧ { { 1 = 𝑏22 + 𝜎𝜺22 { { 1 = 𝑏32 + 𝜎𝜺23 ⎨0.353 = 𝑏 𝑏 1 2 { {0.274 = 𝑏 𝑏 { 1 3 { 0.497 = 𝑏 ⎩ 2 𝑏3 となり,これを解くと ⎧ 𝑏1 = 0.441 { 𝑏 = 0.800 { 2 { { 𝑏3 = 0.622 ⎨𝜎𝜺21 = 0.805 { {𝜎2 = 0.361 { 𝜺2 { 2 ⎩𝜎𝜺3 = 0.613 という標準化解を得ることができます。 7.1.2 2 因子モデル 図 7.3: 2 因子モデル 続いて 図 7.3 のような 2 因子 6 項目の因子分析モデルで同じように見てみましょう。ここで は,因子 1 は最初の 3 項目にのみ,因子 2 は後ろの 3 項目にのみ影響を与えているという仮定 を置いています。また,2 つの因子の間は両矢印でつながっています。これは因子間に相関関係 𝑟𝑓1,𝑓2 があることを表しています。このように, (共)分散を表す時には両矢印を使います。言い 換えると,ここでは因子間の共分散(=相関)が 0 でなくても良いという仮定(斜交回転)を置 いているのです。

6.

7.1 因子分析の見方を変える 6 このモデルでは,因子負荷行列 𝐁⊤ は 𝑏11 ⎡𝑏 ⎢ 21 𝑏 ⊤ 𝐁 = ⎢ 31 ⎢0 ⎢0 ⎣0 0 0⎤ ⎥ 0⎥ 𝑏42 ⎥ 𝑏52 ⎥ 𝑏62 ⎦ (7.5) となります。ちなみに SEM で多因子モデルを扱う場合の多くは,このように 1 項目が 1 因子か らのみ影響を受けていると考えると思います*3 。 すると,6 つの観測変数のモデル上の相関行列 𝚺 は 𝚺 = 𝐁⊤ 𝚽𝐁 + 𝚿 𝑏11 ⎡𝑏 ⎢ 21 𝑏 = ⎢ 31 ⎢0 ⎢0 ⎣0 0 0⎤ ⎥ 1 𝑟𝑓1,𝑓2 𝑏11 𝑏21 𝑏31 0 0⎥ 0 0 [ ][ ]+𝚿 𝑏42 ⎥ 𝑟𝑓1,𝑓2 1 0 0 0 𝑏42 𝑏52 𝑏62 𝑏52 ⎥ 𝑏62 ⎦ 2 𝑏11 𝑏11 𝑏21 𝑏11 𝑏31 𝑟𝑓1,𝑓2 𝑏11 𝑏42 𝑟𝑓1,𝑓2 𝑏11 𝑏52 2 ⎡ 𝑏 𝑏 𝑏21 𝑏21 𝑏31 𝑟𝑓1,𝑓2 𝑏21 𝑏42 𝑟𝑓1,𝑓2 𝑏21 𝑏52 21 11 ⎢ 2 𝑏 𝑏 𝑏 𝑏 𝑏 𝑟𝑓1,𝑓2 𝑏31 𝑏42 𝑟𝑓1,𝑓2 𝑏31 𝑏52 31 11 31 21 31 =⎢ 2 𝑏42 𝑏42 𝑏52 ⎢𝑟𝑓1,𝑓2 𝑏42 𝑏11 𝑟𝑓1,𝑓2 𝑏42 𝑏21 𝑟𝑓1,𝑓2 𝑏42 𝑏31 2 ⎢𝑟𝑓1,𝑓2 𝑏52 𝑏11 𝑟𝑓1,𝑓2 𝑏52 𝑏21 𝑟𝑓1,𝑓2 𝑏52 𝑏31 𝑏52 𝑏42 𝑏52 𝑏62 𝑏42 𝑏62 𝑏52 ⎣𝑟𝑓1,𝑓2 𝑏62 𝑏11 𝑟𝑓1,𝑓2 𝑏62 𝑏21 𝑟𝑓1,𝑓2 𝑏62 𝑏31 𝜎𝜺2 ⎡ 01 ⎢ ⎢ 0 +⎢ ⎢ 0 ⎢ 0 ⎣ 0 0 𝜎𝜺22 0 0 0 0 2 𝑏11 + 𝜎𝜺2 ⎡ 𝑏 𝑏 1 21 11 ⎢ ⎢ 𝑏31 𝑏11 =⎢ ⎢𝑟𝑓1,𝑓2 𝑏42 𝑏11 ⎢𝑟𝑓1,𝑓2 𝑏52 𝑏11 ⎣𝑟𝑓1,𝑓2 𝑏62 𝑏11 0 0 𝜎𝜺23 0 0 0 0 0 0 𝜎𝜺24 0 0 0 0 0 0 𝜎𝜺25 0 𝑏11 𝑏21 2 𝑏21 + 𝜎𝜺22 𝑏31 𝑏21 𝑟𝑓1,𝑓2 𝑏42 𝑏21 𝑟𝑓1,𝑓2 𝑏52 𝑏21 𝑟𝑓1,𝑓2 𝑏62 𝑏21 0 0 ⎤ ⎥ 0 ⎥ 0 ⎥ ⎥ 0 ⎥ 𝜎𝜺26 ⎦ 𝑏11 𝑏31 𝑏21 𝑏31 2 𝑏31 + 𝜎𝜺23 𝑟𝑓1,𝑓2 𝑏42 𝑏31 𝑟𝑓1,𝑓2 𝑏52 𝑏31 𝑟𝑓1,𝑓2 𝑏62 𝑏31 𝑟𝑓1,𝑓2 𝑏11 𝑏42 𝑟𝑓1,𝑓2 𝑏21 𝑏42 𝑟𝑓1,𝑓2 𝑏31 𝑏42 2 𝑏42 + 𝜎𝜺24 𝑏52 𝑏42 𝑏62 𝑏42 𝑟𝑓1,𝑓2 𝑏11 𝑏52 𝑟𝑓1,𝑓2 𝑏21 𝑏52 𝑟𝑓1,𝑓2 𝑏31 𝑏52 𝑏42 𝑏52 2 𝑏52 + 𝜎𝜺25 𝑏62 𝑏52 𝑟𝑓1,𝑓2 𝑏11 𝑏62 𝑟𝑓1,𝑓2 𝑏21 𝑏62 ⎤ ⎥ 𝑟𝑓1,𝑓2 𝑏31 𝑏62 ⎥ 𝑏42 𝑏62 ⎥ 𝑏52 𝑏62 ⎥ 2 𝑏62 ⎦ 𝑟𝑓1,𝑓2 𝑏11 𝑏62 𝑟𝑓1,𝑓2 𝑏21 𝑏62 ⎤ ⎥ 𝑟𝑓1,𝑓2 𝑏31 𝑏62 ⎥ 𝑏42 𝑏62 ⎥ ⎥ 𝑏52 𝑏62 ⎥ 2 𝑏62 + 𝜎𝜺26 ⎦ (7.6) となります。 例えば y_1 と y_4 の繋がりを図 7.3 で見てみると,y_1 → f_1 → f_2 → y_4 という経路に なっており,この 2 変数の共分散はそれぞれの矢印に係る係数の積である 𝑟𝑓1,𝑓2 𝑏42 𝑏11 となって いることがわかります。もし因子間に相関がなければ,y_1 と y_4 を結ぶ経路は存在せず,数式 的には 𝑟𝑓1,𝑓2 = 0 となることからも,この 2 変数が完全に無相関であることを意味するようにな ります。 *3 理論的には 𝑇 因子構造の場合,因子負荷行列のうち最低でも 𝑇 (𝑇 − 1) 個の値を固定したら推定は可能です。

7.

7.1 因子分析の見方を変える 7 このモデルの重要なポイントは,分散共分散行列が 𝐁⊤ 𝚽𝐁 + 𝚿 という形で分解可能だという 点は前回までの因子分析と全く同じだという点です。SEM の枠組みでは,因子負荷行列 𝐁 や因 子間相関 𝚽 に関して要素の値を固定(通常は 0 に固定)するため,それに応じて観測変数間の共 分散の形は変わりますが,違いといえばそれだけです*4 。特定の因子が特定の項目にのみ負荷を 持っているという仮定は,分析者が仮説などに基づいて行うものです。そして得られた結果(𝚺 と 𝐒 の乖離度)は,その仮説(に基づく共分散構造)がどの程度妥当そうかを表したものといえ ます。そのような意味で,SEM における因子分析を検証的(確認的)因子分析 (confirmatory factor analysis; CFA) と呼びます。一方,前回まで行っていた因子分析は,因子構造を探し 当てるのが目的だったため探索的因子分析 (exploratory factor analysis; EFA) と呼んでい ます。 上述のモデルでは,推定するパラメータは全部で 13 個(6 個の因子負荷+ 6 個の誤差分散+ 1 個の因子間相関)あり,対する観測変数間の分散共分散の数が全部で 21 個(分散が 6 個+共分 散が 15 個)あります。ということで 1 因子 3 項目の場合のように解を一意に求めることは出来 ないのですが,なるべく誤差が小さくなるように全てのパラメータをまとめて推定することは可 能なわけです。 7.1.3 もう少しだけ複雑なモデル 図 7.4: 独立ではない 2 因子モデル CFA では,「ある項目は 2 つの因子の影響を受けている」というモデルを作ることも当然可能 です。図 7.4 は,項目 3 だけが 2 つの因子の影響を受けていると仮定しています。この時,因子 負荷行列は 𝑏11 ⎡𝑏 ⎢ 21 𝑏 ⊤ 𝐁 = ⎢ 31 ⎢0 ⎢0 ⎣0 0 0⎤ ⎥ 𝑏32 ⎥ 𝑏42 ⎥ 𝑏52 ⎥ 𝑏62 ⎦ (7.7) *4 残念ながら固有値分解によって因子負荷行列を求めることはできなくなりますが,コンピュータによる反復計算 ならば力技で近い値を求めることができるでしょう。

8.

7.2 R でやってみる(検証的因子分析) 8 となります。このとき共分散行列はどうなるでしょうか。(7.6) 式と同じ要領で 𝚺 は計算できる のですが,すべて書くのは面倒ですね。例えば項目 1 と 3 の共分散だけ抜き出してみると 𝜎𝑦1,𝑦3 = 𝑏31 𝑏11 + 𝑟𝑓1,𝑓2 𝑏32 𝑏11 (7.8) という形になっています。改めて図 7.4 で y_1 と y_3 の経路を見てみると, • y_1 → f_1 → y_3 (𝑏31 𝑏11 ) • y_1 → f_1 → f_2 → y_3(𝑟𝑓1,𝑓2 𝑏32 𝑏11 ) という 2 つの経路が存在しており,それに対応した係数の積の和がこの 2 変数の共分散を表す ようになっています。また,項目 3 の分散は 2 2 2 𝜎𝑦3 = 𝑏31 + 𝑏32 + 2𝑟𝑓1,𝑓2 𝑏31 𝑏32 + 𝜎𝜺23 (7.9) となります。1 因子モデルのときも分散は係数の二乗和になっていましたが,より正確に言えば 2 • y_3 → f_1 → y_3 (𝑏31 ) 2 • y_3 → f_2 → y_3 (𝑏32 ) • y_3 → e_3 → y_3 (𝜎𝜺23 ) • y_3 → f_1 → f_2 → y_3 (𝑟𝑓1,𝑓2 𝑏31 𝑏32 ) • y_3 → f_2 → f_1 → y_3 (𝑟𝑓1,𝑓2 𝑏31 𝑏32 ) という要領で,その変数を出発してから戻るまでの経路の全パターンに関して同様の計算をし ていたわけです。 7.2 R でやってみる(検証的因子分析) それでは,図 7.3 の 2 因子モデルを実際に SEM の枠組み(検証的因子分析)で推定してみま しょう。lavaan では,lm() などと同じように第一引数にモデル式を与えます。ただ複雑なモデ ルになると結構な長さになるので,以下のように事前にモデル式をオブジェクトに入れておくの がおすすめです。 モデル式を用意する 1 2 3 4 5 6 model_cfa <- " # 改行とコメントアウトはご自由に f_1 =~ Q1_1 + Q1_2 + Q1_3 f_2 =~ Q1_6 + Q1_7 + Q1_8 " モデル式は character 型で用意するため,ダブルクオート( " ")かシングルクオート( ' ') で全体をくくります。その中に,回帰式のようなものを書き連ねていきます。lavaan の構文で は,潜在変数を規定する場合にはイコールチルダ( =~)を使用します。つまり,上のコードの

9.

7.2 R でやってみる(検証的因子分析) 9 4 行目では「因子 f_1 は Q1_1 と Q1_2 と Q1_3 に影響を与えているもの」であることを表して いるわけです。ちなみに観測変数に関してはデータフレームの列名で指定しますが,潜在変数 はデータフレーム内に存在しないので,自分でわかりやすい名前をつけても構いません。例え ば Q1_1 と Q1_2 と Q1_3 は”Agreeableness” を測定する項目だとわかっているので,1 行目は f_A =~ Q1_1 + Q1_2 + Q1_3 としても良いわけです。lavaan では,データフレームに存在し ない変数は自動的に潜在変数であるとみなして分析を行ってくれます。 モデル式が用意できたら,あとは分析を実行するだけです。検証的因子分析の場合には cfa() という関数を利用しましょう*5 。 lavaan で CFA 1 2 3 result_cfa <- cfa(model_cfa, data = dat) # 結果を見るときにはlm()と同じようにsummary()にかける summary(result_cfa) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 lavaan 0.6-18 ended normally after 38 iterations Estimator Optimization method Number of model parameters ML NLMINB 13 Number of observations 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 62.061 8 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 Estimate Std.Err z-value P(>|z|) 1.000 1.548 1.348 0.106 0.082 14.538 16.362 0.000 0.000 *5 本当は lavaan パッケージの基本関数は同名の lavaan() というものです。この関数ではモデルの推定のため の設定をいろいろと細かく変更できるのですが,その設定が割と細い上にデフォルトでは思っていたような設定 になかなかたどり着けません。いわば上級者向けの関数です。

10.

7.2 R でやってみる(検証的因子分析) 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 f_2 =~ Q1_6 Q1_7 Q1_8 10 1.000 1.220 0.894 0.075 0.053 16.316 16.756 0.000 0.000 Estimate Std.Err z-value P(>|z|) 0.115 0.016 7.349 0.000 Estimate 1.607 0.492 1.036 0.950 0.888 1.205 0.368 0.567 Std.Err 0.051 0.054 0.050 0.043 0.055 0.044 0.040 0.047 z-value 31.229 9.151 20.917 22.233 16.193 27.532 9.180 11.995 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 結果を上から見ていきましょう。 3 4 5 Estimator Optimization method Number of model parameters ML NLMINB 13 Estimator のところで,最尤推定法( ML)によってパラメータを求めていることがわかりま す。パラメータは反復計算で求めているのですが,Optimization method はその計算アルゴリ ズムを示しています。基本的には触れなくて OK です。Number of model parameters はモデ ルのパラメータ数です。6 個の因子負荷+ 6 個の誤差分散+ 1 個の因子間相関で 13 個というこ とは先程説明した通りです。 9 10 11 12 13 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 62.061 8 0.000 モデルに対して 𝜒2 検定を行っています。帰無仮説は「モデルの共分散行列とデータの共分散 行列が同じ」ということで,𝑝 値が大きい(帰無仮説が棄却されない)ほど当てはまりが良いこ とを意味します。つまり,できればこの検定は棄却されない(𝑝 > .05)と嬉しいのですが,統計 的仮説検定の仕組み上サンプルサイズが多いほど帰無仮説が棄却されやすかったりとなかなか使 い勝手の良いものではないので,基本的には無視でも良いでしょう。

11.

7.2 R でやってみる(検証的因子分析) 21 22 23 24 25 26 27 28 29 30 11 Latent Variables: Estimate Std.Err z-value P(>|z|) 1.000 1.548 1.348 0.106 0.082 14.538 16.362 0.000 0.000 1.000 1.220 0.894 0.075 0.053 16.316 16.756 0.000 0.000 f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 因子負荷です。lavaan はデフォルトでは,パラメータの制約として「因子の分散が 1」の代わ りに「各因子の第 1 項目に対する因子負荷が 1」という制約を置いています。因子分析の資料の 3 ページで潜在変数のスケールの不定性を説明しましたが,lavaan のデフォルトでは因子ごと に最初の項目の 𝑏 の値を一つ固定することによってその不定性を封じているわけです。ですが一 般的には「因子の分散が 1」の方がよく用いられる制約なので,そのようにした場合の推定値も 出力してみます。その方法は 2 種類あり,1 つ目の方法は「推定時に引数 std.lv = TRUE を与 える」というものです。 推定時に潜在変数の分散を 1 にする 1 result_cfa <- cfa(model_cfa, data = dat, std.lv = TRUE) 2 summary(result_cfa) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 lavaan 0.6-18 ended normally after 27 iterations Estimator Optimization method Number of model parameters Number of observations ML NLMINB 13 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 62.061 8 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured

12.

7.2 R でやってみる(検証的因子分析) 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 12 Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 Estimate Std.Err z-value P(>|z|) 0.607 0.939 0.818 0.033 0.034 0.034 18.359 27.729 24.120 0.000 0.000 0.000 0.753 0.919 0.673 0.031 0.035 0.031 23.990 26.112 21.419 0.000 0.000 0.000 Estimate Std.Err z-value P(>|z|) 0.251 0.028 8.852 0.000 Estimate 1.607 0.492 1.036 0.950 0.888 1.205 1.000 1.000 Std.Err 0.051 0.054 0.050 0.043 0.055 0.044 z-value 31.229 9.151 20.917 22.233 16.193 27.532 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 std.lv = TRUE とすることで,潜在変数 (latent variable) を標準化 (standardized) するこ とができます。また,もう一つの方法は「 summary() 時に引数 standardized = TRUE を与え る」というものです。この方法では因子の分散を 1 に調整した場合の推定値を事後的に変換して 出力してくれます。 事後的に推定値を変換する 1 2 # 説明のためstd.lv = TRUEを消して再推定 result_cfa <- cfa(model_cfa, data = dat) 3 summary(result_cfa, standardized = TRUE) 1 2 3 4 5 6 7 lavaan 0.6-18 ended normally after 38 iterations Estimator Optimization method Number of model parameters Number of observations ML NLMINB 13 2432

13.

7.2 R でやってみる(検証的因子分析) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 13 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 62.061 8 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 1.000 1.548 1.348 0.106 0.082 14.538 16.362 0.000 0.000 0.607 0.939 0.818 0.432 0.801 0.626 1.000 1.220 0.894 0.075 0.053 16.316 16.756 0.000 0.000 0.753 0.919 0.673 0.611 0.698 0.523 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.115 0.016 7.349 0.000 0.251 0.251 Estimate 1.607 0.492 1.036 0.950 0.888 1.205 0.368 0.567 Std.Err 0.051 0.054 0.050 0.043 0.055 0.044 0.040 0.047 z-value 31.229 9.151 20.917 22.233 16.193 27.532 9.180 11.995 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.607 0.492 1.036 0.950 0.888 1.205 1.000 1.000 Std.all 0.814 0.358 0.608 0.626 0.513 0.727 1.000 1.000 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 引数 standardized = TRUE を与えると,係数の出力の右に Std.lv と Std.all という 2 つ の列が追加されます。Std.lv 列は,推定時に引数 std.lv = TRUE を与えた時と同じ「潜在変 数のみ標準化された場合」の推定値です。一方 Std.all 列はその名の通り「観測変数も含めて 全て標準化された場合」の推定値,すなわち標準化解を出しています。 ただ実際の推定時には,std.lv = TRUE をいれると同時に,summary() 時に standardized = TRUE

14.

7.2 R でやってみる(検証的因子分析) 14 を入れるようにすると良いのではないかと思います。というのも cfa(std.lv = TRUE) のみだ と観測変数まで標準化した標準化解が出力されません。一方 summary(standardized = TRUE) のみだと各因子の第 1 項目の因子負荷が推定されなくなるため,仮説検定を行ってくれないため です。 標準化解の出し方(おすすめ) 1 result_cfa <- cfa(model_cfa, data = dat, std.lv = TRUE) 2 summary(result_cfa, standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 lavaan 0.6-18 ended normally after 27 iterations Estimator Optimization method Number of model parameters ML NLMINB 13 Number of observations 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 62.061 8 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.607 0.939 0.818 0.033 0.034 0.034 18.359 27.729 24.120 0.000 0.000 0.000 0.607 0.939 0.818 0.432 0.801 0.626 0.753 0.919 0.673 0.031 0.035 0.031 23.990 26.112 21.419 0.000 0.000 0.000 0.753 0.919 0.673 0.611 0.698 0.523 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.251 0.028 8.852 0.000 0.251 0.251 Covariances: f_1 ~~ f_2

15.

7.2 R でやってみる(検証的因子分析) 36 37 38 39 40 41 42 43 44 45 46 15 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 Estimate 1.607 0.492 1.036 0.950 0.888 1.205 1.000 1.000 Std.Err 0.051 0.054 0.050 0.043 0.055 0.044 z-value 31.229 9.151 20.917 22.233 16.193 27.532 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.607 0.492 1.036 0.950 0.888 1.205 1.000 1.000 Std.all 0.814 0.358 0.608 0.626 0.513 0.727 1.000 1.000 ということで改めて因子負荷から見ていきます。 21 22 23 24 25 26 27 28 29 30 Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.607 0.939 0.818 0.033 0.034 0.034 18.359 27.729 24.120 0.000 0.000 0.000 0.607 0.939 0.818 0.432 0.801 0.626 0.753 0.919 0.673 0.031 0.035 0.031 23.990 26.112 21.419 0.000 0.000 0.000 0.753 0.919 0.673 0.611 0.698 0.523 左から「推定値」 「標準誤差」 「検定統計量 𝑧」 「𝑝 値」 「 Std.lv」 「 Std.all」と並んでいます。 回帰分析のときと同じように「因子負荷が 0」という帰無仮説に対して仮説検定を行っています。 検定の結果は標準化してもしなくても変わらないのでご安心ください。 32 33 34 35 Covariances: f_1 ~~ f_2 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.251 0.028 8.852 0.000 0.251 0.251 共分散です。Std.lv と Std.all では潜在変数の分散は 1 になっているため,ここに表示され ている 0.251 は 2 因子の因子間相関を表しています。 37 38 39 40 41 42 43 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 Estimate 1.607 0.492 1.036 0.950 0.888 Std.Err 0.051 0.054 0.050 0.043 0.055 z-value 31.229 9.151 20.917 22.233 16.193 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 1.607 0.492 1.036 0.950 0.888 Std.all 0.814 0.358 0.608 0.626 0.513

16.

7.3 回帰分析の見方を変える 44 45 46 .Q1_8 f_1 f_2 16 1.205 1.000 1.000 0.044 27.532 0.000 1.205 1.000 1.000 0.727 1.000 1.000 各変数の分散です。Std.lv と Std.all では一番下の 2 つ( f_1 と f_2)の分散は 1 に固定 されています。変数名の左に . がついているものは,その観測変数にくっつく独自因子の分散 (または誤差分散)を表しています。 独自因子の分散のなかでも Std.all 列に表示された値は,探索的因子分析と同じように独自 性の値として考えることが出来ます。例えば項目 Q1_1 では,Std.all の値=独自因子の分散が 0.814 です。これに対して因子負荷は 0.432 でした。実際に因子負荷の二乗と独自因子の分散 の和は 0.4322 + 0.814 ≃ 1 となります。 ちなみに因子得点は,predict() 関数によって出すことが出来ます。 因子得点の算出 1 head(predict(result_cfa)) 1 2 3 4 5 6 7 f_1 f_2 [1,] -0.8119757 -1.46119237 [2,] -0.2904413 -0.08641555 [3,] -0.5899198 -0.03237852 [4,] -0.3137981 -0.54036752 [5,] -1.2359450 -0.24949133 [6,] 0.4269696 1.30844315 探索的因子分析のときと同様に,この因子得点の相関はモデル上の因子間相関(今回の場合 0.251)とは異なります。利用する際は気をつけてください。 因子得点の相関 1 2 # モデルパラメータの推定値とは異なる cor(predict(result_cfa)) 1 2 3 f_1 f_2 f_1 1.0000000 0.3259455 f_2 0.3259455 1.0000000 7.3 回帰分析の見方を変える SEM では回帰分析も共通の枠組みで取り扱うことが出来ます。つまり観測変数間の共分散構 造をモデルのパラメータで表し,推定を行います。最もシンプルな回帰モデルとして,図 7.5 の ように協調性の得点 Q1_A を年齢 age で回帰してみましょう。

17.

7.3 回帰分析の見方を変える 17 図 7.5: 単回帰モデル このモデルの回帰式は (7.10) 𝑥𝐴 = 𝑏0 + 𝑏1 𝑥age + 𝜀𝐴 となります。したがって,この 2 変数の共分散行列は 𝚺=[ 𝜎𝑥2 𝐴 𝜎𝑥𝐴 ,𝑥age 𝜎𝑥𝐴 ,𝑥age 𝑏12 𝜎𝑥2 age + 𝜎𝜀2𝐴 ]=[ 2 𝜎𝑥age 𝑏1 𝜎𝑥2 age 𝑏1 𝜎𝑥2 age ] 𝜎𝑥2 age (7.11) と表せます。回帰モデルなので,変数 𝑥𝐴 は 𝑥age の値に応じて変化していると見ることも出来ま す。言い換えると,𝑥𝐴 の値はモデルの中で決まっているということです。このように,モデル式 の中で他の変数の関数によって表される変数のことを内生変数 (endogenous variable) と呼び ます。一方,変数 𝑥age は他の変数の値によって変化することはありません。こうした変数を,内 生変数に対して外生変数 (exogenous variable) と呼びます。グラフィカルモデル的には,他 の変数からの一方向矢印が一つでも刺さっているものは全て内生変数と呼びます。SEM ではこ の「内生変数」と「外生変数」の分類がちょくちょく出てくるので,覚えておいてください。 さて,先程の回帰モデルを SEM で見た場合,推定しないといけないパラメータは 𝑏1 と 𝜎𝜀2𝐴 の 2 つです(𝜎𝑥2 age はデータから直接求めたら良いので)。そしてデータからは( cov() 関数を 使えば)2 つの変数の分散および共分散 𝐒=[ 𝑠2𝑥𝐴 𝑠𝑥𝐴 ,𝑥age 𝑠𝑥𝐴 ,𝑥age 20.667 8.906 ]=[ ] 𝑠2𝑥age 8.906 120.303 の(上三角と下三角は同じ式なので)計 3 つが計算できるため,これでモデルのパラメータが推 定できます。一応連立方程式を立ててみると, 2 2 2 ⎧ 20.667 = 𝑏1 𝜎𝑥age + 𝜎𝜀𝐴 ⎫ { } 20.667 = 120.303𝑏12 + 𝜎𝜀2𝐴 8.906 = 𝑏1 𝜎𝑥2 age ={ } ⎨ ⎬ 8.906 = 120.303𝑏1 {120.303 = 𝜎2 } 𝑥age ⎩ ⎭ となります。このように,外生変数の分散が連立方程式に含まれる場合には,その外生変数の データでの分散をそのまま入れてあげることが出来ます。なお,共分散構造のみを扱うならば, 切片 𝑏0 は推定の対象になっていないという点には気をつけてください。切片もモデルの推定対 象にしたい場合には,平均構造も含めた SEM を実行する必要があります*6 。 実際に計算してみると,(𝑏1 , 𝜎𝜀2𝐴 ) = (0.074, 20.007) という値が得られます。これを 𝚺 にあて *6 平均構造も統一的な枠組みで扱うために,近年では「共分散構造分析」ではなく「構造方程式モデリング」とい う呼び方が一般的なのだと思ってます。

18.

7.3 回帰分析の見方を変える 18 はめてみると, 𝚺=[ 0.0742 × 120.303 + 20.007 20.667 ]≃[ 0.074 × 120.303 120.303 8.906 120.303 ] ということで,データの共分散行列 𝐒 に一致する値が得られました。 7.3.1 もう少し複雑なモデル(パス解析) モデルが複雑になってもやることは同じです。回帰式を順に展開していき,全ての変数の分散 共分散を「外生変数の分散とパラメータ」で表してあげます。例えば 図 7.6 は重回帰分析に単回 帰分析をくっつけたようなモデルです。ちなみにこのように,単一の回帰式で表せないような, 回帰分析をくっつけたモデルは,SEM の中でも特にパス解析 (path analysis) と呼ばれること があります。 図 7.6: パス解析モデル 回帰式はそれぞれ { 𝑥𝐴 = 𝑏0𝐴 + 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝜀𝐴 𝑥𝐸 = 𝑏0𝐸 + 𝑏𝐴 𝑥𝐴 + 𝜀𝐸 (7.12) となりますが,さらに下の式の 𝑥𝐴 を展開することで ⎧𝑥𝐴 = 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝑏0𝐴 + 𝜀𝐴 { 𝑥 = 𝑏𝐴 (𝑏0𝐴 + 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝜀𝐴 ) + 𝑏0𝐸 + 𝜀𝐸 ⎨ 𝐸 { = 𝑏𝐴 𝑏0𝐴 + 𝑏𝐴 𝑏gender 𝑥gender + 𝑏𝐴 𝑏age 𝑥age + 𝑏𝐴 𝜀𝐴 + 𝑏0𝐸 + 𝜀𝐸 ⎩ (7.13) となります。なお,検証的因子分析での独自因子と同じように,パス解析でも内生変数に誤差項 *7 。こうすることによって,各変数の分散および共分散を を明示することがあります(図 7.7 ) 考えるのが多少楽になります(後述) 。 *7 パス解析での誤差項は潜在変数としても扱われないため,楕円で囲わないのが一般的です。

19.

7.3 回帰分析の見方を変える 19 図 7.7: パス解析モデル(誤差項を追加) 4 つの変数のモデル上の共分散行列 𝚺 の各成分は,頑張って展開すると 𝜎𝑥2 age = 𝜎𝑥2 age ⎧ { { 𝜎𝑥2 gender = 𝜎𝑥2 gender { {𝜎 { 𝑥gender ,𝑥age = 𝜎𝑥gender ,𝑥age { 2 2 { 𝜎𝑥2 𝐴 = 𝑏gender 𝜎𝑥2 gender + 𝑏age 𝜎𝑥2 age + 2𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age + 𝜎𝜀2𝐴 { { 2 2 2 2 2 2 2 𝜎𝑥2 𝐸 = 𝑏𝐴 𝑏gender 𝜎𝑥2 gender + 𝑏𝐴 𝑏age 𝜎𝑥2 age + 2𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age + 𝑏𝐴 𝜎𝜀𝐴 + 𝜎𝜀2𝐸 { ⎨ 𝜎𝑥 ,𝑥 = 𝑏gender 𝜎𝑥 + 𝑏age 𝜎𝑥2 age 𝐴 age gender ,𝑥age { { { 𝜎𝑥𝐸 ,𝑥age = 𝑏𝐴 𝑏gender 𝜎𝑥age ,𝑥gender + 𝑏𝐴 𝑏age 𝜎𝑥2 age { 2 { 𝜎 { 𝑥𝐴 ,𝑥gender = 𝑏gender 𝜎𝑥gender + 𝑏age 𝜎𝑥age ,𝑥gender { { 𝜎𝑥𝐸 ,𝑥gender = 𝑏𝐴 𝑏gender 𝜎𝑥2 gender + 𝑏𝐴 𝑏age 𝜎𝑥age ,𝑥gender { { 2 2 𝜎𝑥𝐸 ,𝑥𝐴 = 𝑏𝐴 𝑏gender 𝜎𝑥2 gender + 𝑏𝐴 𝑏age 𝜎𝑥2 age + 2𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age + 𝑏𝐴 𝜎𝜀2𝐴 ⎩ (7.14) となります。これを 図 7.7 に照らし合わせると,例えば 𝜎𝑥2 𝐴 は 2 • Q1_A → gender → Q1_A (𝑏gender 𝜎𝑥2 gender ) 2 • Q1_A → age → Q1_A (𝑏age 𝜎𝑥2 age ) • Q1_A → gender → age → Q1_A (𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age ) • Q1_A → age → gender → Q1_A (𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age ) • Q1_A → e_A → Q1_A (𝜎𝜀2𝐴 ) の和になっています。検証的因子分析のときと同じように,自分自身を出発してから最低 1 つの外生変数を通過して戻るまでの全経路の係数の和になっているわけです。同様に,共分散 𝜎𝑥𝐸 ,𝑥𝐴 では 2 • Q1_E → Q1_A → gender → Q1_A (𝑏𝐴 𝑏gender 𝜎𝑥2 gender ) 2 • Q1_E → Q1_A → age → Q1_A (𝑏𝐴 𝑏age 𝜎𝑥2 age ) • Q1_E → Q1_A → gender → age → Q1_A (𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age ) • Q1_E → Q1_A → age → gender → Q1_A (𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age ) • Q1_E → Q1_A → e_A → Q1_A (𝑏𝐴 𝜎𝜀2𝐴 ) という感じで,Q1_E から Q1_A への全経路での係数の和の形になっていると見ることができ

20.

7.4 R でやってみる(回帰分析・パス解析) 20 ます*8 。 というわけで,モデル上の共分散行列 𝚺 を求めることが出来ました。あとはこれに対応する データ上の分散(4 つ)と共分散(6 つ)を用いて,5 つのパラメータ (𝑏𝐴 , 𝑏age , 𝑏gender , 𝜎𝜀2𝐴 , 𝜎𝜀2𝐸 ) を推定するだけです。 実際に計算してみると, 𝜎𝑥2 age = 120.254 ⎧ { { 𝜎𝑥2 gender = 0.221 { { {𝜎𝑥gender ,𝑥age = 0.204 { { 𝑏𝐴 = 0.550 ⎨ 𝑏age = 0.071 { { 𝑏gender = 1.891 { { { 𝜎𝜀2𝐴 = 19.210 { { 𝜎𝜀2𝐸 = 22.154 ⎩ という解が得られます(上 3 つはデータから直接求めた値)。これを (7.14) 式に当てはめてみ ると, 𝜎𝑥2 age ⎡𝜎 𝑥gender ,𝑥age 𝚺=⎢ ⎢ 𝜎 ⎢ 𝑥𝐴 ,𝑥age ⎣ 𝜎𝑥𝐸 ,𝑥age 𝜎𝑥2 gender 𝜎𝑥𝐴 ,𝑥gender 𝜎𝑥𝐸 ,𝑥gender 𝜎𝑥2 𝐴 𝜎𝑥𝐸 ,𝑥𝐴 120.254 ⎤ ⎡ 0.221 ⎥ = ⎢ 0.204 ⎥ ⎢ 8.902 0.432 ⎥ 0.238 𝜎𝑥2 𝐸 ⎦ ⎣ 4.892 20.685 11.354 ⎤ ⎥ ⎥ 28.395⎦ となります。また,データ上の共分散行列の値は 120.254 ⎡ 0.204 𝐒=⎢ ⎢ 8.906 ⎣ 4.198 0.221 0.433 0.260 20.667 11.359 ⎤ ⎥ ⎥ 28.407⎦ となり,だいぶ近い値が得られました。 7.4 R でやってみる(回帰分析・パス解析) それでは,lavaan を使って回帰分析をやってみましょう。sem() 関数を使うと,回帰分析を 含むパス解析に適した設定で自動的に推定を行ってくれます。 モデル構文では,lm() や glm() のときと同じように,両辺をチルダ( ~)でつなげることで 観測変数どうしの回帰を表します。ということで,単回帰分析であれば以下のように 1 文だけの モデル構文を書けばよいわけです。 *8 「途中で Q1_A を通っているじゃないか」という点は大目に見てください。SEM では全ての内生変数の分散・ 共分散を外生変数の分散の関数で表す必要があるため,パスの経路で考える場合には必ず外生変数を通過する必 要があるのです。

21.
[beta]
7.4 R でやってみる(回帰分析・パス解析)

21

lavaan で単回帰分析
1
2
3
4

model <- "Q1_A ~ age"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

lavaan 0.6-18 ended normally after 1 iteration

result_lm <- sem(model, data = dat)
summary(result_lm)

Estimator
Optimization method
Number of model parameters

ML
NLMINB
2

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom

0.000
0

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Regressions:
Q1_A ~
age

Estimate

Std.Err

z-value

P(>|z|)

0.074

0.008

8.952

0.000

Estimate
19.999

Std.Err
0.574

z-value
34.871

P(>|z|)
0.000

Variances:
.Q1_A

基本的な結果の見方は因子分析の時と同じです。出力の Regressions: の部分が回帰係数を,

Variances: の部分が誤差分散を表しています。先程説明したように,SEM では共分散構造の
みを扱うならば,切片 𝑏0 は推定の対象にならないため,切片項 𝑏0 の推定値は出力されていませ
ん。これを出すためには,モデル式に少し手を加える必要があります。これも lm() や glm() の
時と同じなのですが,回帰式に "+ 1"を加えると,切片項を明示的に推定するように指示するこ
とが出来ます。

22.
[beta]
7.4 R でやってみる(回帰分析・パス解析)

22

切片項も出してください
1

model <- "

2

Q1_A ~ age + 1

3
4
5
6

"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

lavaan 0.6-18 ended normally after 1 iteration

result_lm <- sem(model, data = dat)
summary(result_lm)

Estimator
Optimization method
Number of model parameters

ML
NLMINB
3

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom

0.000
0

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Regressions:
Q1_A ~
age

Estimate

Std.Err

z-value

P(>|z|)

0.074

0.008

8.952

0.000

Estimate
21.122

Std.Err
0.253

z-value
83.433

P(>|z|)
0.000

Estimate
19.999

Std.Err
0.574

z-value
34.871

P(>|z|)
0.000

Intercepts:
.Q1_A
Variances:
.Q1_A

出力を見ると,新たに Intercepts: という欄ができています。これが切片を表している部分
です。一応,ここまでの結果を,lm() で普通に回帰分析を行った場合と比較してみましょう。

23.
[beta]
7.4 R でやってみる(回帰分析・パス解析)

23

lm() で回帰分析
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# できるだけlavaanのコードと見た目を同じにしてみました
model <- formula("Q1_A ~ age")
result_lm_base <- lm(model, data = dat)
summary(result_lm_base)

Call:
lm(formula = model, data = dat)
Residuals:
Min
1Q
-18.565 -2.602

Median
0.621

3Q
3.361

Max
8.064

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 21.121738
0.253261 83.399
<2e-16 ***
age
0.074029
0.008273
8.949
<2e-16 ***
--Signif. codes:

0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 4.474 on 2430 degrees of freedom
Multiple R-squared: 0.0319,
Adjusted R-squared: 0.0315
F-statistic: 80.08 on 1 and 2430 DF, p-value: < 2.2e-16

lm() では最小二乗法で解を求めている一方,lavaan はデフォルトでは最尤法で解を求めて
います。推定法の違いはありますが,回帰係数および切片はほぼ一致する値が得られました。
続いてパス解析もやってみましょう。基本的には一つ一つの回帰式を順番に書いていけば良い
だけです。簡単ですね。
パス解析
1
2
3
4
5
6
7

model <- "
Q1_A ~ gender + age
Q1_E ~ Q1_A
"

1
2
3

lavaan 0.6-18 ended normally after 1 iteration

result_sem <- sem(model, data = dat)
summary(result_sem)

Estimator

ML

24.

7.5 回帰分析と因子分析を組み合わせる 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 24 Optimization method Number of model parameters NLMINB 5 Number of observations 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 0.709 2 0.702 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Regressions: Q1_A ~ gender age Q1_E ~ Q1_A Estimate Std.Err z-value P(>|z|) 1.891 0.071 0.189 0.008 9.996 8.733 0.000 0.000 0.550 0.021 26.173 0.000 Estimate 19.210 22.154 Std.Err 0.551 0.635 z-value 34.871 34.871 P(>|z|) 0.000 0.000 Variances: .Q1_A .Q1_E 7.5 回帰分析と因子分析を組み合わせる 図 7.6 に基づくパス解析では,因子 A と因子 E に関する変数として和得点( Q1_A と Q1_E) を使用しました。ですが和得点には独自因子(構成概念からすると誤差)の影響が残っているた め,可能であれば因子得点を用いた方が「純粋」な構成概念得点であると考えられます。あるい は(構成概念)妥当性の考え方の根底にあった「観測得点はあくまでも構成概念の顕在化」とい う考えに従えば,仮説モデルでは構成概念そのもの同士の関係(法則定立ネットワーク)を見る べきだと言えるでしょう。 いま,手元には構成概念(因子)を構成する各項目の回答そのものがあります。そこで,図 7.3 の因子分析と 図 7.6 の回帰分析を組み合わせて,図 7.8 のようなモデルを考えてみましょう。

25.

7.5 回帰分析と因子分析を組み合わせる 25 図 7.8: 回帰分析と因子分析を組み合わせてみた モデルが複雑になってもやることは同じです。全ての(標準化された)観測変数間の相関行列 1 ⎡𝑟 ⎢ gender,age ⎢ 𝑟𝑦1,age ⎢ 𝑟 𝚺 = ⎢ 𝑦2,age 𝑟 ⎢ 𝑦3,age ⎢ 𝑟𝑦6,age ⎢ 𝑟𝑦7,age ⎣ 𝑟𝑦8,age 1 𝑟𝑦1,gender 𝑟𝑦2,gender 𝑟𝑦3,gender 𝑟𝑦6,gender 𝑟𝑦7,gender 𝑟𝑦8,gender 1 𝑟𝑦2,𝑦1 𝑟𝑦3,𝑦1 𝑟𝑦6,𝑦1 𝑟𝑦7,𝑦1 𝑟𝑦8,𝑦1 1 𝑟𝑦3,𝑦2 𝑟𝑦6,𝑦2 𝑟𝑦7,𝑦2 𝑟𝑦8,𝑦2 1 𝑟𝑦6,𝑦3 𝑟𝑦7,𝑦3 𝑟𝑦8,𝑦3 1 𝑟𝑦7,𝑦6 𝑟𝑦8,𝑦6 1 𝑟𝑦8,𝑦7 ⎤ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ 1⎦ と,データ上の相関行列 1 ⎡0.039 ⎢ ⎢0.156 ⎢0.113 𝐒=⎢ 0.064 ⎢ ⎢0.095 ⎢0.018 ⎣0.065 1 0.157 0.184 0.137 0.008 0.060 0.048 1 0.353 0.274 −0.011 −0.011 0.024 1 0.497 1 0.098 0.110 1 0.124 0.142 0.435 0.185 0.126 0.313 1 0.359 ⎤ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ 1⎦ がなるべく近くなるように各種パラメータを推定してあげます。 ここでいくつかの変数間のモデル上の相関係数を具体的に見てみましょう。同じ因子に属する Q1_1 と Q1_2 の相関は,(検証的)因子分析のときには 2 項目の因子負荷の積 (𝑏11 𝑏21 ) という簡 単な形で表すことができていました。今回のモデルではどうでしょうか。因子得点は内生変数と して扱われており,𝑓𝐴 = 𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 という回帰式になっています。これま でと同じように Q1_1 と Q1_2 をそれぞれ外生変数( age と gender)の関数になるまで展開し てあげるならば, 𝑦 1 = 𝑓 𝐴 𝑏1 + 𝜀 1 = (𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 )𝑏1 + 𝜀1 𝑦 2 = 𝑓 𝐴 𝑏2 + 𝜀 2 (7.15) = (𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 )𝑏2 + 𝜀2 となり,これを頑張って展開して相関を求める必要がありそうです。しかしよく考えてみる

26.

7.5 回帰分析と因子分析を組み合わせる 26 と,因子分析モデルでは潜在変数の分散を 1 に固定する,という制約がありました。つまり 𝑓𝐴 = (𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 ) の部分は,これをすべて合わせて分散 1 になるように調 整されるということです。したがってこの 2 項目の相関を求めると,結局 Chapter 6 で示した 1 因子モデルにおける観測変数間の相関 に帰着して*9 𝑟𝑦1,𝑦2 = 𝑟(𝑓𝐴 𝑏1 +𝜀1 ),(𝑓𝐴 𝑏2 +𝜀2 ) = 𝑟(𝑓𝐴 𝑏1 ),(𝑓𝐴 𝑏2 ) (7.16) = 𝑏1 𝑏2 (𝜎𝑓𝐴 ) = 𝑏 1 𝑏2 となるのです。また,誤差分散 𝜎𝜀2𝐴 の値は 1 から回帰係数の二乗和をひいた値になっています。 このあたりの議論は,矢印の向きこそ反対ですが因子分析の時に見た「観測変数の分散は因子負 荷の二乗和と独自因子の分散の和になっている」というのと同じですね。 続いて最も距離の遠い age と Q1_8 の相関を見てみます。Q1_8 を外生変数( age と gender) の関数に戻してあげると, 𝑦 8 = 𝑓 𝐸 𝑏8 + 𝜀 8 = (𝑏𝐴 𝑓𝐴 + 𝜀𝐸 )𝑏8 + 𝜀8 = (𝑏𝐴 [𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 ] + 𝜀𝐸 ) 𝑏8 + 𝜀8 (7.17) error ⏞⏞⏞ = 𝑏𝐴 𝑏8 (𝑏age 𝑥age + 𝑏gender 𝑥gender ) + ⏞⏞ 𝑏𝐴 𝑏8⏞ 𝜀⏞⏞⏞ 𝐴 + 𝑏8 𝜀𝐸 + 𝜀8 となります。後ろの 𝜀 に関する項 (error) は,観測変数 age との相関はゼロなはずなので無視し て分散を求めると, 2 𝑟age,𝑦8 = 𝑏𝐴 𝑏8 𝑏age 𝜎age + 𝑏𝐴 𝑏8 𝑏gender 𝜎age,gender = 𝑏𝐴 𝑏8 𝑏age + 𝑏𝐴 𝑏8 𝑏gender 𝜎age,gender (7.18) となります。ここでもやはり • Q1_8 → f_E → f_A → age (𝑏𝐴 𝑏8 𝑏age ) • Q1_8 → f_E → f_A → gender → age (𝑏𝐴 𝑏8 𝑏gender 𝜎age,gender ) という要領で,2 変数間の全経路の係数の積の和の形になっていることがわかります。 モデルが複雑になっても,内部でやっていることは今までと同じであることを確認したので, 実際に R で推定を行ってみましょう。 因子分析と回帰分析を同時にやる 1 2 3 4 5 # まずはモデル式を書く model <- " f_A =~ Q1_1 + Q1_2 + Q1_3 f_E =~ Q1_6 + Q1_7 + Q1_8 f_A ~ age + gender *9 共通因子と独自因子の間は無相関であり,またモデル上独自因子間も無相関と仮定しているため,これらの項が 全て消えています。

27.
[beta]
7.5 回帰分析と因子分析を組み合わせる

6
7
8

27

f_E ~ f_A
age ~~ gender
"

6 行目( age ~~ gender)は,age と gender の共分散を明示的に推定するように指示して
います(任意)。書かなくても勝手にデータから計算した値を使ってくれるので,この行の有無
でパラメータの推定値が変わることはないのですが,この行を書くことによって,結果の出力に
データの共分散の値を表示してくれるようになります。
1
2

result_sem <- sem(model, data = dat, std.lv = TRUE)
summary(result_sem, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

lavaan 0.6-18 ended normally after 36 iterations
Estimator
Optimization method
Number of model parameters

ML
NLMINB
18

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

129.227
18
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f_A =~
Q1_1
Q1_2
Q1_3
f_E =~
Q1_6
Q1_7
Q1_8
Regressions:

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.602
0.888
0.786

0.031
0.030
0.030

19.255
29.426
25.796

0.000
0.000
0.000

0.628
0.926
0.819

0.447
0.790
0.627

0.728
0.888
0.651

0.031
0.035
0.031

23.767
25.607
21.262

0.000
0.000
0.000

0.753
0.918
0.673

0.611
0.698
0.523

28.

7.5 回帰分析と因子分析を組み合わせる 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 f_A ~ age gender f_E ~ f_A 28 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.014 0.522 0.002 0.053 6.275 9.894 0.000 0.000 0.013 0.501 0.147 0.236 0.252 0.030 8.402 0.000 0.254 0.254 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.204 0.105 1.945 0.052 0.204 0.039 Estimate 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 1.000 1.000 Std.Err 0.051 0.046 0.046 0.043 0.055 0.044 3.449 0.006 z-value 31.144 11.273 22.666 22.240 16.228 27.533 34.871 34.871 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 0.920 0.935 Std.all 0.801 0.376 0.607 0.626 0.513 0.727 1.000 1.000 0.920 0.935 Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_E 結果の見方も同じなので省略します。一応全ての標準化解を図 7.8 に書き加えると,図 7.9 の ようになるわけです。実際に論文などで報告する際には,全ての値を載せるとごちゃごちゃして しまう可能性があります。そこで,以下のような省略を行い簡潔化することがあります。このあ たりは自由というか,どういう基準で簡略化したかがハッキリわかれば OK です。 • 因子分析の部分は書かない(因子だけ残す) • 係数が一定以下のところには矢印をひかない • 統計的に有意ではない係数のところは矢印をひかない lavaan の関数( cfa() や sem())によって得られた結果のオブジェクトから,自動的にパ ス図を作ってくれるものとして,lavaanPlot パッケージというものが用意されています。こ ういったものを利用して,自分で書いたモデルのコードが正しいものだったかをきちんと確認 しておくと良いでしょう。lavaanPlot パッケージは,図 7.10 のように比較的そのまま論文に も載せられそうなレベルのきれいな図を書いてくれます。ただ,見た目の点では変数名を変え たり,微妙に矢印の位置を調整したりする必要が出てくることが多いと思うので,最終的には PowerPoint や Illustrator などを使って自分で図を作ったほうが良さそうです。

29.

7.5 回帰分析と因子分析を組み合わせる 29 図 7.9: 結果を全て書くと lavaanPlot で簡単に作図 1 2 3 4 5 6 7 8 # インストールがまだの人は # install.packages("lavaanPlot") library(lavaanPlot) # 引数coefをTRUEにすると係数も乗せてくれる(デフォルトではFALSE) # 合わせて引数standをTRUEにすると標準化解になる # 他にも「有意なものだけ載せる」「有意なところに*をつける」など可能 # 他にも見た目をいじる引数が大量にあるので色々試してみてください lavaanPlot(result_sem, coef = TRUE, stand = TRUE) age gender 0.15 0.24 f_A 0.45 0.79 0.63 Q1_1 Q1_2 Q1_3 0.25 f_E 0.61 0.7 Q1_6 Q1_7 図 7.10: lavaanPlot による出力 0.52 Q1_8

30.

7.5 回帰分析と因子分析を組み合わせる 30 LIGHTBULB (情報提供 1)期待の新星 lavaangui パッケージ ​ ​ 2024 年 9 月に新しく CRAN にリリースされた lavaangui パッケージは,その名の通り GUI で操作可能な形で lavaan を利用できるパッケージです。基本的な機能は 2 種類で, まず 1 つ目は GUI でモデル式を自動作成できる機能です。使い方は簡単で,lavaangui() を実行するとウェブブラウザ上に GUI の画面が表示されます*10 。後はマルや四角や矢印 を適宜置いていくだけです。この講義資料の上ではそこまで表示できないので,ぜひ手元 で試してみてください。 lavaangui を開く 1 2 3 4 5 # インストールがまだの人は # install.packages("lavaangui") library(lavaangui) # ブラウザでGUIでモデル式を作る lavaangui() 2 つ目の機能は,cfa() や sem() 関数で推定した結果を図示する機能です。lavaangui パッケージの強みは,表示された図をグリグリ動かせる点です。つまり,各変数の位置を うまく調整することで,そのまま論文に載せられるレベルの図が作れるかもしれません。 推定結果をプロットする 1 2 plot_lavaan(result_sem) # あとは好きなようにいじってください。

31.

7.5 回帰分析と因子分析を組み合わせる 図 7.11: plot_lavaan(result_sem) を少しいじってみた結果 実際に弄ってみると分かりますが,各要素の色やフォントサイズなどは一つ一つ自由に変 更可能です。また,いろいろと弄った後のものを File > Download model で保存可能な ので,あとで編集を再開するといったことも可能です。 LIGHTBULB (情報提供 2)semPlot パッケージもあるよ ​ ​ 結果のオブジェクトから自動的にパス図を作成してくれるものとしては,semPlot パッ ケージにある semPaths() という関数もあります。lavaanPlot と比べても,残念ながら そのまま論文に載せられるほど高性能ではないのですが,自分の書いたモデル式に間違い が無いかを確認したり,係数が一定以下のところを除外したときの図をさっと確認するの には使えると思います。 ( lavaanPlot は比較的新しいパッケージでまだ挙動の変更の可能性があるので,なんか うまくいかない場合のプラン B として補足的に紹介しておきます。 ) *10 ちなみにこれで表示される画面は,https://lavaangui.org/ からもアクセス可能です。 31

32.

7.5 回帰分析と因子分析を組み合わせる 32 semPaths() で簡単に作図 1 2 3 4 5 6 7 # インストールがまだの人は # install.packages("semPlot") library(semPlot) # 引数whatは「何を表示するか」,"std"にすると標準化解を出してくれる # 引数minimumは「その絶対値以下の矢印はひかない」 # 他にも大量に引数があるので色々試してみてください semPaths(result_sem, what = "std", minimum = 0.1) 0.80 0.38 0.61 1.00 1.00 Q1_1 Q1_2 Q1_3 age gnd 0.45 0.63 0.79 0.24 0.15 f_A 0.94 0.25 0.92 f_E 0.61 0.52 0.70 Q1_6 Q1_7 Q1_8 0.63 0.51 0.73 図 7.12: semPaths() による出力 7.5.1 (おまけ)SEM モデルを一つの式で表す ここまでに見てきたように,SEM は回帰分析と因子分析を内包する上位の概念です。回帰分 析も因子分析も,「被説明変数を説明変数の線形和で表現する」という点は変わらないので,こ れらがくっついたモデル(図 7.8 )であっても,これまでと同じように線形代数を使えば一つの 式で表すことができます(Adachi, 2020) 。 まず,因子分析の部分(潜在変数から観測変数に矢印が引かれている部分)だけ見てみると, これは単純な 2 因子モデルなので, (7.19) (1) 𝐲𝑝 = 𝐟𝑝 𝐁(1) + 𝜺𝑝 と表すことができます。上付きの添字 (1) は,因子分析パートと回帰分析パートの 𝐁 や 𝜺 を区 別するために便宜的につけているものです。それぞれを展開すると, [𝑦𝑝1 𝑦𝑝2 𝑦𝑝3 𝑦𝑝6 𝑦𝑝7 𝑦𝑝8 ] = [𝑓𝑝A + [𝜀𝑝1 𝑏 𝑓𝑝E ] [ 11 0 𝑏21 0 𝑏31 0 𝜀𝑝2 𝜀𝑝4 𝜀𝑝5 𝜀𝑝3 0 𝑏42 0 𝑏52 𝜀𝑝6 ] 0 ] 𝑏62 (7.20)

33.

7.5 回帰分析と因子分析を組み合わせる 33 となります。同様に,回帰分析の部分は, (7.21) (2) 𝑓𝑝E = 𝑓𝑝A 𝑏A + 𝜺𝑝 となります。ここで,因子分析の表現に合わせるため,式の左辺にすべての潜在変数が登場する ように少し式を書き換えます。具体的には { 𝑓𝑝A = 𝑓𝑝A (7.22) 𝑓𝑝E = 𝑓𝑝A 𝑏A +𝜀𝑝A という連立方程式を用意し,これを行列によって [𝑓𝑝A 𝑓𝑝E ] = [𝑓𝑝A (2) ⟶ 𝐟𝑝 = 𝐟𝑝 𝐁 𝑓𝑝E ] [ 0 0 𝑏A ] + [𝑓𝑝A 0 𝜀𝑝A ] (7.23) (2) + 𝜺𝑝 と表現します。 これで準備は完了です。あとは (7.20) 式と (7.23) 式をうまく組み合わせると, [𝐟𝑝 𝐲𝑝 ] = [𝐟𝑝 𝐲𝑝 ] [ 𝐁(1) 𝟎 𝐁(2) ] + [𝜺(1) 𝑝 𝟎 (2) 𝜺𝑝 ] (7.24) ⟶ 𝐯 𝑝 = 𝐯 𝑝 𝐁 + 𝜺𝑝 となります。回帰係数行列の 𝟎 は,今回のモデルでは 𝑦 から 𝑓 への回帰や 𝑦 同士の回帰は一つも 無いため,ゼロ行列を置いています。もしも 𝑦 同士の回帰などがあれば,それに応じて係数を入 れる必要があります。とにかく,これによってすべての(観測・潜在)変数同士の回帰分析のモ デルを統一的に表すことができました。 ちなみに展開すると横長になりすぎてかなり見にくいですが,一応 [𝑓𝑝A 𝑓𝑝E 𝑦𝑝1 𝑦𝑝2 𝑦𝑝3 𝑦𝑝6 𝑦𝑝7 𝑦𝑝8 ] = 0 ⎡0 ⎢ ⎢0 ⎢0 [𝑓𝑝A 𝑓𝑝E 𝑦𝑝1 𝑦𝑝2 𝑦𝑝3 𝑦𝑝6 𝑦𝑝7 𝑦𝑝8 ] ⎢ 0 ⎢ ⎢0 ⎢0 ⎣0 + [𝑓𝑝A 𝜀𝑝A 𝜀𝑝1 𝜀𝑝2 𝜀𝑝3 𝜀𝑝4 𝜀𝑝5 𝜀𝑝6 ] 𝑏A 0 0 0 0 0 0 0 𝑏11 0 0 0 0 0 0 0 𝑏21 0 0 0 0 0 0 0 𝑏31 0 0 0 0 0 0 0 0 𝑏42 0 0 0 0 0 0 0 𝑏52 0 0 0 0 0 0 0 𝑏62 ⎤ ⎥ 0⎥ 0⎥ 0⎥ ⎥ 0⎥ 0⎥ 0⎦ (7.25) という形をしています。 あとは (7.24) 式を,左辺が 𝐲 のみになるように変形していくだけです。 (𝑇 + 𝐼) 単位行列 𝐈(𝑇 +𝐼) を用いると 𝐯𝑝 𝐈(𝑇 +𝐼) = 𝐯𝑝 𝐁 + 𝜺𝑝 (7.26)

34.

7.6 モデルの適合度 34 と表せるので,𝐯𝑝 𝐁 を移項させてから両辺に逆行列をかけると (7.27) 𝐯𝑝 = 𝜺𝑝 (𝐈(𝑇 +𝐼) − 𝐁)−1 と変形させることができます。ここで, 𝐯𝑝 = [𝐟𝑝 (7.28) 𝐲𝑝 ] であることを踏まえると,𝐯𝑝 のうち 𝐟𝑝 に当たる部分が 0 になったものが 𝐲𝑝 なので,(𝑇 × 𝑇 ) のゼロ行列 𝟎(𝑇 ) と,(𝐼 × 𝐼) の単位行列 𝐈(𝐼) を縦に並べた行列 𝐇 を使って, 𝐲𝑝 = [𝐟𝑝 𝟎 𝐲𝑝 ] [ (𝑇 ) ] 𝐈(𝐼) (7.29) = 𝐯𝑝 𝐇 と表せます。あとは,これに (7.27) 式を代入することで, (7.30) 𝐲𝑝 = 𝜺𝑝 (𝐈(𝑇 +𝐼) − 𝐁)−1 𝐇 という形で,どんな SEM モデルであっても,すべての観測変数をすべてのパラメータの関数で 表す一般化が完成しました。 7.6 モデルの適合度 ここまで,いくつかの簡単なモデルで SEM の基本的な仕組みを紹介しました。SEM の目的 はなるべく少ないモデルパラメータによってデータの共分散行列に近い値を再現することです。 データ(の共分散行列 𝐒)に対するモデル(の共分散行列 𝚺)の当てはまりの程度を表す指標を (モデルの)適合度と呼び,その指標には様々な種類があります。以下でいくつかの代表的な指標 を紹介します。これらは,どれか一つ・一種類の指標を使えば OK というものではありません。 様々な視点からの評価を行い,総合的にモデルの適合度を判定するようにしましょう。適合度指 標に関する議論は,星野 他(2005)あたりが詳しいです。 7.6.1 相対的指標 相対的指標では, 「最悪のモデル」と比べてどの程度当てはまりが改善したかを考えます。ここ での「最悪のモデル」とは,全ての変数が完全に無相関だと仮定したモデルです。例えば 図 7.6 のパス解析で考えると,このモデルには計 4 個の観測変数が登場するので,「最悪のモデル」は 図 7.13 のような状態です。 何もないということは,モデル上の相関行列 𝚺0 は 𝜎𝑥2 ⎡ 0age 𝚺0 = ⎢ ⎢ 0 ⎣ 0 𝜎𝑥2 gender 0 0 𝜎𝑥2 𝐴 0 ⎤ ⎥ ⎥ 𝜎𝑥2 𝐸 ⎦ (7.31)

35.

7.6 モデルの適合度 35 図 7.13: 共分散がなにもない(ヌル)モデル ということです。もちろんこれ以上当てはまりの悪いモデルは考えられません。ということ で,相対的指標ではこの独立モデル(ヌルモデル)と比べて,設定したモデルではどの程度当て はまりが改善したかを確認します*11 。ここで用いる「当てはまり」の指標は,最尤推定の場合は 尤度を元に設定します。分析者が設定した仮説モデルに関する当てはまりの指標 𝐿ℎ は 𝐿ℎ = (𝑃 − 1) {tr(𝚺−1 𝐒) − log |𝚺−1 𝐒| − 𝐼} (7.32) となります。この式は,最尤推定量におけるモデルの尤度(波括弧の中身)を 𝑃 − 1 倍したもの なのですが,細かい式の意味や導出はともかく,この値が「データにおける観測された共分散行 列 𝐒」と「仮説モデルの共分散行列 𝚺」の比(𝚺−1 𝐒)に基づく値だということだけ理解してお いてください。つまりこの値は 𝚺 と 𝐒 の値が近くなるほど小さな値を取る,いわば乖離度のよ うなものを表しています*12 。そして同様に,独立モデルでの当てはまりの指標 𝐿0 を −1 𝐿0 = (𝑃 − 1) {tr(𝚺−1 0 𝐒) − log |𝚺0 𝐒| − 𝐼} (7.33) とします。相対的指標では,この 𝐿ℎ と 𝐿0 を比較していきます。 相対的指標でよく用いられている指標の一つは,TLI(Tucker-Lewis index: Tucker & Lewis, 1973)でしょう。 TLI = 𝐿0 𝐿ℎ 𝑑𝑓0 − 𝑑𝑓ℎ 𝐿0 𝑑𝑓0 − 1 (7.34) 𝑑𝑓ℎ と 𝑑𝑓0 はそれぞれ仮説モデルと独立モデルでの自由度です。自由度はデータの分散共分散 の総数( 𝐼(𝐼+1) )からパラメータ数を引いた数になります。例えば 図 7.6 のモデルでは,4 つの 2 観測変数から計算できる分散(4 個)と共分散(4 C2 = 6 個)の総数 10 個を 8 つのモデルパラ メータで表現しました。そのため自由度は 𝑑𝑓ℎ = 2 となります。本来データの分散共分散は 10 個あったのに,8 個だけでそれを再現したという意味では,自由度は「何個のパラメータを削減 しているか」という見方もできそうです。 あらためて TLI の式を見てみます。 𝑑𝑓0 は独立モデルでの乖離度です。削減したパラメータ 1 𝐿 0 *11 独立モデルとは反対に,全ての観測変数間に両方向の矢印を引いたモデル(共分散を独立に推定するモデル)の ことを飽和モデル(フルモデル)と呼びます。わざわざ飽和モデルを SEM で実行する必要はまったくないので すが「全てのモデルは独立モデルと飽和モデルの間に位置している」という感覚は持っておくと良いかもしれま せん。 *12 もう少し詳しく説明すると,𝐿 は「対立仮説を飽和モデルとしたときの 𝚺 の尤度比検定統計量」になっていま ℎ す。尤度比検定では,𝐿ℎ つまり乖離度が大きい場合には対立仮説が採択されるため,「いま考えているモデル 𝚺 よりは飽和モデルが真のモデル構造と考えられる」となります。

36.

7.6 モデルの適合度 36 個につきどの程度のズレが発生したかを表しています*13 。これに対して, 𝑑𝑓ℎ は仮説モデルでの 𝐿 ℎ 乖離度です。あってもなくても良いパラメータは削減しても大きなズレは発生しないですが,重 要なパラメータを削減すると大きなズレが発生します。ズレの大きさをパラメータ数で割ること で,「(ヌルモデルから)追加したパラメータ数の割に当てはまりが改善したか」を評価している わけですね。 似たような指標に CFI(Comparative fit index: Bentler, 1990)があり,これもよく用いら れています。 CFI = 1 − max(𝐿ℎ − 𝑑𝑓ℎ , 0) max(𝐿ℎ − 𝑑𝑓ℎ , 𝐿0 − 𝑑𝑓0 , 0) (7.35) CFI では乖離度 𝐿ℎ から自由度 𝑑𝑓ℎ を引いています。が,あとは大体同じです。分母の方の max 関数では,普通は最も乖離度の大きい 𝐿0 − 𝑑𝑓0 が選ばれるはずです。そうなると CFI = 1 − 𝐿ℎ − 𝑑𝑓ℎ 𝐿0 − 𝑑𝑓0 (7.36) となり,仮説モデルにおける当てはまりの改善度を表していることがよくわかります。 TLI や CFI は 1 に近いほど良い指標です。一般的には 0.9 くらいはほしいだの 0.95 あると嬉 しいだの言われています。しかし 𝐿ℎ は 𝚺 と 𝐒 のズレの大きさに規定されている以上,基本的 にはパラメータ数を増やすほど値が改善していくという点には注意が必要です。 7.6.2 絶対的指標 データの相関行列 𝐒 とモデルの相関行列 𝚺 の要素レベルでのズレを (7.37) 𝐄=𝚺−𝐒 と表すと,適合度の指標として 𝐄 の部分がどれだけ小さいかという発想が自然に出てきます。例 えば 図 7.6 のパス解析では, 𝐄=𝚺−𝐒 120.254 ⎡ 0.204 0.221 =⎢ ⎢ 8.902 0.432 0.238 ⎣ 4.892 20.685 11.354 0 ⎡ 0 0 =⎢ ⎢−0.004 −0.001 0.018 ⎣ 0.694 −0.022 −0.005 120.254 ⎤ ⎡ 0.204 0.221 ⎥+⎢ ⎥ ⎢ 8.906 0.433 28.395⎦ ⎣ 4.198 0.260 20.667 11.359 ⎤ ⎥ ⎥ 28.407⎦ ⎤ ⎥ ⎥ −0.012⎦ という関係になっています。ここから適合度を単純に考えると,例えば 𝐄 の成分の平均のような ものを計算すると良さそうです。この指標を RMR (root mean-squared residual) と呼び,式と *13 ちなみに 𝐿 ℎ や 𝐿0 を 𝑃 − 1 で割ったものの期待値は,対応する自由度に一致することが知られています。つ まり,自由度が小さいほど=パラメータ数が多いほどズレの期待値は当然のように小さくなるわけです。

37.

7.6 モデルの適合度 37 しては √ 𝐼 𝐼 √ 2 RMR = √ ∑ ∑(𝜎𝑖𝑗 − 𝑠𝑖𝑗 )2 𝐼(𝐼 − 1) 𝑖=1 𝑗=1 ⎷ (7.38) と表されます。ここで 𝜎𝑖𝑗 , 𝑠𝑖𝑗 はそれぞれ 𝚺, 𝐒 の (𝑖, 𝑗) 成分の値を意味しています。しかし, RMR は変数のスケールの影響を受けてしまいます。例えば全ての変数の値を 10 倍(=分散は 100 倍)にしたとしたら,𝐒 と 𝚺 の各要素の値は単純に 100 倍されてしまうため,𝐄 の平均であ る RMR も 100 倍になってしまいます。 これでは基準を決められないので, RMR を標準化することで生まれたのが SRMR(stan- dardized RMR: Hu & Bentler, 1999)です。標準化の仕方は,「共分散から相関係数を導出する 時」と同様にすることで, √ 𝐼 𝐼 𝜎𝑖𝑗 − 𝑠𝑖𝑗 2 √ 2 SRMR = √ ∑∑( ) 𝐼(𝐼 − 1) 𝑖=1 𝑗=1 𝑠𝑖𝑖 𝑠𝑗𝑗 ⎷ (7.39) と定式化されます。 SRMR の他にもよく使われる指標としては,GFI(Goodness of fit index: Bentler, 1983)が あります。これも基本的な考え方は同じで,𝐒 と 𝚺 の各要素の値が近いほど良くなります。 GFI = 1 − =1− 𝑡𝑟 [(𝐒 − 𝚺)2 ] 𝑡𝑟[𝐒2 ] ∑𝐼𝑖=1 ∑𝑖𝑗=1 (𝑠𝑖𝑗 − 𝜎𝑖𝑗 )2 𝐼 (7.40) 𝑖 ∑𝑖=1 ∑𝑗=1 𝑠2𝑖𝑗 SRMR や GFI は,回帰分析の決定係数や因子分析の分散説明率のようなもので,パラメータ の数が多いほど値は改善していきます。因子分析の分散説明率では「最低限これくらいは欲し い」といった考え方を紹介しました。その観点ではこれらの指標は役に立ちます。例えば SRMR では 0.08 や 0.05 以下くらいだと良いと言われていたり,GFI や後述する AGFI は 0.95 以上だ と良いと言われていたりします(Hancock et al., 2019; 豊田,2014) 。ですが SEM の目的は「な るべく少ないパラメータで」達成したいところです。そう考えると,これらの指標だけを用いて いると少し問題があるわけです。 ちなみに,GFI には自由度で調整した AGFI(Adjusted GFI) というものがあります。 AGFI = 1 − 𝐼(𝐼 + 1) 1 (1 − GFI) 2 𝑑𝑓 (7.41) これは,自由度調整済み決定係数のような感じで,推定するパラメータ数が多くなるほど相関行 列の乖離度 (1 − GFI) を過大評価するような調整がされているわけです。 7.6.3 倹約的指標 データへの当てはまりは良いほど嬉しいのですが,「なるべく少ないパラメータで」を満たす ために,先ほど紹介した AGFI のように推定するパラメータ数を考慮した適合度指標を考えま

38.

7.6 モデルの適合度 38 す。このクラスで多分最もよく用いられているのが RMSEA(Root Mean Square error of approximation: Steiger & Lind, 1980)です。 RMSEA = √max ( 𝐿ℎ 1 − , 0) 𝑑𝑓ℎ 𝑃 −1 (7.42) 𝐿ℎ TLI のところでも登場した 𝑑𝑓 は「削減したパラメータ 1 個あたりの乖離度の大きさ」の指標で ℎ す。したがって,乖離度 𝐿ℎ が同じであれば,パラメータ数が少ない=自由度が大きいほど良い 値になります。RMSEA に関しては,0.05 を下回っていると良いとか,90% 信頼区間が 0.1 を含 まないと良いなどと言われています。 倹約的指標には,他にも PGFI(parsimonious GFI: Mulaik et al., 1989)といったものもあ ります。 𝑑𝑓ℎ PGFI = 𝐼(𝐼−1) GFI (7.43) 2 ただ,PGFI はシンプルなモデルでは変動が大きすぎることがあります。例えば図 7.6 のモデル 2 では,10 個の分散共分散を 8 個のパラメータで説明していましたが,この場合 𝑃 𝐺𝐹 𝐼 = 10 𝐺𝐹 𝐼 となり,GFI の 5 分の 1 になってしまいます。独立モデルだったとしても各変数の分散パラメー 6 タは必ず存在しているため,𝑃 𝐺𝐹 𝐼 = 10 𝐺𝐹 𝐼 となります。ということで,PGFI と同様の補正 がかかる倹約的指標では,どの程度の値なら十分かを明確に決めづらいためあまり使われること はない印象があります。 7.6.4 モデル比較の指標 適合度指標とは少し異なりますが,パラメータ数の割に当てはまりの良いモデルを選ぶための 指標として情報量規準というものがあります。代表的な情報量規準には AIC = 𝐿ℎ − 2𝑑𝑓ℎ BIC = 𝐿ℎ − log(𝑃 )𝑑𝑓ℎ (7.44) などがあります(Akaike, 1969/1998–1969; Schwarz, 1978) 。式からわかるように,パラメー タ数が多くなるほど第 2 項の値が小さくなり,結果的に情報量規準の値が大きくなってしまい ます。 情報量規準には絶対的な基準はありません。単体のモデルに対する値を見て一喜一憂するもの ではなく,複数のモデルにおける値を比較してより小さい方を選ぶためのものです。 一般的に,乖離度 𝐿ℎ はサンプルサイズが大きくなるほど大きな値になりやすいものです。 AIC ではパラメータを 1 つ追加した際のペナルティがサンプルサイズによらず 2 のため,サンプ ルサイズが大きくなるほど「パラメータを追加したことによる当てはまりの改善」のほうが「パ ラメータを追加したことによるペナルティ」よりも大きくなりやすく,結果的にパラメータ数の 多いモデルを選びやすくなる,という性質があったりします。また 2 つのモデルでの値の差がわ ずかな場合には,標本誤差によって大小関係が変わりうるため,単一の情報量規準だけを用いて モデルを選択するのは危険なときがあるかもしれません。少しだけ注意しましょう。

39.

7.6 モデルの適合度 39 7.6.5 確認してみよう それでは,これまでに紹介したものを含めた様々な適合度指標を lavaan で出してみましょ う。fitmeasures() 関数を使うと簡単に出すことが出来ます*14 。 適合度指標を出す 1 fitmeasures(result_sem) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 npar fmin 18.000 0.027 df pvalue 18.000 0.000 baseline.df baseline.pvalue 28.000 0.000 tli nnfi 0.925 0.925 nfi pnfi 0.945 0.607 rni logl 0.952 -34146.289 aic bic 68328.579 68432.915 bic2 rmsea 68375.725 0.050 rmsea.ci.upper rmsea.ci.level 0.059 0.900 rmsea.close.h0 rmsea.notclose.pvalue 0.050 0.000 rmr rmr_nomean 0.308 0.308 srmr_bentler srmr_bentler_nomean 0.036 0.036 crmr_nomean srmr_mplus 0.041 0.036 cn_05 cn_01 544.308 656.021 agfi pgfi 0.974 0.494 ecvi 0.068 chisq 129.227 baseline.chisq 2331.678 cfi 0.952 rfi 0.914 ifi 0.952 unrestricted.logl -34081.676 ntotal 2432.000 rmsea.ci.lower 0.042 rmsea.pvalue 0.450 rmsea.notclose.h0 0.080 srmr 0.036 crmr 0.041 srmr_mplus_nomean 0.036 gfi 0.987 mfi 0.977 これまでに紹介したもの以外にも色々出ていますが,とりあえず先ほど紹介したものに関する 指標だけ説明すると *14 summary() に引数 fit = TRUE を与えても良いのですが,この方法だと一部の適合度指標しか出してくれま せん。

40.

7.6 モデルの適合度 40 表 7.1: fitmeasures() 関数で表示される適合度指標の一部 指標名 解説 chisq 𝜒2 統計量(𝐿ℎ ) df 自由度(𝑑𝑓ℎ ) pvalue 𝜒2 検定の 𝑝 値 baseline.*** 独立モデルでの値(𝐿0 , 𝑑𝑓0 ) cfi CFI aic AIC bic BIC rmsea RMSEA rmsea.ci.lower RMSEA の 90% 信頼区間の下限 rmsea.ci.upper RMSEA の 90% 信頼区間の上限 rmsea.pvalue 「RMSEA が 0.05 以下」という帰無仮説に対する 𝑝 値 srmr SRMR gfi GFI agfi AGFI pgfi PGFI といった感じです。 では実際に複数のモデルを比較して,各適合度指標の挙動を確認してみましょう。ここでは, 「正しい」モデルとして 図 7.3 の「本来の 2 因子モデル」を例として,これに「余計な矢印が入っ た 2 因子モデル」 ( 「正しくない」モデル)と比較してみましょう。まずは 2 つのモデルそれぞれ についてパラメータ推定を行います。 2 つのモデルを比較 1 2 3 4 5 6 7 model1 <- " # 本来の2因子モデル f_1 =~ Q1_1 + Q1_2 + Q1_3 f_2 =~ Q1_6 + Q1_7 + Q1_8 " model2 <- " # 余計なものが入っている 8 f_1 =~ Q1_1 + Q1_2 + Q1_3 + Q1_6 9 10 11 12 13 f_2 =~ Q1_6 + Q1_7 + Q1_8 " result1 <- cfa(model1, data = dat) result2 <- cfa(model2, data = dat) 続 い て 2 つ の モ デ ル の 適 合 度 を 比 較 し て い き ま し ょ う。 と は い え, 一 つ 一 つ

41.
[beta]
7.6 モデルの適合度

41

fitmeasures() し て 出 力 を 見 比 べ る の は 大 変 な の で, 複 数 の モ デ ル の 適 合 度 を 並 べ て く
れる semTools::compareFit() という関数を使ってみます。

semTools::compareFit(): 複数のモデルの適合度を比較する
1
2
3
4
5

# インストールがまだの人は
# install.packages("semTools")
library(semTools)
# summary()にかけないと中身がみえない
summary(compareFit(result1, result2))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

################### Nested Model Comparison #########################
Chi-Squared Difference Test

result2
result1
---

Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
7 46682 46764 57.197
8 46685 46761 62.062
4.8642 0.039861
1
0.02742 *

Signif. codes:

0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

####################### Model Fit Indices ###########################
chisq df pvalue rmsea
cfi
tli
srmr
aic
result2 57.197† 7
.000 .054 .976† .949 .033† 46682.454†
result1 62.061
8
.000 .053† .974 .952† .035
46685.319
bic
result2 46763.605
result1 46760.673†
################## Differences in Fit Indices #######################
df rmsea
cfi
tli srmr
aic
bic
result1 - result2 1 -0.002 -0.002 0.003 0.002 2.864 -2.932

最初の Nested Model Comparison というところは,ネストされたモデル間での比較です。
今回の例の場合,result1 のモデルは,result2 のモデルで f_1 =~ Q1_6 の値が 0 になった場
合という意味で,result2 の特殊なケースといえます。このように,あるモデルが別のモデルに
内包されているとき,そのモデルは「ネスト」の関係にあると呼んだりします。
ネストされたたモデル間の比較では,尤度比検定を行うことができます。ネストされたモデル
では,パラメータ数の減少に伴い少なからずデータに対する当てはまりが悪化(尤度が減少)し
ているはずですが,もしも尤度比検定が有意にならない場合,その当てはまりの悪化が「減ら
したパラメータ数的に許容できる」という感じになり,それならばより節約的なモデルを選ぼ
う,という流れになります。今回の場合,Pr(>Chisq) が 0.05 より小さいため検定は有意になっ
ています。result2 を基準に見ると result1 のモデルは f_1 =~ Q1_6 のパスを 0 にしたこと

42.
[beta]
7.6 モデルの適合度

42

によって当てはまりが有意に悪化している,ということです。したがって,尤度比検定的には

result2 を選ぶべし,となります。しかしこれも例によって統計的仮説検定あるあるの「サンプ
ルサイズが大きいと有意になりやすい」があるので,これだけを信じすぎないほうが良いと思い
ます。
その下の Model Fit Indices では各種適合度指標を並べてくれています。ダガー( †)の
付いているものは,その適合度指標においてベストなモデル,という意味です。また一番下の

Differences in Fit Indices は読んで字のごとく適合度指標の差分です。僅かな差ですが,
RMSEA や TLI の値は f_1 =~ Q1_6 のパスが無い(本来正しい)モデルの方が良い値です。一
方で絶対的指標である CFI や SRMR は result2 のほうが良い値になっています。
情報量規準を見ると,AIC はモデル 2,BIC はモデル 1 のほうが大きな値になっています。先
程説明したように,AIC のほうがサンプルサイズが大きくなるほど複雑な(パラメータ数の多
い)モデルを好む傾向があり,今回の比較でもその傾向が表れたということです。
このように,適合度指標の定義によってモデル比較の結果も一貫しないことが大半なので,結
果を報告する際には複数の指標を提示し,総合的に判断する必要があるわけです。

compareFit() 関数は,デフォルトでは上に表示されているいくつかの指標のみを表示する
様になっています。この Section で紹介した他の適合度指標についても比較してほしい場合に
は,引数を設定する必要があります。
表示する適合度指標を選ぶ
1
2

# summary()の引数としてのfit.measuresです
summary(compareFit(result1, result2), fit.measures = c("gfi", "agfi",
"rmsea.pvalue"))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

################### Nested Model Comparison #########################
Chi-Squared Difference Test

result2
result1

Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
7 46682 46764 57.197
8 46685 46761 62.062
4.8642 0.039861
1
0.02742 *

--Signif. codes:

0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

####################### Model Fit Indices ###########################
gfi
agfi rmsea.pvalue
result2 .992† .977
.271†
result1 .992 .978†
.333
################## Differences in Fit Indices #######################
gfi agfi
result1 - result2 -0.001 0.001

43.

7.6 モデルの適合度 引数 fit.measures に指定できるのは,fitmeasures() 関数で表示されるものの名前です。 そして実は fitmeasures() 関数自体も同じ引数 fit.measures を受け付けるので,同様に一 部の指標のみを表示したい場合には設定してあげると良いでしょう。 INFO (おまけ)適合度指標の関係 図 7.14 に,各種適合度指標の関係を表してみました。無理やり 1 つの図にまとめたので 多少変なところがあるかもしれませんが… • 相対的指標は「独立モデルを0,飽和モデルを1」としたときの仮説モデルの位置 づけを表しています。 • 絶対的指標は「飽和モデル=データ」からのズレを表す指標です。理論上はたぶん 下限は決まっていませんが,基本的に0から1の範囲内に収まるはずです。 • 倹約的指標はものによります。自由度で調整した値です。 • 情報量規準は独立モデル・飽和モデルと何の関係もありません。尤度を自由度で調 整しただけです。図の例では,モデル B のほうが絶対的な当てはまりは良いのです が,自由度による調整の結果情報量規準の値はモデル A のほうが良い,という状態 を表しています。 43

44.

7.7 モデルの修正 44 図 7.14: 適合度指標の関係 7.7 モデルの修正 (ここからはプラクティカルな話題です。 ) SEM では,まずドメイン知識に基づいた仮説を立てて,その仮説をモデルを落とし込んでいく (パス図に線を引く)ことになります。そして,実際のデータと仮説モデルとで共分散行列がど の程度ずれているかを評価し,ズレが小さければ「問題ないモデル」と判断します。ズレの大き さを評価する適合度指標には,大きく分けると「絶対的なズレの大きさを評価するもの(SRMR や GFI など) 」と「パラメータ数(自由度)を考慮して評価するもの(AGFI や RMSEA) 」の 2 種類がありました。

45.

7.7 モデルの修正 45 もしも仮説モデルにおいて適合度指標の値が悪ければ,モデルを修正してデータとの整合性 and/or モデルの倹約度を高める必要があります。データとの整合性を高めるためには,矢印を 追加してあげれば良いです。矢印を追加するということは推定するパラメータが増えるため,回 帰分析の説明変数や因子分析の因子数を増やした時と同じように,パラメータを増やした分だけ データとモデルのズレは小さくできるはずです。一方,モデルの倹約度を高めるためには矢印を 消去する必要もあります。ある矢印が,あってもなくてもデータとモデルのズレに大きな影響を 与えないのであれば,そのような矢印はなくなったほうが RMSEA などは向上するはずです。 ということで,この節ではモデルを修正してデータとの整合性を高めるための方法について説 明します。手当たり次第にひとつひとつ矢印を足したり引いたりしたモデルを試しまくるのはさ すがに効率が悪いので,もう少しスマートに修正案にアタリをつけたいと思います。以降では, 図 7.8 の SEM モデルを題材にモデルの修正を試してみます。 まずはベースモデルの推定 1 2 3 4 5 6 7 8 9 10 model1 <- " f_A =~ Q1_1 + Q1_2 + Q1_3 f_E =~ Q1_6 + Q1_7 + Q1_8 f_A ~ age + gender f_E ~ f_A age ~~ gender " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 lavaan 0.6-18 ended normally after 36 iterations result1 <- sem(model1, data = dat, std.lv = TRUE) summary(result1, standardized = TRUE) Estimator Optimization method Number of model parameters Number of observations ML NLMINB 18 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 129.227 18 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured

46.

7.7 モデルの修正 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 46 Latent Variables: Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.602 0.888 0.786 0.031 0.030 0.030 19.255 29.426 25.796 0.000 0.000 0.000 0.628 0.926 0.819 0.447 0.790 0.627 0.728 0.888 0.651 0.031 0.035 0.031 23.767 25.607 21.262 0.000 0.000 0.000 0.753 0.918 0.673 0.611 0.698 0.523 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.014 0.522 0.002 0.053 6.275 9.894 0.000 0.000 0.013 0.501 0.147 0.236 0.252 0.030 8.402 0.000 0.254 0.254 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.204 0.105 1.945 0.052 0.204 0.039 Estimate 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 1.000 1.000 Std.Err 0.051 0.046 0.046 0.043 0.055 0.044 3.449 0.006 z-value 31.144 11.273 22.666 22.240 16.228 27.533 34.871 34.871 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 0.920 0.935 Std.all 0.801 0.376 0.607 0.626 0.513 0.727 1.000 1.000 0.920 0.935 f_A =~ Q1_1 Q1_2 Q1_3 f_E =~ Q1_6 Q1_7 Q1_8 Regressions: f_A ~ age gender f_E ~ f_A Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_E 適合度はすでにかなり良いんですが… 1 fitmeasures(result1) 1 2 3 npar 18.000 df fmin 0.027 pvalue chisq 129.227 baseline.chisq

47.

7.7 モデルの修正 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 18.000 0.000 baseline.df baseline.pvalue 28.000 0.000 tli nnfi 0.925 0.925 nfi pnfi 0.945 0.607 rni logl 0.952 -34146.289 aic bic 68328.579 68432.915 bic2 rmsea 68375.725 0.050 rmsea.ci.upper rmsea.ci.level 0.059 0.900 rmsea.close.h0 rmsea.notclose.pvalue 0.050 0.000 rmr rmr_nomean 0.308 0.308 srmr_bentler srmr_bentler_nomean 0.036 0.036 crmr_nomean srmr_mplus 0.041 0.036 cn_05 cn_01 544.308 656.021 agfi pgfi 0.974 0.494 ecvi 0.068 47 2331.678 cfi 0.952 rfi 0.914 ifi 0.952 unrestricted.logl -34081.676 ntotal 2432.000 rmsea.ci.lower 0.042 rmsea.pvalue 0.450 rmsea.notclose.h0 0.080 srmr 0.036 crmr 0.041 srmr_mplus_nomean 0.036 gfi 0.987 mfi 0.977 7.7.1 不要なパスを消す 普通に考えると年齢 age と性別 gender は無相関だと考えるのが自然ですね。先程の分析の結 果を見ても,共分散 age ~~ gender の検定結果は有意にはなっていません。summary(sem()) で出力される検定では,帰無仮説に「そのパラメータの母数が 0 に等しい」を設定した Wald 検 定の結果を出しています。Wald 検定の中身はともかく,とりあえずこの P(>|z|) 列を見れば, そのパラメータを削除してよいかにアタリをつけられそうかが分かります。 ということで,検定結果が有意ではなかった age ~~ gender の共分散をゼロに固定して再度 推定してみましょう。 パラメータを制約する 1 2 model2 <- " f_A =~ Q1_1 + Q1_2 + Q1_3

48.
[beta]
7.7 モデルの修正

48

3
4
5

f_E =~ Q1_6 + Q1_7 + Q1_8
f_A ~ age + gender
f_E ~ f_A

6

age ~~ 0 * gender

7

"

lavaan の記法では,このように右辺の変数名の前に 0*を付けると,そのパラメータの値を 0
に固定することが出来ます*15 。
修正後のモデルで再度推定
1
2

result2 <- sem(model2, data = dat, std.lv = TRUE)
summary(result2, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

lavaan 0.6-18 ended normally after 30 iterations
Estimator
Optimization method
Number of model parameters

ML
NLMINB
17

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

133.020
19
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f_A =~
Q1_1
Q1_2
Q1_3
f_E =~
Q1_6
Q1_7

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.602
0.888
0.786

0.031
0.030
0.031

19.216
29.335
25.715

0.000
0.000
0.000

0.627
0.925
0.818

0.446
0.789
0.627

0.728
0.888

0.031
0.035

23.763
25.602

0.000
0.000

0.753
0.918

0.611
0.698

*15 同じように,1*としたら 1 に固定したりもできます。0 以外はあまり使い道ないかもしれませんが…

49.

7.7 モデルの修正 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 49 Q1_8 0.651 0.031 21.259 0.000 0.673 0.523 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.014 0.522 0.002 0.053 6.280 9.901 0.000 0.000 0.013 0.502 0.147 0.236 0.252 0.030 8.387 0.000 0.254 0.254 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.000 0.000 Std.lv 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 0.923 0.936 Std.all 0.801 0.377 0.607 0.626 0.513 0.727 1.000 1.000 0.923 0.936 Regressions: f_A ~ age gender f_E ~ f_A Covariances: age ~~ gender 0.000 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_E Estimate 1.581 0.517 1.034 0.950 0.889 1.205 120.254 0.221 1.000 1.000 Std.Err 0.051 0.046 0.046 0.043 0.055 0.044 3.449 0.006 z-value 31.136 11.237 22.625 22.238 16.225 27.532 34.871 34.871 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 結果を見ると,確かに共分散 age ~~ gender の値が推定されず,0 に固定されています。そ れでは,パス削除前( result1)と削除後( result2)の適合度を比較してみましょう。 修正前後で適合度を比較 1 summary(compareFit(result1, result2)) 1 2 3 4 5 6 7 8 9 10 ################### Nested Model Comparison ######################### Chi-Squared Difference Test Df AIC BIC Chisq Chisq diff RMSEA Df diff Pr(>Chisq) result1 18 68329 68433 129.23 result2 19 68330 68429 133.02 3.7929 0.033888 1 0.05147 . --Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

50.

7.7 モデルの修正 11 12 13 14 15 16 17 18 19 20 21 22 50 ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result1 129.227† 18 .000 .050 .952† .925 .036† 68328.579† result2 133.020 19 .000 .050† .951 .927† .037 68330.371 bic result1 68432.915 result2 68428.911† ################## Differences in Fit Indices ####################### df rmsea cfi tli srmr aic bic result2 - result1 1 -0.001 -0.001 0.002 0.001 1.793 -4.004 い ま 比 較 し て い る 2 つ の モ デ ル の う ち result2 の モ デ ル は, result1 の モ デ ル で age ~~ gender の値が 0 になった場合という意味で,result1 の特殊なケースといえます。と いうことで尤度比検定の結果が出力されています。今回の場合,Pr(>Chisq) が 0.05 より大きい ため検定は(ギリギリ)有意になっていません。したがって,尤度比検定的にはパラメータを 1 つ削除しても当てはまりは有意には悪化していない,そのためより節約的な result2 を選ぼう, ということになるわけです。 続いて各種適合度指標を見ると,僅かな差ですが,RMSEA や TLI の値は改善しているよう です。一方で絶対的指標である SRMR は悪化しているようですね。 このように,単一のパスを削除する場合には,cfa() や sem() の結果の検定のところを見る のが第一歩です。ですが,統計的仮説検定の枠組みの中にあるため,サンプルサイズの影響を受 けてしまう点は注意が必要です。例えば先程の分析を,サンプルサイズを 100 人にして行うと, さっきは有意だった f_A ~ age の回帰係数も有意ではなくなってしまいます。検定の結果だけ を鵜呑みにするのではなく,例えば実際の推定値の大きさを踏まえて決定するなどの対応が必要 でしょう。 サンプルサイズを減らしてみると 1 2 result1_100 <- sem(model1, data = dat[1:100, ], std.lv = TRUE) summary(result1_100, standardized = TRUE) 1 2 3 4 5 6 7 8 9 lavaan 0.6-18 ended normally after 35 iterations Estimator Optimization method Number of model parameters Number of observations Model Test User Model: ML NLMINB 18 100

51.

7.7 モデルの修正 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 51 Test statistic Degrees of freedom P-value (Chi-square) 29.972 18 0.038 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 f_E =~ Q1_6 Q1_7 Q1_8 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.535 0.926 0.674 0.151 0.147 0.141 3.540 6.301 4.781 0.000 0.000 0.000 0.576 0.996 0.725 0.394 0.857 0.537 0.764 0.829 0.822 0.126 0.135 0.132 6.085 6.163 6.222 0.000 0.000 0.000 0.840 0.911 0.904 0.679 0.690 0.698 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.011 0.720 0.010 0.254 1.050 2.830 0.294 0.005 0.010 0.669 0.115 0.330 0.424 0.148 2.874 0.004 0.415 0.415 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 1.028 0.580 1.772 0.076 1.028 0.180 Estimate 1.801 0.360 1.296 0.823 0.915 0.860 133.886 0.244 1.000 Std.Err 0.273 0.234 0.225 0.172 0.197 0.190 18.934 0.034 z-value 6.606 1.535 5.769 4.788 4.647 4.533 7.071 7.071 P(>|z|) 0.000 0.125 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.801 0.360 1.296 0.823 0.915 0.860 133.886 0.244 0.864 Std.all 0.844 0.266 0.711 0.539 0.524 0.513 1.000 1.000 0.864 Regressions: f_A ~ age gender f_E ~ f_A Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A

52.

7.7 モデルの修正 56 .f_E 52 1.000 0.828 0.828 7.7.2 新しいパスを増やす 続いて,新しいパスを追加することを考えたいと思います。パスを追加する場合,基本的に絶 対的な適合度は上昇するため,先程の尤度比検定の考え方とは反対に「パラメータを 1 個追加す る価値があるだけの適合度の改善が見られる」ようなパラメータは追加してあげればよいわけで す。modificationIndices() という関数は,現状モデル内でパラメータが自由推定になってい ない全てのパス*16 について,「そこにパスを追加するとどれだけ適合度が改善するか」をまとめ て表してくれます。 修正指標 1 2 3 # 実はmodindices()でも良い # 引数sort = TRUEを与えると,改善度の大きい順に並べてくれる modificationIndices(result2, sort = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 lhs op rhs mi epc sepc.lv sepc.all sepc.nox 24 f_E =~ Q1_1 33.281 -0.196 -0.203 -0.144 -0.144 32 Q1_1 ~~ age 25.661 1.519 1.519 0.110 0.110 37 Q1_2 ~~ Q1_8 23.532 0.114 0.114 0.145 0.145 45 Q1_6 ~~ Q1_7 19.848 0.527 0.527 0.574 0.574 23 f_A =~ Q1_8 19.845 0.134 0.139 0.108 0.108 47 Q1_6 ~~ age 13.741 0.902 0.902 0.084 0.084 30 Q1_1 ~~ Q1_7 9.220 -0.092 -0.092 -0.078 -0.078 33 Q1_1 ~~ gender 9.153 0.040 0.040 0.068 0.068 26 f_E =~ Q1_3 7.717 0.087 0.089 0.069 0.069 43 Q1_3 ~~ age 6.496 -0.690 -0.690 -0.062 -0.062 50 Q1_7 ~~ age 6.371 -0.645 -0.645 -0.062 -0.062 41 Q1_3 ~~ Q1_7 5.463 0.062 0.062 0.065 0.065 [ reached 'max' / getOption("max.print") -- omitted 32 rows ] 引数 sort = TRUE を与えると,改善度(出力の一番左,mi 列)の大きい順に並べてくれます。 したがって今回の場合,一つだけパスを追加するならば f_E =~ Q1_1 というパスを追加すると 適合度が最も改善する,ということです。出力では mi 列に続いて, epc ​ ​ そのパスを自由推定にした際のパラメータの変化量の予測値。パスが引かれていない場合 は「0 からの変化量」なので推定値そのものの予測値を意味する。 sepc.lv 潜在変数 lv を標準化した際の EPC (standardized EPC)。 ​ ​ sepc.all 全ての変数を標準化した際(標準化解)の EPC。 ​ ​ *16 「自由推定になっていない」ということは,例えば 1*によって係数を 0 以外の定数に固定している場所も検討 対象にしてくれる,ということです。

53.
[beta]
7.7 モデルの修正

53

sepc.nox 観測変数の外生変数以外を全て標準化した際の EPC。
​

​

が表示されています。きっと多くの場合では mi が大きいところは sepc.all が大きくなって
いることでしょう。ということで,パスを追加する際には mi が大きいほうから試してみると良
いでしょう。さっそく f_E =~ Q1_1 を追加して推定してみます。

modindices の仰せのままに
1
2
3
4
5
6
7
8
9
10

model3 <- "
f_A =~ Q1_1 + Q1_2 + Q1_3
f_E =~ Q1_6 + Q1_7 + Q1_8 + Q1_1
f_A ~ age + gender
f_E ~ f_A
age ~~ 0*gender
"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

lavaan 0.6-18 ended normally after 31 iterations

result3 <- sem(model3, data = dat, std.lv = TRUE)
summary(result3, standardized = TRUE)

Estimator
Optimization method
Number of model parameters

ML
NLMINB
18

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

98.800
18
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f_A =~
Q1_1
Q1_2
Q1_3
f_E =~

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.678
0.867
0.792

0.034
0.029
0.030

19.682
29.957
26.483

0.000
0.000
0.000

0.707
0.904
0.826

0.503
0.772
0.633

54.

7.7 モデルの修正 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 Q1_6 Q1_7 Q1_8 Q1_1 54 0.720 0.879 0.647 -0.201 0.030 0.034 0.030 0.034 23.860 25.758 21.333 -5.875 0.000 0.000 0.000 0.000 0.752 0.918 0.675 -0.210 0.610 0.698 0.524 -0.149 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.014 0.529 0.002 0.053 6.466 9.982 0.000 0.000 0.014 0.507 0.152 0.238 0.287 0.031 9.131 0.000 0.287 0.287 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.000 0.000 Std.lv 1.514 0.555 1.021 0.952 0.889 1.202 120.254 0.221 0.920 0.918 Std.all 0.767 0.404 0.600 0.628 0.513 0.725 1.000 1.000 0.920 0.918 Regressions: f_A ~ age gender f_E ~ f_A Covariances: age ~~ gender 0.000 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_E Estimate 1.514 0.555 1.021 0.952 0.889 1.202 120.254 0.221 1.000 1.000 Std.Err 0.052 0.042 0.044 0.042 0.054 0.044 3.449 0.006 z-value 29.360 13.069 23.011 22.594 16.558 27.589 34.871 34.871 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 パス追加前( result2)と追加後( result3)の適合度を比較してみましょう。 モデル 2, 3 の適合度を比較 1 summary(compareFit(result2, result3)) 1 2 3 4 5 6 7 8 ################### Nested Model Comparison ######################### Chi-Squared Difference Test Df AIC BIC Chisq Chisq diff RMSEA Df diff Pr(>Chisq) result3 18 68298 68402 98.80 result2 19 68330 68429 133.02 34.22 0.11688 1 4.921e-09 ***

55.

7.7 モデルの修正 9 10 11 12 13 14 15 16 17 18 19 20 21 22 --Signif. codes: 55 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result3 98.800† 18 .000 .043† .965† .945† .029† 68298.151† result2 133.020 19 .000 .050 .951 .927 .037 68330.371 bic result3 68402.488† result2 68428.911 ################## Differences in Fit Indices ####################### df rmsea cfi tli srmr aic bic result2 - result3 1 0.007 -0.014 -0.018 0.008 32.22 26.424 尤度比検定の結果は有意になっています。今回は result2 のほうが節約的なモデルなので, パス追加前( result2)の方が当てはまりが有意に悪い,ということになりました。ほかの適合 度指標を見ても,どうやら確かに追加したあとの方が改善しているようです。 7.7.3 実際のところ ここまで,モデルを修正するための候補を統計的な視点から紹介しました。しかし SEM で重 要なのは,因子分析と同じようにその結果をきちんと解釈できるか(解釈可能性)です。実際に モデルを修正するかどうかは,そのパスが持つ意味をよく考えて行う必要があります。先程の修 正では,f_E =~ Q1_1 を追加したことによって図 7.15 のような状態になりました。つまり完全 な単純構造ではないと考えたほうがデータ的には当てはまりが良い,ということです。ですが修 正指標( mi)も,尤度に基づく指標です。つまりサンプルサイズが大きいほど当てはまりは大 幅に改善するように見えてしまいます。したがって,本質的には無意味なパスが手元のデータに おいては偶然それなりの改善を示しただけの可能性もあります。同様に,モデルが複雑になるほ ど自由度も大きくなり共分散構造の乖離度も大きくなりやすいと考えられます。 「 f_E =~ Q1_1 を追加すると良い」ということが,本当に「 Q1_1 が因子 E を反映した項目である」ことを示し ているのかは,実質的な意味に基づいてよく考える必要があるでしょう。 ということで,モデルの修正の際には,パスを追加・削除することが自分の仮説と照らし合わ せて受け入れられるかをよく考えるようにしましょう。 実践場面でよく見られる修正としては,図 7.16 のように独自因子の間の相関を追加するパ ターンです。例えば時系列モデルにおいて,異なる時期に聞かれた同一の項目間においたり,あ るいは DIF のように特定の属性などが影響していると言えそうな場合には妥当なパスの追加だ と思われます。このような場合にも,パスを追加する場合にはなぜそのパスを追加するべき(し ても問題ない)と考えたかをきちんと説明するようにしましょう。裏を返せば,そのパスが意味 するところが説明できないような場所には,いくら適合度が改善するにしてもパスを追加しない ほうが良いだろう,ということです。

56.

7.7 モデルの修正 56 図 7.15: より当てはまりの良いモデル。でもいいの? ホントにそれで 図 7.16: 独自因子間の相関 また,モデルの修正は割と終わりなき戦いです。というのも,modificationIndices() で出 力される mi は必ず正の値を取ります。絶対的な適合度指標と同じように,パスを追加すればす るほど当てはまりは良くなるということです。モデルの修正を行う場合には, 1. まず仮説で立てたモデルを基準として 2. もしそのままでは当てはまりが良くない(適合度指標が許容範囲を超えている)という場 合にのみ 3. もともとの仮説で受け入れられるパスの追加・削除を少しずつ行い 4. 適合度指標が許容範囲になったらその時点でストップ くらいに考えておくのが良いのではないかと思います。多くの場合は仮説で立てたモデルが (本当に考え抜いて構築されたのならば)理論的には最も整合的なはずなので,そこからあまり 変えないようにできればそれに越したことは無いわけです。適合度指標の許容範囲についてはゼ ロイチで判断できるものではないですが,自分が納得できる&査読者などを納得させられるくら いの値であれば良いでしょう。

57.

7.8 カテゴリカル変数の SEM 57 7.8 カテゴリカル変数の SEM 資料の前半で見てきたように,SEM は因子分析や回帰分析を内包する分析手法です。したがっ て,カテゴリカル変数を扱う場合も因子分析や回帰分析と同じように考えれば OK です。 7.8.1 内生変数がカテゴリカルな回帰分析・パス解析 内生変数,つまり結果変数がカテゴリカルな場合,ポリコリック相関のように,本来連続的 なものが閾値で切り分けられてカテゴリになっている,と考えると良さそうです。ここでは, 図 7.17 のように,性別と勤勉性( Q1_C)がカテゴリカルな内生変数である「学歴」に与える影 響を考える回帰分析モデルを実行してみましょう*17 。 図 7.17: 内生変数がカテゴリカルな場合 lavaan には,内生観測変数がカテゴリカルであることを示す引数 ordered が用意されてい ます。 内生変数がカテゴリカル 1 2 3 4 5 # まずは普通にモデル式を作成 model <- " education ~ gender + Q1_C " # 引数orderedに指定する 6 result <- sem(model, data = dat, ordered = "education") 7 summary(result) 1 2 3 4 5 6 7 8 lavaan 0.6-18 ended normally after 3 iterations Estimator Optimization method Number of model parameters Number of observations DWLS NLMINB 6 Used 2232 Total 2432 *17 外生変数の gender も二値のカテゴリカル変数じゃないか,と思われるかもしれませんがそこは一旦おいといて ください。

58.

7.8 カテゴリカル変数の SEM 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 58 Model Test User Model: Standard 0.000 0 Test Statistic Degrees of freedom Scaled 0.000 0 Parameter Estimates: Parameterization Standard errors Information Information saturated (h1) model Delta Robust.sem Expected Unstructured Regressions: education ~ gender Q1_C Estimate Std.Err z-value P(>|z|) 0.007 0.006 0.047 0.005 0.150 1.233 0.881 0.217 Estimate -1.217 -0.706 0.608 1.117 Std.Err 0.123 0.123 0.124 0.125 z-value -9.858 -5.757 4.914 8.961 P(>|z|) 0.000 0.000 0.000 0.000 Estimate 1.000 Std.Err z-value P(>|z|) Thresholds: education|t1 education|t2 education|t3 education|t4 Variances: .education 結果を見ると,Intercepts: と Variances: のところにある education に,潜在変数であ ることを示す . がついて .education になっています。そしてこれらの推定値がそれぞれ 0, 1 になっています。つまりこれは,education という変数の背後にある連続的なものが平均 0,分 散 1 に標準化された値として考慮されている,ということです。 そのもとで,Thresholds: のところには各カテゴリの閾値が表示されています。図 4.8 に当て はめると図 7.18 のような状態だということです。 7.8.2 (おまけ)外生変数がカテゴリカルな回帰分析・パス解析 「外生変数がカテゴリカル」ということは,回帰分析の説明変数がカテゴリカルな場合と同じ ように考えたら OK です。すなわち,その変数が二値カテゴリカルであればそのまま使用してよ く,多値カテゴリカルであればダミー変数に置き換えることで対応可能です。例えば多値カテゴ リカル変数である education を説明変数とする,図 7.19 の回帰分析モデルを考えます。 education は順序カテゴリカル変数ですが,いったん順序を無視してダミー変数へ変換して

59.

7.8 カテゴリカル変数の SEM 59 1 2 -1.217 3 4 5 0.608 -0.706 1.117 図 7.18: education の閾値 図 7.19: 外生変数がカテゴリカルな場合 みます(順序性を考慮したダミー変数化はあとで説明)。ダミー変数をデータフレームに追加す る簡単な方法として,contr.treatment() 関数を利用する方法があります*18 。 一気にダミー変数を作る 1 2 3 # ダミーコーディングの形を作る関数 # 数字はカテゴリ数 contr.treatment(5) 1 2 3 4 5 6 2 3 4 5 1 0 0 0 0 2 1 0 0 0 3 0 1 0 0 4 0 0 1 0 5 0 0 0 1 contr.treatment() 関数では第一カテゴリを基準カテゴリとしたダミー変数を作成してく れます。 ダミー変数化 1 contr.treatment(5)[dat$education, ] ​ ​ ​ ​ ​ *18 ダミー変数を作るためのパッケージとして makedummies というものもあります。こちらはデータフレーム内の factor 型変数を一気に全部ダミー変数に変えてくれるものです。用途に応じて使い分けると良いでしょう(た だ 2019 年が最終更新なので急に使えなくなるかも)。

60.
[beta]
7.8 カテゴリカル変数の SEM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

2 3 4 5
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
3
0 1 0 0
<NA> NA NA NA NA
2
1 0 0 0
<NA> NA NA NA NA
1
0 0 0 0
<NA> NA NA NA NA
<NA> NA NA NA NA
1
0 0 0 0
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
<NA> NA NA NA NA
5
0 0 0 1
2
1 0 0 0
1
0 0 0 0
3
0 1 0 0
5
0 0 0 1
[ reached getOption("max.print") -- omitted 2407 rows ]

contr.treatment() で作成したダミー行列の dat$education 行目を取る,ということは,
• education == 1 の人なら 0 0 0 0 の行
• education == 2 の人なら 1 0 0 0 の行
• education == 3 の人なら 0 1 0 0 の行
• education == 4 の人なら 0 0 1 0 の行
• education == 5 の人なら 0 0 0 1 の行
• education == NA の人なら NA NA NA NA の行
が返ってくるわけです。これをもとの dat の存在しない列名に代入してあげれば OK ですね。
1

dat[, paste0("edu_", 2:5)] <- contr.treatment(5)[dat[, "education"], ]

こうして作成したダミー変数を入れたモデルを作成して実行しましょう。

60

61.
[beta]
7.8 カテゴリカル変数の SEM

61

ダミー変数を入れて回帰モデル
1
2
3
4
5
6

# ダミー変数を一つずつ書かないといけないのがやや面倒です
model <- "
Q1_A ~ age + edu_2 + edu_3 + edu_4 + edu_5 + 1
"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

lavaan 0.6-18 ended normally after 1 iteration

summary(sem(model, data = dat))

Estimator
Optimization method
Number of model parameters

ML
NLMINB
7
Used
2232

Number of observations
Model Test User Model:
Test statistic
Degrees of freedom

0.000
0

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Regressions:
Q1_A ~
age
edu_2
edu_3
edu_4
edu_5

Estimate

Std.Err

z-value

P(>|z|)

0.068
-0.207
1.097
-0.132
0.413

0.009
0.417
0.336
0.393
0.394

7.470
-0.497
3.263
-0.337
1.046

0.000
0.619
0.001
0.736
0.295

Estimate
20.897

Std.Err
0.382

z-value
54.641

P(>|z|)
0.000

Estimate
18.842

Std.Err
0.564

z-value
33.407

P(>|z|)
0.000

Intercepts:
.Q1_A
Variances:
.Q1_A

Total
2432

62.

7.8 カテゴリカル変数の SEM 62 Number of observations のところに Total という値が追加されています。当然ですが欠 測値がある場合にはそのままだと分析が出来ないため,デフォルトでは「分析に使用する変数に 欠測が一つもない人」だけを使って分析をしているのです。今回の場合,education == NA の 人は全てのダミー変数が NA になっているので,「 education に回答している人のデータのみ」 を使用した結果となっている点には注意が必要かもしれません。 LIGHTBULB 順序カテゴリをダミー化するなら 順序カテゴリの順序性を保ったままダミー化する場合は,下の表のようにダミーの効果を 加算していく,という方法が考えられます。カテゴリ 2 では edu_2 の効果のみ,カテゴリ 3 では edu_2 + edu_3 の効果,…というようになります。そして例えば edu_3 の係数は, education == 2 の人と education == 3 の人の切片の差を表すことになるわけです。 表 7.2: 順序カテゴリのダミー変数化 ダミー education edu_2 edu_3 edu_4 edu_5 1 0 0 0 0 2 1 0 0 0 3 1 1 0 0 4 1 1 1 0 5 1 1 1 1 7.8.3 カテゴリカルな確認的因子分析 確認的因子分析の場合,モデル上は因子得点から観測変数に矢印が引かれているため,これら は全て内生変数として扱われます。したがって引数 ordered を使えば OK です。ということで, 前回行った 図 7.3 の単純構造 2 因子モデルで試してみましょう。 全ての変数を名指しで ordered=paste0("Q1_",c(1,2,3,6,7,8)) という感じで指定しても 良いのですが,もし全ての内生変数である観測変数がカテゴリの場合*19 ,ordered = TRUE と することで全てカテゴリカルになります。 カテゴリカル検証的因子分析 1 2 3 # まずは普通にモデル式を作成 model <- " f_1 =~ Q1_1 + Q1_2 + Q1_3 *19 因子得点から観測変数への回帰を含むモデルにおいて ordered = TRUE にすると,内生変数となった観測変数 も自動的にカテゴリ変数として扱われます。このように観測変数の回帰と因子分析を組み合わせた場合には意図 せぬカテゴリ化を行ってしまう可能性があるので気をつけましょう。

63.
[beta]
7.8 カテゴリカル変数の SEM

63

4
5
6
7
8

f_2 =~ Q1_6 + Q1_7 + Q1_8
"
# 引数orderedを指定する
result <- cfa(model, data = dat, std.lv = TRUE, ordered = TRUE)
summary(result, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

lavaan 0.6-18 ended normally after 14 iterations
Estimator
Optimization method
Number of model parameters

DWLS
NLMINB
37

Number of observations

2432

Model Test User Model:
Standard
72.885
8
0.000

Test Statistic
Degrees of freedom
P-value (Chi-square)
Scaling correction factor
Shift parameter
simple second-order correction

Scaled
100.302
8
0.000
0.733
0.815

Parameter Estimates:
Parameterization
Standard errors
Information
Information saturated (h1) model

Delta
Robust.sem
Expected
Unstructured

Latent Variables:
f_1 =~
Q1_1
Q1_2
Q1_3
f_2 =~
Q1_6
Q1_7
Q1_8

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.472
0.854
0.681

0.020
0.021
0.019

24.163
41.558
36.343

0.000
0.000
0.000

0.472
0.854
0.681

0.472
0.854
0.681

0.649
0.729
0.561

0.020
0.019
0.018

32.847
37.962
30.590

0.000
0.000
0.000

0.649
0.729
0.561

0.649
0.729
0.561

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.271

0.027

10.191

0.000

0.271

0.271

Covariances:
f_1 ~~
f_2

64.

7.9 多母集団同時分析 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 64 Thresholds: Estimate Std.Err z-value P(>|z|) Q1_1|t1 -1.887 0.051 -36.934 0.000 Q1_1|t2 -1.234 0.034 -36.437 0.000 Q1_1|t3 -0.743 0.028 -26.414 0.000 Q1_1|t4 -0.326 0.026 -12.588 0.000 Q1_1|t5 0.434 0.026 16.487 0.000 Q1_2|t1 -2.144 0.064 -33.743 0.000 Q1_2|t2 -1.534 0.040 -38.430 0.000 Q1_2|t3 -1.179 0.033 -35.716 0.000 Q1_2|t4 -0.478 0.027 -18.047 0.000 Q1_2|t5 0.481 0.027 18.127 0.000 Q1_3|t1 -1.829 0.049 -37.433 0.000 Q1_3|t2 -1.303 0.035 -37.181 0.000 Q1_3|t3 -0.963 0.030 -31.885 0.000 Q1_3|t4 -0.328 0.026 -12.668 0.000 [ reached getOption("max.print") -- omitted 16 rows ] Std.lv -1.887 -1.234 -0.743 -0.326 0.434 -2.144 -1.534 -1.179 -0.478 0.481 -1.829 -1.303 -0.963 -0.328 Std.all -1.887 -1.234 -0.743 -0.326 0.434 -2.144 -1.534 -1.179 -0.478 0.481 -1.829 -1.303 -0.963 -0.328 Std.lv 0.777 0.270 0.536 0.578 0.469 0.686 1.000 1.000 Std.all 0.777 0.270 0.536 0.578 0.469 0.686 1.000 1.000 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 Estimate 0.777 0.270 0.536 0.578 0.469 0.686 1.000 1.000 Std.Err z-value P(>|z|) ordered を指定せずにやった結果と比べると,因子負荷の値( Std.all 列)が少し大きく なっていることがわかります。このあたりは探索的因子分析のときと同じですね。 7.9 多母集団同時分析 分析結果の一般化可能性を高めるためには「異なる属性間で一貫して同じ結果が得られるか」 を検討するのが一つの手段となります。あるいは異なる属性・集団の間での差異に関心がある場 合にも,グループごとに分析を行い結果の一貫性を検討することが多々あります。例えば因子分 析によって得られる因子得点に関して,男性と女性で平均点に差があるか・どちらのほうが平均 点が高いかを検討したいとしましょう。SEM では多母集団同時分析という枠組みによってこう した分析を行うことができます。

65.

7.9 多母集団同時分析 65 7.9.1 多母集団同時分析の基本的な考え方 基本的な考え方はシンプルです。図 7.20 のように,まずデータをグループごとに分けておい て,同じモデルをグループごとに適用し,対応するパラメータの推定値が同じかどうかを評価し ていきます。なおここでは,上付き添字はグループごとに異なる係数を表すと思ってください。 (𝑀) つまり 𝑏1 (𝐹 ) と 𝑏1 は同じ因子から同じ項目への因子負荷ですが,異なるパラメータとして別々 に推定される,ということです。 図 7.20: 多母集団同時分析 lavaan では,引数 group に,グループを表す変数の名前を指示してあげればすぐに分析が 可能です。 とりあえずグループごとに分析してみる 1 2 3 4 model <- "f_A =~ Q1_1 + Q1_2 + Q1_3 + Q1_4" 5 result_base <- cfa(model, data = dat, std.lv = TRUE, group = "gender") 6 summary(result_base, standardized = TRUE) 1 2 3 4 5 6 7 8 lavaan 0.6-18 ended normally after 43 iterations # もちろんordered=TRUEにしてもOKです。 # ここでは簡略化のためorderedは指定しません。 Estimator Optimization method Number of model parameters Number of observations per group: 1 ML NLMINB 24 802

66.

7.9 多母集団同時分析 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 66 2 1630 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) Test statistic for each group: 1 2 34.458 4 0.000 7.472 26.986 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Group 1 [1]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.549 0.857 0.965 0.761 0.058 0.051 0.054 0.059 9.544 16.813 17.784 13.003 0.000 0.000 0.000 0.000 0.549 0.857 0.965 0.761 0.385 0.682 0.731 0.515 Estimate 4.278 4.494 4.347 4.434 Std.Err 0.050 0.044 0.047 0.052 z-value 85.060 101.352 93.246 84.932 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.278 4.494 4.347 4.434 Std.all 3.004 3.579 3.293 2.999 Estimate 1.728 0.842 0.811 1.607 1.000 Std.Err 0.093 0.070 0.082 0.094 z-value 18.624 11.949 9.916 17.037 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.728 0.842 0.811 1.607 1.000 Std.all 0.852 0.534 0.465 0.735 1.000 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A Group 2 [2]:

67.

7.9 多母集団同時分析 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 67 Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.575 0.811 0.852 0.695 0.039 0.032 0.037 0.041 14.834 25.073 23.087 16.883 0.000 0.000 0.000 0.000 0.575 0.811 0.852 0.695 0.420 0.738 0.665 0.474 Estimate 4.748 4.953 4.728 4.818 Std.Err 0.034 0.027 0.032 0.036 z-value 139.992 182.102 149.135 132.828 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.748 4.953 4.728 4.818 Std.all 3.467 4.510 3.694 3.290 Estimate 1.544 0.549 0.913 1.662 1.000 Std.Err 0.059 0.041 0.052 0.066 z-value 26.000 13.298 17.571 25.038 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.544 0.549 0.913 1.662 1.000 Std.all 0.824 0.455 0.557 0.775 1.000 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A 結果を見ると,Number of observations per group:(7 行目)のところで,各グループで の人数を表示しています。そして Group 1 [1]:(27 行目から)と Group 2 [2]:(54 行目か ら)という形で,それぞれのグループに対する推定結果が表示されています。 ただしこの段階では,単にデータを分割してそれぞれ独立にパラメータ推定を行っただけなの で,グループごとに因子得点が標準化されています(52, 78 行目) 。そのため,当然ながら平均値 などの比較はできません。そして因子得点をグループ間で比較可能にするためには,因子負荷と 切片がともにグループ間で等しいという制約を置く必要があります。多母集団同時分析の目的の 一つは,因子構造が同じかどうかを検証することですが,同一性が満たされて初めて,異なるグ ループ間での因子得点の平均が比較可能になります。 因子負荷が等しいという条件は,そもそも因子自体がグループ間で異なっていないことを示す ために必要です。これが満たされていないと,(仮にモデルの矢印が同じであっても)因子に占 める各項目の重みが変わってしまうため,完全に同じ因子とは言えないのです。 では,切片が同じという制約はなぜ必要なのでしょうか。ここでいう「切片」は,回帰分析の 「切片」と同じようなものです。因子分析では説明変数にあたる因子得点が潜在変数のため,少 し厄介なことになっているのです。これまで 1 因子の因子分析モデルは 𝐲𝑖 = 𝐟 𝑏 𝑖 + 𝜺 𝑖 (7.45) という形を取っていました。ですが本当は,回帰分析での 𝑏0 にあたる切片項(ここでは 𝜏 と表

68.

7.9 多母集団同時分析 68 記します)が存在しており, 𝐲𝑖 = 𝜏 + 𝐟 𝑏 𝑖 + 𝜺 𝑖 (7.46) という式になっています。通常 SEM(因子分析)では,観測変数 𝐲𝑖 は標準化されていれば(あ るいは標準化解を出す場合には),暗黙に 𝜏 = 0 となります。そのためにこれまでは 𝜏 を無視し てきました。ですが多母集団同時分析では,観測変数 𝐲𝑖 が標準化されていたとしても,切片項 まで考慮しないと因子得点の比較ができなくなってしまいます*20 。 例えば,データ全体で標準化された(全体平均が 0 の)観測変数 𝐲𝑖 の平均値が,男性のみで 計算すると 0.3, 女性のみで計算すると-0.3 だった,つまり男性のほうが平均的に高い得点をつけ ていたとしましょう。これは心理尺度で言えば,男性のほうが「当てはまる」寄りの回答をしが ち,という状況に相当します。そう考えるとこの 0.6 の差は「男性のほうが関連する因子得点 𝐟 が高い」ということを意味しているように見えるかもしれませんが,まだそうではない可能性を 持っています。もしグループごとに異なる切片 𝜏 (𝑔) があるとすると,先程の式は 𝐲𝑖 = 𝜏 (𝑔) + 𝐟 𝑏𝑖 + 𝜺𝑖 (7.47) となります。ここで,もし男性の切片 𝜏 (M) = 0.3 で女性の切片 𝜏 (F) = −0.3 だとすると,観測変 数 𝐲𝑖 の平均値の差 0.6 は切片の差に起因するものになってしまい,因子得点 𝐟 の部分では平均 値には差がなくなります。これは回帰分析で言えば gender というダミー変数に対する回帰係数 が 0.6 だった,ということです。例えばその項目が因子とは別の理由で男性の方が「あてはまる」 と答えやすい項目(つまり DIF)などのケースでは,こういったことが起こると考えられます。 そこで,もし 𝜏 (M) = 𝜏 (F) という制約をおけば,観測変数 𝐲𝑖 の平均値の差 0.6 は因子得点 𝐟 のほ うに表れてくれる,というわけです。こういった理由から,グループ間で因子得点を比較可能に するためには,因子負荷だけでなく切片にも等値制約を置く必要があるのです。 7.9.2 測定不変性の検証 多母集団同時分析では,先程実行した「グループ間でモデル式までは同じ」モデル(配置不変 モデル:configural invariance などと呼ばれます)をベースラインとして,グループ間で等 値制約をどこまで追加しても当てはまりが悪化しないかを検証していきます。ということで,も し配置不変モデルの段階で適合度が悪かったら終了です。そのような場合は,少なくとも group で分ける前から適合度が悪いはず… 配置不変モデルの適合度が問題なければ制約を追加していきましょう。ここからは 1.【弱測定不変モデル:weak invariance】因子負荷が同じ 2.【強測定不変モデル:strong invariance】さらに切片が同じ 3.【厳密な測定不変モデル:strict invariance】さらに独自因子の分散(共分散)が同じ 4.【(ほぼ完全な測定不変モデル)】さらに共通因子の分散共分散が同じ 5.【(完全な測定不変モデル)】さらに因子得点の平均が同じ *20 多母集団同時分析以外でも切片を考えても良いのですが,グループ間での比較をしない限りはさほど重要ではな いのでこれまで無視してきました。

69.

7.9 多母集団同時分析 69 という順番で徐々に制約を追加していきます*21 。つまり最低でも強測定不変モデルが許容さ れるならば,因子得点の平均の比較が可能になるというわけです。また,もしも一番下までクリ ア出来てしまった場合には,多母集団同時分析を行う必要はありません。その場合には,胸を 張って単一母集団モデルとしての結果を報告しましょう。 lavaan でこれらの等値制約をかける場合には,引数 group.equal に制約をかけたいパラ メータの種類を指定します。指定は何種類でも OK です。 表 7.3: group.equal で指定できる等値制約 指定 制約されるもの loadings 因子負荷 intercepts 切片 means 因子得点の平均 thresholds 閾値( orderedのときの) regressions 回帰係数 residuals 独自因子の分散 residual.covariances 独自因子の共分散 lv.variance 共通因子の分散 lv.covariance 共通因子の共分散 ということで,まずは弱測定不変モデル(因子負荷が同じ)を実行してみます。 弱測定不変モデル 1 # 因子負荷に等値制約を置く 2 result_weak <- cfa(model, data = dat, group = "gender", std.lv = TRUE, grou p.equal = c("loadings")) summary(result_weak, standardized = TRUE) 3 1 2 3 4 5 6 7 8 9 10 11 lavaan 0.6-18 ended normally after 43 iterations Estimator Optimization method Number of model parameters Number of equality constraints Number of observations per group: 1 2 ML NLMINB 25 4 802 1630 *21 下 2 つのモデルには決まった名称が無いため,カッコをつけています。

70.

7.9 多母集団同時分析 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 70 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) Test statistic for each group: 1 2 35.926 7 0.000 8.416 27.509 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Group 1 [1]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 (.p1.) (.p2.) (.p3.) (.p4.) Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.596 0.869 0.937 0.756 0.038 0.039 0.042 0.041 15.684 22.169 22.576 18.308 0.000 0.000 0.000 0.000 0.596 0.869 0.937 0.756 0.415 0.692 0.714 0.512 Estimate 4.278 4.494 4.347 4.434 Std.Err 0.051 0.044 0.046 0.052 z-value 84.317 101.301 93.738 84.975 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.278 4.494 4.347 4.434 Std.all 2.977 3.577 3.310 3.001 Estimate 1.709 0.823 0.846 1.612 1.000 Std.Err 0.092 0.062 0.068 0.091 z-value 18.650 13.282 12.457 17.623 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.709 0.823 0.846 1.612 1.000 Std.all 0.828 0.522 0.491 0.738 1.000 Estimate Std.Err z-value P(>|z|) Std.lv Std.all Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A Group 2 [2]: Latent Variables:

71.

7.9 多母集団同時分析 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 (.p1.) (.p2.) (.p3.) (.p4.) 71 0.596 0.869 0.937 0.756 0.038 0.039 0.042 0.041 15.684 22.169 22.576 18.308 0.000 0.000 0.000 0.000 0.552 0.804 0.867 0.700 0.405 0.732 0.675 0.478 Estimate 4.748 4.953 4.728 4.818 Std.Err 0.034 0.027 0.032 0.036 z-value 140.596 182.141 148.704 132.793 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.748 4.953 4.728 4.818 Std.all 3.482 4.511 3.683 3.289 Estimate 1.555 0.559 0.896 1.656 0.856 Std.Err 0.059 0.038 0.049 0.065 0.075 z-value 26.460 14.861 18.158 25.361 11.434 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 1.555 0.559 0.896 1.656 1.000 Std.all 0.836 0.464 0.544 0.772 1.000 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A 因子負荷のところに (.p1.) などといったものが表示されるようになりました。lavaan では, 各パラメータに名前をつけられる機能があり,複数のパラメータに同じ名前をつけると等値制約 をかけることができます(他の使い方は後述) 。そして group.equal でパラメータの種類の指定 をすると,その種類のすべてのパラメータに自動的に名前をつけることで,等値制約をかけてい るのです。実際に Group 1 [1]: と Group 2 [2]: のそれぞれ対応する因子負荷には同じ名前 がついているため,等値制約が置かれたことがわかります。 また Intercepts: 欄には各観測変数の切片(=グループ平均)が表示されています。これを 見る限りでは Group 2 [2]:,つまり女性の方が平均点が高そうですが,まだ切片には等値制約 を置いていないため,先ほど説明した理由よりこれが「因子得点の差」なのか「それ以外の要因 の差」なのかはまだわかりません。 そしてもう一点。Group 2 [2]: の因子の分散 ( f_A) の値が 1 では無くなっています。一方 Group 1 [1]: のほうでは相変わらず因子の分散は 1 に固定されています,これは,因子負荷に 等値制約を置いたことで,共通因子のスケールは Group 1 [1]: 側で決まり,Group 2 [2]: 側 では制約を置く必要がなくなったためです。その結果,因子負荷の Std.lv 列は「全ての潜在変 数の分散を 1 にした」時の推定値なので,グループ間で値が変わってしまいます。せっかく等値 制約を置いたのに,これでは多少違和感がありますが,そういうものなのであまり気にしないで ください。実際に弱測定不変モデルの結果を報告する際には,たぶん因子負荷は Estimate 列の 値を載せて,各グループの因子得点の分散を記入することが多いと思います。 続いて,弱測定不変モデルと配置不変モデルの間で適合度が著しく悪化していないかを検証し ます。比較の方法は Section 7.6.5 と同じです。多母集団モデルでは,各パラメータをグループご とに異なるものとしてそれぞれ自由に推定していました。ここに等値制約を置くということは,

72.
[beta]
7.9 多母集団同時分析

72

自由に推定できるパラメータの数が減少していることを意味するので,それだけ適合度は悪くな
るはずです。モデル修正におけるパスの削除が「そのパスの係数を 0 に固定する」だとすると,
(F)

多母集団モデルにおける等値制約は例えば「因子負荷 𝑏𝑖

(M)

の値を 𝑏𝑖

に固定する」としている

ようなもので,やっていることは同じなわけですね。
1

summary(compareFit(result_base, result_weak))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

################### Nested Model Comparison #########################
Chi-Squared Difference Test
Df
AIC
BIC Chisq Chisq diff RMSEA Df diff Pr(>Chisq)
result_base 4 31636 31775 34.458
result_weak 7 31631 31753 35.925
1.4678
0
3
0.6897
####################### Model Fit Indices ###########################
chisq df pvalue rmsea
cfi
tli
srmr
aic
result_base 34.458† 4
.000 .079
.979
.936 .022† 31635.698
result_weak 35.926
7
.000 .058† .980† .965† .023 31631.166†
bic
result_base 31774.813
result_weak 31752.891†
################## Differences in Fit Indices #######################
df rmsea
cfi
tli srmr
aic
bic
result_weak - result_base 3 -0.021 0.001 0.029 0.001 -4.532 -21.922

今回の等値制約では,4 つの項目の因子負荷にそれぞれ等値制約を置いたため,パラメータが

4 つ減少しています。一方で,先程説明したように Group 2 [2]: の因子の分散が自由推定可能
になったことでパラメータが実は 1 つ増えており,弱測定不変モデルでは差し引き 3 つのパラ
メータが減少しています。これが自由度 Df の違いに表れているのです。
結果を見ると,どうやら等値制約による当てはまりの悪化よりもパラメータを減らした(倹約
度の向上)効果の方が大きいらしく,RMSEA や CFI は改善しました。尤度比検定も有意では
なかったということで,弱測定不変性が確認されたと言って良いでしょう。
続いて,強測定不変モデル(因子負荷+切片)の検討に移ります。
強測定不変モデル
1

# group.equalに"intercepts"を追加

2

result_strong <- cfa(model, data = dat, group = "gender", std.lv = TRUE,
group.equal = c("loadings", "intercepts"))

3

summary(result_strong, standardized = TRUE)

73.

7.9 多母集団同時分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 73 lavaan 0.6-18 ended normally after 37 iterations Estimator Optimization method Number of model parameters Number of equality constraints ML NLMINB 26 8 Number of observations per group: 1 2 802 1630 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) Test statistic for each group: 1 2 48.938 10 0.000 18.205 30.733 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Group 1 [1]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 Estimate Std.Err z-value P(>|z|) Std.lv Std.all (.p1.) (.p2.) (.p3.) (.p4.) 0.626 0.882 0.910 0.752 0.037 0.039 0.040 0.040 16.693 22.885 22.835 18.705 0.000 0.000 0.000 0.000 0.626 0.882 0.910 0.752 0.432 0.701 0.696 0.509 (.10.) (.11.) (.12.) (.13.) Estimate 4.385 4.504 4.296 4.437 Std.Err 0.037 0.040 0.042 0.041 z-value 117.490 112.782 103.377 108.640 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.385 4.504 4.296 4.437 Std.all 3.025 3.582 3.285 3.004 Estimate Std.Err z-value P(>|z|) Std.lv Std.all Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances:

74.

7.9 多母集団同時分析 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A 74 1.710 0.804 0.883 1.616 1.000 0.092 0.062 0.066 0.092 18.510 13.057 13.277 17.663 0.000 0.000 0.000 0.000 1.710 0.804 0.883 1.616 1.000 0.814 0.508 0.516 0.741 1.000 Estimate Std.Err z-value P(>|z|) Std.lv Std.all (.p1.) (.p2.) (.p3.) (.p4.) 0.626 0.882 0.910 0.752 0.037 0.039 0.040 0.040 16.693 22.885 22.835 18.705 0.000 0.000 0.000 0.000 0.579 0.816 0.842 0.696 0.422 0.743 0.659 0.475 (.10.) (.11.) (.12.) (.13.) Estimate 4.385 4.504 4.296 4.437 0.504 Std.Err 0.037 0.040 0.042 0.041 0.053 z-value 117.490 112.782 103.377 108.640 9.503 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 4.385 4.504 4.296 4.437 0.545 Std.all 3.198 4.099 3.362 3.028 0.545 Estimate 1.545 0.541 0.924 1.663 0.856 Std.Err 0.059 0.037 0.048 0.065 0.075 z-value 26.271 14.646 19.413 25.474 11.413 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 1.545 0.541 0.924 1.663 1.000 Std.all 0.822 0.448 0.566 0.774 1.000 Group 2 [2]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A Group 2 [2]: の f_A の Intercepts: の値がゼロではなくなりました。切片まで固定した ことによって,因子得点の平均値が自由推定になり,比較可能になった状態です。推定値が 0.504 ということは,女性の方が各観測変数のグループ平均が高かったのは確かに因子得点が平均的に 高いためだ,といえそうです。一方で,もしも適合度がひどく悪化していたら「切片がグループ 間で同じというのはおかしい」ということになり,観測変数のグループ間の差は,むしろ切片項 に起因するものだと言えそうです。 強測定不変モデルも加えて 3 つのモデル比較 1 2 # 3モデル以上でも一気に出来ます summary(compareFit(result_base, result_weak, result_strong))

75.
[beta]
7.9 多母集団同時分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

75

################### Nested Model Comparison #########################
Chi-Squared Difference Test
Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
result_base
4 31636 31775 34.458
result_weak
7 31631 31753 35.925
1.4678 0.000000
3
0.68973
result_strong 10 31638 31743 48.938
13.0123 0.052389
3
0.00461
result_base
result_weak
result_strong **
--Signif. codes:

0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

####################### Model Fit Indices ###########################
chisq df pvalue rmsea
cfi
tli
srmr
aic
result_base
34.458† 4
.000 .079
.979
.936 .022† 31635.698
result_weak
35.926
7
.000 .058 .980† .965
.023 31631.166†
result_strong 48.938 10
.000 .057† .973 .967† .030
31638.178
bic
result_base
31774.813
result_weak
31752.891
result_strong 31742.514†
################## Differences in Fit Indices #######################
df rmsea
cfi
tli srmr
aic
bic
result_weak - result_base
3 -0.021 0.001 0.029 0.001 -4.532 -21.922
result_strong - result_weak 3 -0.002 -0.007 0.002 0.006 7.012 -10.377

尤度比検定は有意になった(=当てはまりが有意に悪くなった)のですが,適合度指標はさほ
ど悪化していません。というか RMSEA や TLI は更に改善しました。尤度比検定はサンプルサ
イズが多いとすぐ有意になってしまうこともありますし,BIC も強測定不変モデルを支持してい
るため,ここは強測定不変性が認められたと結論付けて先に進んでみましょう。
あとはどこまで測定不変性が認められるかを試すだけです。とりあえず一気に残りの全てのモ
デルを推定してみます。
残りのモデルも一気にやってしまう
1
2
3
4

# group.equalに"intercepts"を追加
# 厳密な測定不変モデル
# 独自因子の分散共分散を制約に追加
# 独自因子の共分散を追加している場合は"residual.covariances"も入れる

5

result_strict <- cfa(model, data = dat, group = "gender", std.lv = TRUE,

76.
[beta]
7.9 多母集団同時分析

group.equal = c("loadings", "intercepts", "residuals"))
6
7
8
9

# (ほぼ完全な測定不変モデル)
# 共通因子の分散共分散を制約に追加
# 2因子以上の場合は"lv.covariances"も入れる

10

result_almost <- cfa(model, data = dat, group = "gender", std.lv = TRUE,
group.equal = c("loadings", "intercepts", "residuals", "lv.variances"))

11
12
13

# (完全な測定不変モデル)
# 因子得点の平均を制約に追加

14

result_complete <- cfa(model, data = dat, group = "gender", std.lv = TRUE,
group.equal = c("loadings", "intercepts", "residuals", "lv.variances",
"means"))

そして全部一気に適合度を比較してみます*22 。
全てのモデルを比較
1

summary(compareFit(result_base, result_weak, result_strong, result_strict,
result_almost, result_complete))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

################### Nested Model Comparison #########################
Chi-Squared Difference Test
Df
AIC
BIC
Chisq Chisq diff
RMSEA Df diff
result_base
4 31636 31775 34.458
result_weak
7 31631 31753 35.925
1.468 0.000000
3
result_strong
10 31638 31743 48.938
13.012 0.052389
3
result_strict
14 31652 31733 70.463
21.526 0.060026
4
result_almost
15 31657 31732 77.395
6.931 0.069841
1
result_complete 16 31760 31830 183.159
105.765 0.293522
1
Pr(>Chisq)
result_base
result_weak
0.6897314
result_strong
0.0046101 **
result_strict
0.0002491 ***
result_almost
0.0084694 **
result_complete < 2.2e-16 ***
*22 ここまでのプロセスの大半を一度にやってくれる関数として,semTools::measurementInvariance() という

関数があります。一応今のところは使えるのですが,やがて消えることが公式にアナウンスされています。「代
わりに measEq,syntax() を使え」とアナウンスされているのですが,これは「指定した等値制約を置いたモデ
ル式を作ってくれる関数」のようです。つまり,機械的にとりあえずいろいろな不変モデルを試すのではなく,
一つ一つの結果を見て能動的に判断していけよということなのかもしれません。

76

77.

7.9 多母集団同時分析 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 --Signif. codes: 77 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result_base 34.458† 4 .000 .079 .979 .936 .022† 31635.698 result_weak 35.926 7 .000 .058 .980† .965 .023 31631.166† result_strong 48.938 10 .000 .057† .973 .967† .030 31638.178 result_strict 70.463 14 .000 .058 .960 .966 .036 31651.703 result_almost 77.395 15 .000 .058 .956 .965 .048 31656.635 result_complete 183.159 16 .000 .093 .883 .912 .094 31760.399 bic result_base 31774.813 result_weak 31752.891 result_strong 31742.514 result_strict 31732.854 result_almost 31731.989† result_complete 31829.957 ################## Differences in Fit Indices ####################### df rmsea cfi tli srmr aic result_weak - result_base 3 -0.021 0.001 0.029 0.001 -4.532 result_strong - result_weak 3 -0.002 -0.007 0.002 0.006 7.012 result_strict - result_strong 4 0.001 -0.012 -0.001 0.007 13.526 result_almost - result_strict 1 0.001 -0.004 -0.001 0.011 4.931 result_complete - result_almost 1 0.034 -0.074 -0.053 0.046 103.765 bic result_weak - result_base -21.922 result_strong - result_weak -10.377 result_strict - result_strong -9.660 result_almost - result_strict -0.865 result_complete - result_almost 97.968 この結果を踏まえてどこまでの測定不変性を認めるかについては諸説ありそうです。基本的に は適合度指標が許容範囲内にある中で最も制約の強いモデルを選べば良いのではないか,と思い ますが,人によって許容範囲内であっても前のモデルから適合度指標が著しく低下している場合 にはアウトとする人もいます。 7.9.3 (おまけ)部分的な測定不変性 測定不変性がどこまで満たされるかをもっと厳密に検証しようとすると,ギリギリ許容できる レベルはきっと上で見たいくつかのモデルの間にあるでしょう。例えば弱測定不変モデルの適合 度は許容範囲だが強測定不変モデルまでいくと許容範囲から外れてしまう場合,置くことのでき る等値制約は「全ての因子負荷+一部の切片」ということになる可能性が高いです。

78.

7.9 多母集団同時分析 78 ここからは,そのような部分的な測定不変性を lavaan で推定する方法を紹介していきます。 ここでは,仮に「弱測定不変までは認められるが強測定不変性は認められなかった」として,そ の間の部分的な強測定不変性を検証していきます。 考え方としては,許容されなかったモデルをベースに「どこの等値制約を外すと良さそうか」 を見ていくことになります。そのために有用な関数が lavTestScore() です*23 。 外すべき等値制約を見つける 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 lavaan::lavTestScore(result_strong) $test ​ ​ total score test: ​ ​ ​ ​ ​ ​ ​ test X2 df p.value 1 score 14.128 8 0.078 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ $uni univariate score tests: lhs op rhs X2 df p.value 1 .p1. == .p15. 2.795 1 0.095 2 .p2. == .p16. 0.040 1 0.842 3 .p3. == .p17. 1.865 1 0.172 4 .p4. == .p18. 0.008 1 0.930 5 .p10. == .p24. 9.348 1 0.002 6 .p11. == .p25. 0.303 1 0.582 7 .p12. == .p26. 6.396 1 0.011 8 .p13. == .p27. 0.011 1 0.917 ここで表示されているのはスコア検定(またの名をラグランジュ乗数検定)と呼ばれるもので す。compareFit() 関数で出てくる検定(尤度比検定)は,複数のネストされたモデルについて, 「制約のないモデル」を基準として,(a) グループ間で等値制約を置く,(b) 矢印を消す(あるパ ラメータの値を 0 に制約する)など「制約を増やしたときに,増やした制約の数の割に尤度が低 下していないか」を確かめるものでした。 スコア検定はこれとは反対に,「制約のあるモデル」を基準として,「制約を減らしたときに, 減らした制約の数に合った尤度の改善が見られるか」を確かめるものです。帰無仮説自体は尤度 比検定のときと同じで「2 つのモデルの尤度(厳密には最尤推定値)が同じであるか」なので,ス コア検定が有意だった場合には「制約を減らしたほうが良さそう」と判断できるわけです。 一番上に出ている $test は,モデル全体での検定の結果です。今回は全ての因子負荷と切片 *23 パラメータを自由推定にした際の適合度の改善を見るわけなので modificationindices() も使えそうなので すが,こいつは「等値制約を外したとき」を評価してはくれないのでここでは使えません。

79.

7.9 多母集団同時分析 79 に等値制約が置かれた強測定不変モデル( result_strong)をもとに検定しているため「強測 定不変モデルと配置不変モデルの比較」を直接していることになります(その意味では弱測定不 変モデルのとき以外は見なくても良さそう?) 。 次に出ている $uni は,パス単位で等値制約を外したときの検定です。結果を見るのがやや大 変ですが,lhs にかかれている名前は summary(result_strong) の出力にあったパラメータ名 です( rhs は等値制約を外したときにグループ 2 のそのパラメータにつけられるはずの別名)。 したがって,上の 4 つ( .p1. から .p4)が各因子負荷を,下の 4 つ( .p10. から .p13)が各 切片を意味しています。今回は強測定不変モデルから制約を緩めようとしているので,特に下の 4 つに注目してみると,.p10. つまり Q1_1 に対する切片のところが 𝜒2 値( X2)が最大となっ ています。ここから, 「切片の等値制約を一つだけ外すとしたら Q1_1 を外すと良い」ということ が言えるわけです。 これが分かったところで,実際に部分的に等値制約を外したモデルで推定を行ってみましょ う。ここで使用するのが group.partial という引数です。 強測定不変モデルから制約を外す 1 2 # group.partialにモデル式の形で指定する # 切片は "~ 1"で指定可能でした 3 result_strong_p <- cfa(model, data = dat, group = "gender", std.lv = TRUE, 4 summary(result_strong_p, standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 lavaan 0.6-18 ended normally after 43 iterations group.equal = c("loadings", "intercepts"), group.partial = "Q1_1 ~1") Estimator Optimization method Number of model parameters Number of equality constraints Number of observations per group: 1 2 ML NLMINB 26 7 802 1630 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) Test statistic for each group: 1 2 Parameter Estimates: 39.596 9 0.000 11.227 28.369

80.

7.9 多母集団同時分析 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 80 Standard errors Information Information saturated (h1) model Standard Expected Structured Group 1 [1]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.599 0.884 0.918 0.757 0.038 0.039 0.040 0.040 15.732 22.808 22.859 18.746 0.000 0.000 0.000 0.000 0.599 0.884 0.918 0.757 0.417 0.701 0.701 0.512 Estimate 4.278 (.11.) 4.522 (.12.) 4.310 (.13.) 4.450 Std.Err 0.051 0.040 0.042 0.041 z-value 84.310 112.334 102.718 108.457 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 4.278 4.522 4.310 4.450 Std.all 2.977 3.589 3.292 3.009 Estimate 1.706 0.806 0.872 1.613 1.000 Std.Err 0.092 0.062 0.067 0.091 z-value 18.629 13.041 13.063 17.633 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.706 0.806 0.872 1.613 1.000 Std.all 0.826 0.508 0.508 0.738 1.000 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.599 0.884 0.918 0.757 0.038 0.039 0.040 0.040 15.732 22.808 22.859 18.746 0.000 0.000 0.000 0.000 0.554 0.817 0.849 0.700 0.406 0.743 0.663 0.478 Estimate 4.463 (.11.) 4.522 Std.Err 0.044 0.040 z-value 100.948 112.334 P(>|z|) 0.000 0.000 Std.lv 4.463 4.522 Std.all 3.273 4.110 (.p1.) (.p2.) (.p3.) (.p4.) Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A Group 2 [2]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 (.p1.) (.p2.) (.p3.) (.p4.) Intercepts: .Q1_1 .Q1_2

81.

7.9 多母集団同時分析 68 69 70 71 72 73 74 75 76 77 78 .Q1_3 .Q1_4 f_A 81 (.12.) (.13.) 4.310 4.450 0.476 0.042 0.041 0.053 102.718 108.457 8.927 0.000 0.000 0.000 4.310 4.450 0.515 3.368 3.034 0.515 Estimate 1.552 0.543 0.917 1.660 0.855 Std.Err 0.059 0.037 0.048 0.065 0.075 z-value 26.450 14.562 19.119 25.427 11.427 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 1.552 0.543 0.917 1.660 1.000 Std.all 0.835 0.448 0.560 0.772 1.000 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A 結果を見ると,確かに Intercepts: の Q1_1 のところの等値制約が外れています。あとは適 合度の比較をするだけです。 部分的な不変モデルとの比較 1 2 # 一応弱測定不変モデルとも比べてみる summary(compareFit(result_weak, result_strong_p, result_strong)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ################### Nested Model Comparison ######################### Chi-Squared Difference Test Df AIC BIC Chisq Chisq diff RMSEA Df diff result_weak 7 31631 31753 35.925 result_strong_p 9 31631 31741 39.596 3.6704 0.026208 2 result_strong 10 31638 31743 48.938 9.3419 0.082826 1 Pr(>Chisq) result_weak result_strong_p 0.15958 result_strong 0.00224 ** --Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result_weak 35.926† 7 .000 .058 .980† .965 .023† 31631.166 result_strong_p 39.596 9 .000 .053† .979 .971† .025 31630.836† result_strong 48.938 10 .000 .057 .973 .967 .030 31638.178 bic result_weak 31752.891 result_strong_p 31740.969† result_strong 31742.514

82.
[beta]
7.10 lavaan の記法
​

26
27
28
29
30
31
32
33

82

​

################## Differences in Fit Indices #######################
df rmsea
cfi
tli srmr
aic
result_strong_p - result_weak
2 -0.005 -0.001 0.006 0.001 -0.330
result_strong - result_strong_p 1 0.004 -0.006 -0.004 0.005 7.342
bic
result_strong_p - result_weak
-11.923
result_strong - result_strong_p
1.545

結果を見ると,部分的な強測定不変モデル( result_strong_p)は,弱測定不変モデル
( result_weak)と比べても尤度の低下が大きくなく,また RMSEA や AIC, BIC などは改善
しており,何なら強測定不変モデルよりも良い値になっています。
…という感じで,測定不変性を細かいところまで見ていくことも可能です。因子分析で言え
ば,特定の項目だけ切片が異なるというのは,もしかしたらその項目に DIF 的な要素があった
ことを示しているのかもしれません。このあたりも掘り下げることができれば面白い示唆が得ら
れるかもしれないので,余裕があればいろいろ試してみると良いでしょう。

7.10 lavaan の記法
​

​

知っていると役に立つ日が来るかもしれない,lavaan のより高度な記法について少しだけ紹
介します。

7.10.1 パラメータの制約
尺度を作成する際には,探索的因子分析の結果 2 項目だけの因子が誕生してしまうことがあり
ます。ですが 2 項目だけの因子は,モデル的には単体では結構危うい存在です。実際に,2 項目

1 因子のみの因子分析モデルを考えてみましょう。この場合,推定するパラメータは因子負荷と
独自因子の分散がそれぞれ 2 つずつで計 4 つです。その一方で,データの分散共分散は 3 つしか
ありません。つまりそのままでは推定に失敗する,ということです*24 。
試しに 2 項目 1 因子の(うまくいかない)モデルをやってみましょう。
うまくいかない 2 項目 1 因子モデル
1
2

model <- "f_A =~ Q1_1 + Q1_2"
summary(cfa(model, data = dat, std.lv = TRUE), standardized = TRUE)

1
2
3

Warning: lavaan->lav_model_vcov():
Could not compute standard errors! The information matrix could not
be inverted. This may be a symptom that the model is not identified.
*24 一応他の因子との因子間相関(両方向の矢印)があれば,2 項目でも問題なく推定できるようになりますが,安

定しないことも多々あります…

83.

7.10 lavaan の記法 ​ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 83 ​ lavaan 0.6-18 ended normally after 9 iterations Estimator Optimization method Number of model parameters ML NLMINB 4 Number of observations 2432 Model Test User Model: Test statistic Degrees of freedom P-value (Unknown) NA -1 NA Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_A =~ Q1_1 Q1_2 Estimate Std.Err 1.010 0.575 NA NA Estimate 0.954 1.044 1.000 Std.Err NA NA z-value P(>|z|) Std.lv Std.all 1.010 0.575 0.719 0.491 Std.lv 0.954 1.044 1.000 Std.all 0.483 0.759 1.000 Variances: .Q1_1 .Q1_2 f_A z-value P(>|z|) 出力を見ると Degrees of freedom が -1 になっており,検定も行われていません。一応因 子負荷は出ているのですが,実際のところこれが正しいという保証は全くありません。本当はこ のような場合には,項目数を増やしたり他の項目と合わせて因子構造を再検討するのが重要にな るのですが,もしもどうしてもこの 2 項目だけで行かなければならない場合には,とりあえず 2 項目の因子負荷に等値制約をかけることで推定するパラメータ数を減らす事ができます。 等値制約をかける 1 model <- "f_A =~ b1 * Q1_1 + b1 * Q1_2" モデルの修正のところで,右辺の変数名の前に 0*をかけることで共分散をゼロに固定する方 法を紹介しました。それと同じように,ここでは右辺の変数名の前に共通の b1 をかけています。

84.

7.10 lavaan の記法 ​ 84 ​ 等値制約をかけて推定 1 summary(cfa(model, data = dat, std.lv = TRUE), standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 lavaan 0.6-18 ended normally after 11 iterations Estimator Optimization method Number of model parameters Number of equality constraints ML NLMINB 4 1 Number of observations 2432 Model Test User Model: Test statistic Degrees of freedom 0.000 0 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f_A =~ Q1_1 Q1_2 (b1) (b1) Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.762 0.762 0.023 0.023 32.813 32.813 0.000 0.000 0.762 0.762 0.543 0.650 Estimate 1.394 0.793 1.000 Std.Err 0.051 0.039 z-value 27.466 20.520 P(>|z|) 0.000 0.000 Std.lv 1.394 0.793 1.000 Std.all 0.706 0.577 1.000 Variances: .Q1_1 .Q1_2 f_A 結果を見ると,因子負荷の欄に測定不変性の検証の時と同じように (b1) という表記が追加さ れています。パラメータ数を減らしたことによって,Degrees of freedom が 0(つまり飽和モ デル)になり,晴れてパラメータの検定が行われるようになりました。 INFO (意見)尺度得点を和得点にするなら因子負荷の等値制約が必要じゃないか 尺度得点として,因子得点ではなく和得点を使うケースが多いことはすでに説明したとお りです。このような場合でも,尺度作成論文では通常「1 項目が 1 因子にのみ負荷してい る状態(完全な単純構造) 」で CFA を行い,モデル適合度を確認しています。ですがよく

85.
[beta]
7.10 lavaan の記法
​

​

考えると,尺度得点が和得点であるならば,CFA を行う際に因子負荷には等値制約をか
けたほうがよいのではないかという気がしています。
因子負荷の大きさは,その項目が因子得点の推定に与える影響の強さを表しています。言
い換えると,因子負荷はその項目の重みという見方ができるということです。そう考える
と,等値制約を置かない CFA によるモデル適合度の検証は「重み付け得点を使用した場
合の適合度」であり,もしも項目の重みが極端に異なる場合は,重み付けない単純な和得
点では著しく適合度が悪化する可能性があります。
したがって,
「和得点でのモデル適合度」を検証するために,因子ごとに全ての因子負荷に
等値制約をおいた状態でのモデル適合度を評価すべきではないか,という気がするのです
が実際にそのようにしている研究は見たことが無い気が…と思っていたらこんな論文があ
りました。→ McNeish & Wolf(2020)
等値制約は他にも,多母集団同時分析で特定の回帰係数が同じかどうかを評価する際や,複数
時点で同一のモデルを測定する場合に共通のパスが同じ値かを検討する際にも使ったりします。
多母集団同時分析に関して,例えば 図 7.19 の回帰分析モデルを性別ごとに行い,
「 age が Q1_A
におよぼす影響」が男女間で同じかを検討したい場合には,以下のようにして,等値制約あり/
なしのモデルを比較すると良いですね。
部分的な等値制約の検討
1
2
3
4
5
6
7

# 制約なしモデル
model_base <- '
Q1_A ~ age + education
'

8

Q1_A ~ c(b,b) *age + education

9
10
11
12
13

'

1
2
3
4
5
6
7
8

################### Nested Model Comparison #########################

# 制約ありモデル
model_const <- '

result_base <- sem(model_base,data=dat,group="gender")
result_const <- sem(model_const,data=dat,group="gender")
summary(compareFit(result_base, result_const))

Chi-Squared Difference Test

result_base
result_const

Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
0 12810 12856 0.0000
1 12810 12850 2.0076
2.0076 0.030048
1
0.1565

85

86.

7.10 lavaan の記法 ​ 9 10 11 12 13 14 15 16 17 18 19 86 ​ ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result_base .000† NA .000† 1.000† 1.000† .000† 12809.872† result_const 2.008 1 .157 .030 .978 .911 .009 12809.880 bic result_base 12855.557 result_const 12849.854† ################## Differences in Fit Indices ####################### df rmsea cfi tli srmr aic bic result_const - result_base 1 0.03 -0.022 -0.089 0.009 0.008 -5.703 このように掛け算する時に group の数と同じ長さの c() を与えると,グループの順にそれぞ れパラメータに名前を付けることができます。もちろん c(0.5, 0.6)*というように直接数字を 入力することによって,グループごとに異なる値に固定することもできます。 7.10.2 等式・不等式制約 図 7.21 のように,各因子の 2 番目の項目を逆の因子に入れてしまった因子分析モデルを考え ます。 図 7.21: 間違えちゃった このモデルを推定すると, (設定をミスっているので)推定値が変なことになります。 間違えたまま推定しちゃった 1 2 3 4 5 model <- " f_A =~ Q1_1 + Q1_7 + Q1_3 f_E =~ Q1_6 + Q1_2 + Q1_8 " result <- cfa(model, data = dat, std.lv = TRUE)

87.
[beta]
7.10 lavaan の記法
​

1
2
3

87

​

Warning: lavaan->lav_object_post_check():
covariance matrix of latent variables is not positive definite ; use
lavInspect(fit, "cov.lv") to investigate.

するとなにやら Warning が出てきました。どうやらメッセージを読む限りは「潜在変数の共
分散行列が正定値 (positive definite) ではない」ということですが,つまりどういうことでしょ
うか。
とりあえず summary() を見てみる
1

summary(result, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

lavaan 0.6-18 ended normally after 33 iterations
Estimator
Optimization method
Number of model parameters

ML
NLMINB
13

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

844.850
8
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f_A =~
Q1_1
Q1_7
Q1_3
f_E =~
Q1_6
Q1_2
Q1_8

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.500
0.407
0.726

0.033
0.030
0.034

15.207
13.355
21.515

0.000
0.000
0.000

0.500
0.407
0.726

0.356
0.309
0.556

0.318
0.753
0.372

0.029
0.034
0.030

11.027
22.179
12.325

0.000
0.000
0.000

0.318
0.753
0.372

0.258
0.642
0.289

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

Covariances:

88.

7.10 lavaan の記法 ​ 34 35 36 37 38 39 40 41 42 43 44 45 46 88 ​ f_A ~~ f_E 1.290 0.057 22.693 0.000 1.290 1.290 Estimate 1.725 1.566 1.177 1.415 0.808 1.519 1.000 1.000 Std.Err 0.053 0.047 0.048 0.042 0.046 0.045 z-value 32.801 33.520 24.574 33.927 17.491 33.623 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.725 1.566 1.177 1.415 0.808 1.519 1.000 1.000 Std.all 0.874 0.904 0.691 0.933 0.588 0.916 1.000 1.000 Variances: .Q1_1 .Q1_7 .Q1_3 .Q1_6 .Q1_2 .Q1_8 f_A f_E Covariances: の推定値(35 行目)が 1.290 になっています。この値は,2 つの因子 f_A と f_E の相関係数を表しているはずなので 1 を超えるのは明らかにおかしな話です。このように, モデルの設定をめちゃめちゃ失敗すると不適解が発生してしまいます。不適解が生じた場合に は,基本的にはモデルに誤設定がある(あまりに変なパスを引いてしまっている or 絶対に必要 なパスを引いていなかったり,変な変数が入っていたり)可能性が高いので,まずはそれを修正 するべきです。 ただ場合によってはモデルの設定は問題ないという自負があるにも関わらず不適解が生じるこ とがあります。よくあるのはデータが悪い状況です。SEM では,データにおいて観測された分 散共分散をもとにして,モデル上の分散共分散を推定していきます。したがって,データが酷い (サンプルサイズが小さい・欠測値が多すぎる・適当な回答が見られる)ときには,モデルが正 しくてもうまく推定できないことがあります*25 。Chapter 3 において,事前に適当な回答をし ているデータを除外する方法を紹介したのはこのような事態を回避するためでもあったのです。 そして特にモデルが複雑な場合やデータがひどい場合には,独自因子の分散がマイナスになっ たり相関係数が 1 を超えるなどの事態(Heywood case)が起こることがあります。基本的に は不適解はそのまま報告してはいけないのですが, • どう考えてもモデルは正しいし, • データには問題ない(と思っている)し, • 不適解の部分以外はいい感じの推定値だし, • 不適解といってもギリギリアウト(独自因子の分散が-0.005 とか) という感じで,自分は悪くないと言い切れる自信がある状況であれば,多少の不適解には目を つぶって*26 不等式制約をかけてとりあえず結果を報告することがあります。そういう場合には, パラメータに上限・下限を定めて推定するという方法をとります。 *25 R に慣れた方は,試しに「変数間の相関関係を完全に無視してデータのサイズだけ合わせたデータ」を乱数生成 して試してみてください。ほぼ確実に推定失敗すると思います。 *26 独自因子の分散の真値がほぼゼロの場合,標本誤差の影響などで 0 を下回ってしまうことが実際にあるのです。 そうだと言い切れるなら仕方ないのです。

89.
[beta]
7.10 lavaan の記法
​

89

​

パラメータの上限・下限を決める
1
2
3
4
5

model <- "
f_A =~ Q1_1 + Q1_7 + Q1_3
f_E =~ Q1_6 + Q1_2 + Q1_8

6

f_A ~~ cor * f_E

7
8

# パラメータの制約を不等号で記述する

# 制約をかけたいパラメータにラベルを付ける

9

cor < 1

10
11

# 同様に,独自因子の分散を0以上にしたいなら

12

Q1_1 ~~ var_e1 * Q1_1

13

var_e1 > 0

14
15
16

"
result <- cfa(model, data = dat, std.lv = TRUE)
summary(result, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

lavaan 0.6-18 ended normally after 62 iterations
Estimator
Optimization method
Number of model parameters
Number of inequality constraints

ML
NLMINB
13
2

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

862.410
8
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f_A =~
Q1_1
Q1_7

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.585
0.315

0.033
0.031

17.759
10.041

0.000
0.000

0.585
0.315

0.416
0.239

90.

7.10 lavaan の記法 ​ 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 90 ​ Q1_3 f_E =~ Q1_6 Q1_2 Q1_8 0.843 0.032 26.209 0.000 0.843 0.645 0.253 0.884 0.347 0.029 0.030 0.031 8.579 29.289 11.336 0.000 0.000 0.000 0.253 0.884 0.347 0.205 0.754 0.270 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 1.000 1.000 Std.lv 1.633 1.632 0.995 1.453 0.594 1.537 1.000 1.000 Std.all 0.827 0.943 0.584 0.958 0.432 0.927 1.000 1.000 Covariances: f_A ~~ f_E (cor) 1.000 Variances: .Q1_1 .Q1_7 .Q1_3 .Q1_6 .Q1_2 .Q1_8 f_A f_E (vr_1) Estimate 1.633 1.632 0.995 1.453 0.594 1.537 1.000 1.000 Std.Err 0.052 0.048 0.047 0.042 0.043 0.046 z-value 31.646 33.979 21.346 34.230 13.723 33.715 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 Constraints: 1 - (cor) var_e1 - 0 |Slack| 0.000 1.633 ということで,Warning も出ずに無事推定できました。ただ,この方法はあくまでも対処療法 です。まずはモデルの誤設定の可能性を完全に消し去るのが第一です。 不等式制約と同じように,等式制約や四則演算による制約を置くことも可能です。例えば(意 味があるかはともかく)「項目 1 の因子負荷」が「項目 2 と項目 3 の因子負荷の平均」よりも大 きいということが仮説から言えるとしたら,次のような書き方が出来ます。 等式制約も置けないことはない 1 2 model <- " f_A =~ b1*Q1_1 + b2*Q1_2 + b3*Q1_3 + Q1_4 + Q1_5 3 b1 > (b2 + b3)/2 4 " 7.10.3 推定しないパラメータの定義(媒介分析) SEM でよくあるのが,ある変数が別の変数に及ぼす効果を「直接的な効果(直接効果)」と 「別の変数を介して及ぼす効果(間接効果) 」に分解して考えるモデルです。図 7.22 では,学歴 に性別が及ぼす効果について,「性別が勤勉性 ( Q1_C) を介して学歴に影響している」という間

91.

7.10 lavaan の記法 ​ 91 ​ 接効果を考えています。 図 7.22: 媒介モデル このように,ある変数間の関係に第 3 の変数を考える分析のことを媒介分析 (mediation analysis) と呼びます。Baron & Kenny(1986)の枠組みでは,gender から education に対 する Q1_C の媒介効果を確認するためには 1. Q1_C をモデルから消したときには gender から education への単回帰が有意である 2. その上で gender から Q1_C への単回帰も Q1_C から age への単回帰も有意になる 3. Q1_C をモデルに含めた場合には,gender から education への直接効果が有意ではなく なる ことを示せば良いとしています。理想的には 3 点目に関して gender から education への直 接効果が完全にゼロになってくれれば, 「 gender は Q1_C を通してのみ education に影響を与 える」ということがハッキリ言えるわけですが,実際にはなかなかそうもいきません。とりあえ ず gender から education への直接効果が有意に減少してくれれば万々歳です。 図 7.22 のモデルでは,gender から education への経路は 2 つあります。こうしたケースで は 2 変数の共分散は「全ての経路のパス係数の積の和」となりました。媒介分析でも同じよう に,直接効果が 𝑐,間接効果が 𝑎𝑏 と表されるならば,これらを合わせた 𝑎𝑏 + 𝑐 が gender から education への総合効果となります。先程の 1 点目は,言い換えると「 gender から education への総合効果が有意である」ということです。 したがって,先程の Baron & Kenny(1986)の枠組みを SEM のパラメータで表すと • 𝐻1 ∶ 𝑎𝑏 + 𝑐 ≠ 0 • 𝐻2 ∶ 𝑎 ≠ 0 • 𝐻3 ∶ 𝑏 ≠ 0 • 𝐻4 ∶ 𝑎𝑏 ≠ 0 を全て示すことができれば,Q1_C による媒介効果を認めることができるわけです*27 。 それでは lavaan で媒介分析を行ってみましょう。 *27 もしこれに加えて 𝐻 ∶ 𝑐 = 0 が示せれば,完全な媒介効果だといえます。因果関係における中継点を見つけた, 5 という意味で因果関係のメカニズム解明にかなり役立つ情報になりえます。

92.

7.10 lavaan の記法 ​ 92 ​ 媒介分析 1 2 3 4 5 model <- " education ~ b*Q1_C + c*gender Q1_C ~ a*gender 6 ab := a*b 7 total := ab + c 8 " # 制約ではなく事後的な計算をして欲しい ここでのポイントは ":="という記号です。これをを使うと,ラベル付けしたパラメータの推 定値に基づいて計算をしてくれます。上の例では,まず 図 7.22 に沿って各回帰係数に a,b,c というラベルを付けています。そして "ab := a*b"と書くことで,「 a*b を ab と定義します」 という意味になります。":="によって記述した場合,ab というパラメータを推定するというこ とはありません。ただ単に推定された a と b の値をもとに,事後的に ab を計算して出力してく れるようになります。一方,もしも ab = a*b と書いてしまうと,ab は( a*b との等値制約が 置かれた)パラメータとして推定されてしまいます。 媒介分析の結果を見る 1 2 result <- sem(model, data = dat) summary(result, standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 lavaan 0.6-18 ended normally after 7 iterations Estimator Optimization method Number of model parameters Number of observations ML NLMINB 5 Used 2232 Model Test User Model: Test statistic Degrees of freedom 0.000 0 Parameter Estimates: Standard errors Information Information saturated (h1) model Regressions: Standard Expected Structured Total 2432

93.

7.11 同値モデル 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 93 Estimate Std.Err z-value P(>|z|) Std.lv Std.all (b) (c) 0.006 0.007 0.005 0.050 1.187 0.134 0.235 0.893 0.006 0.007 0.025 0.003 (a) 0.822 0.213 3.852 0.000 0.822 0.081 Estimate 1.235 22.423 Std.Err 0.037 0.671 z-value 33.407 33.407 P(>|z|) 0.000 0.000 Std.lv 1.235 22.423 Std.all 0.999 0.993 Defined Parameters: Estimate ab 0.005 total 0.012 Std.Err 0.004 0.050 z-value 1.134 0.232 P(>|z|) 0.257 0.817 Std.lv 0.005 0.012 Std.all 0.002 0.005 education ~ Q1_C gender Q1_C ~ gender Variances: .education .Q1_C Defined Parameters: という箇所が増えました。定義されたパラメータについても,自由推 定されたパラメータと同じように仮説検定まで行ってくれます。ということで,これを使えば先 程の仮説群をまとめて検証することが出来ます。ただ今回の場合では,そもそも total の推定 値から,𝐻1 ∶ 𝑎𝑏 + 𝑐 ≠ 0 が有意ではないことが分かるのでおしまいです*28 。 7.11 同値モデル 突然ですが,同じ 4 つの観測変数について,図 7.23 に 2 つの異なるモデルを考えました。上 は「 gender が education に及ぼす影響」を考えるモデルです。これに対して下のモデルでは 矢印の向きを全てひっくり返して「 education が gender に及ぼす影響」を推定するモデルに なっています。 図 7.23: 矢印の向きを変えてみた 普通に考えたら,少なくとも「学歴によって性別が影響を受ける」よりは「性別によって学歴 が影響を受ける」上のモデルのほうが自然な気がしますが,とりあえずこれらのモデルを分析し てみましょう。 *28 当然ですが,total の値は lm(education ~ gender,data=dat) の結果と一致します。

94.

7.11 同値モデル とりあえず 2 つのモデルを推定して比較 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 model1 <- " education ~ Q1_C Q1_C ~ Q1_A Q1_A ~ gender " 16 summary(compareFit(result1, result2, nested = FALSE)) 1 2 3 4 5 6 7 ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result1 5.916† 3 .116 .021† .988† .977† .016 32827.430 result2 5.916 3 .116 .021 .988 .977 .016† 28979.094† bic result1 32861.694 result2 29013.358† model2 <- " gender ~ Q1_A Q1_A ~ Q1_C Q1_C ~ education " result1 <- sem(model1, data = dat) result2 <- sem(model2, data = dat) # 適合度指標を比較,ネストしていないので nested = FALSE をつけて 実はこの 2 つのモデルでは,RMSEA, CFI, TLI, SRMR といった適合度指標は全て完全に同 じ値になります*29 。ダガー( †)がついているのは,数値計算上の細かいズレのためであり,こ れも小数点第 9 位くらいでやっと差が出る程度の違いしかありません。適合度指標が完全に一致 しているということは,モデル上の共分散行列(𝚺)に関しても全く同じ値になっているという ことなので,これらの 2 つのモデルは統計的には優劣をつけることが出来ません。こうしたモデ ルのことを同値モデル (equivalent model) と呼びます。 基本的には,回帰を含む SEM のモデルには多少なりとも同値モデルが存在しており,可能 であればこうした同値モデルに関しても議論をしておくべきだという意見もあります(Kang & Ahn, 2021)*30 。多くの場合,同値モデルは 図 7.23 のように,どこかしらの矢印の向きを反対 にしたモデルです。一部の人は SEM(あるいは回帰分析)の矢印を「因果関係」かのように扱っ てしまいますが,これは誤った考え方です。統計的にはデータに対する当てはまり(=モデルの 「良さ」)が完全に同じモデルがあるということは,分析上は矢印の向きはどちらでも良いといえ ます。これは回帰分析の 𝑥 と 𝑦 は入れ替えても問題ないのと同じです。したがって,特に SEM *29 AIC や BIC がぜんぜん違う値になっているのですが,この理由は分かりません…何か計算方法のせいだとは思 うのですが,とりあえず今回のケースでは AIC や BIC はあてにならないと思ってください。 *30 ちなみに同値モデルの作り方に関しては Mayekawa(1994)などにあります。 94

95.

7.12 𝜔ℎ を求める 95 を実施する際には,分析者は統計以外の側面から,つまり先行研究などを踏まえてなるべく理論 的に矢印の向きを指定する必要があります。「同値モデルに関しても議論をしておくべき」とい うのは「なぜ矢印の向きが逆ではいけないのか」をきちんと説明しておく必要があるということ です。 7.12 𝜔ℎ を求める Chapter 6 で紹介した 𝜔 係数のお話の続きです。今回は,分析者が事前に設定した因子構造に おける 𝜔ℎ を求める方法を紹介します。 7.12.1 双因子モデル 図 7.24 の 10 項目 2 因子のモデルに関してやってみましょう。 図 7.24: 10 項目 2 因子モデル まずは今までと同じように cfa() でパラメータの推定を行います。ただし,𝐺 因子にあたる ものを用意する点に注意です。 omega_h を求めるために 1 2 3 4 5 6 7 8 9 10 model <- " g =~ Q1_1 + Q1_2 + Q1_3 + Q1_4 + Q1_5 + Q1_6 + Q1_7 + Q1_8 + Q1_9 + Q1_10 f_A =~ Q1_1 + Q1_2 + Q1_3 + Q1_4 + Q1_5 f_C =~ Q1_6 + Q1_7 + Q1_8 + Q1_9 + Q1_10 # G因子と特殊因子は無相関にしないと推定できない g ~~ 0*f_A + 0*f_C " result <- cfa(model, data = dat, ordered = TRUE)

96.

7.12 𝜔ℎ を求める 96 𝜔 係数を算出するためには semTools::compRelSEM() という関数を使います*31 。 omega_h を求める 1 compRelSEM(result) 1 2 g f_A f_C 0.566 0.633 0.034 出てくる値は,それぞれの因子のみの 𝜔 係数です。したがって,g のところにある 0.566 とい う値が,𝜔ℎ を表しています。Chapter 6 のなかで omega() 関数で出した値(0.42)と比べる とそこそこ大きな値になっています。これは「カテゴリカル因子分析にした」ことと「もう一方 の因子に対する因子負荷を完全にゼロにした」ことが理由だと思われます。g 以外の特殊因子の 値は, 「G 因子の影響を取り除いた 𝜔」という位置づけなので,使う機会は無いでしょう。また, 引数 return.total = TRUE とすると,𝜔𝑡 も出してくれます。ただ Chapter 6 でお話したよう に,一つの尺度の内的一貫性に関心がある場合には 𝜔𝑡 を優先的に使うことは無いと思うので, 基本的にはそのままで OK です。 7.12.2 高次因子モデル G 因子の位置づけに関して,場合によっては 図 7.25 のように各特殊因子の上位にあると考え るほうが妥当なケースがあるかもしれません(総合的な学力に対する「文系」「理系」なんかは まさにそれ) 。 図 7.25: 高次因子モデル このような場合に,全ての項目をまとめて一つの得点と考えた場合の内的一貫性は,先ほどの 𝜔ℎ とは異なる形になります。例えば一番左の項目 1 について式を展開すると(因子 𝑓𝐴 は内生変 *31 少し前までは semTools:reliability() という関数もあったのですが,すでに deprecated になっているの で semTools::compRelSEM() を使います。

97.

7.12 𝜔ℎ を求める 97 数となっているために誤差 𝜺𝐴 を追加して) , 𝐲1 = 𝐟𝐴 𝑏1 + 𝜺1 𝑔 = (𝐆𝑏𝐴 + 𝜺𝐴 )𝑏1 + 𝜺1 (7.48) error 𝑔 ⏞⏞ = 𝐆𝑏𝐴 𝑏1 + ⏞ 𝑏1⏞ 𝜺⏞ 𝐴 + 𝜺1 となるため,真値 𝑡 に相当する部分は 𝐆𝑏𝐴 𝑏1 となります。したがって,その係数 𝑏𝐴 𝑏1 を使っ 𝑔 𝑔 て,高次因子モデルにおける 𝜔ℎ𝑜 は 2 𝜔ℎ𝑜 = 𝐼 (∑𝑖=1 𝑏⋅𝑔 𝑏𝑖 ) 𝜎𝑦2total (7.49) となります。𝑏⋅𝑔 は項目によって 𝑏𝐴 か 𝑏𝐶 になるものです。 𝑔 𝑔 数理的にはそういう扱いですが,lavaan で行う場合にはそれほど難しくはありません。まずは いつも通りモデルを組みます。 (2 因子だと解が求められなかったので 3 因子分用意しています。 ) omega_ho を求めるために 1 2 3 4 5 6 7 8 9 10 11 model <- " f_A =~ Q1_1 + Q1_2 + Q1_3 + Q1_4 + Q1_5 f_C =~ Q1_6 + Q1_7 + Q1_8 + Q1_9 + Q1_10 f_E =~ Q1_11 + Q1_12 + Q1_13 + Q1_14 + Q1_15 # 高次因子の測定方程式 g =~ f_A + f_C + f_E " # ordered = TRUEにするとcompRelSEM()でエラーが出る result <- cfa(model, data = dat) あとは semTools::compRelSEM() に入れるだけです。 omega_ho を求める 1 compRelSEM(result, higher = "g") 1 2 f_A f_C f_E g 0.714 0.745 0.767 0.638 高次因子があるモデルについて計算する場合は,引数 higher に高次因子の名前を入れてあげ るだけです。先ほどと同じように g のところにある 0.638 という値が,𝜔ℎ𝑜 を表しているわけで す。このように,semTools::compRelSEM() を利用することで, 「完全な単純構造ではない場合 の 𝜔」や「独自因子の間に相関を認めた場合の 𝜔」などもフレキシブルに計算可能です。

98.

7.13 もう一つの SEM 98 7.13 もう一つの SEM これまでに紹介してきた SEM は,共分散構造分析という別名にも表れているように,観測変 数間の共分散(相関係数)をうまく復元できるようにモデルのパラメータを推定する方法です。 この共分散に基づく SEM (Covariance Based SEM: CB-SEM) に対して,主にマーケティング の分野として(とはいえ今では様々な分野で使われている),異なる SEM が独自に発展してい るようです。ということで最後に,もう一つの SEM こと PLS-SEM (Partial Least Squares SEM) を簡単に紹介します。 SEM は多変量解析の手法ですが,もともと多変量解析の手法としては重回帰分析や分散分析, クラスター分析などのシンプルな手法が存在しています。20 世紀にはこうした手法によって(あ るいはこうした手法に当てはめられるように RQ やデータを設計することで)多変量解析の研究 が行われていました。しかしこうした手法には,(a) 複雑なモデルを考えることができない,(b) 潜在変数を考えることができない(すべての変数は直接観測可能だとみなす),(c) 測定誤差と いうものを明示的に考えることができない,といった限界がありました(Haenlein & Kaplan, 2004)。これらの問題を解決するために考案されたのが (CB-)SEM ということになるようです。 そもそも SEM というものは「構造方程式モデリング」と訳される名が示すように,潜在変数を 含む複雑な変数間の関係性を(連立)方程式によって表現し,そのパラメータをデータから推定 する方法でした。PLS-SEM とは,その定式化および推定の方法として,CB-SEM とは別の文脈 から生まれてきたもののようです。 7.13.1 モデルの設計 したがって,PLS-SEM においても「構造方程式モデリング」としての基本的なコンセプトは CB-SEM と大きく変わりません。とりあえず観測変数間の関係性をモデルに起こすところから 始まります。図 7.26 は,ホテル利用者が行う評価に及ぼす影響をイメージした仮想的なグラフィ カルモデルです*32 。このモデルには,以下の 3 つの潜在変数およびそれらを測定する計 7 項目 の観測変数があるとします。 •【満足度】ホテルのサービスに対する満足度。以下の 3 項目によって,それぞれ 7 段階評 価で測定される。 – スタッフの対応は良かった。( sat_1) – ホテルは綺麗だった。( sat_2) – 食事は美味しかった。( sat_3) •【価格】 (主観的な)価格。 「1 泊あたりの価格はどう感じましたか。( price)」という 1 項 目に対して「とても安かった」から「とても高かった」までの 7 段階評価。 •【評価】ホテルの評価。以下の 3 項目によって,それぞれ 7 段階評価で測定される。 – このホテルのファンになった。( rate_1) – 機会があればまたこのホテルに泊まりたい。( rate_2) *32 このモデルはあくまでも仮想です。一応元ネタは Albers(2010)ですが,皆さんの知見に照らし合わせたとき に「そんな因果関係なわけないだろ!」といった批判は甘んじて受け入れます。

99.

7.13 もう一つの SEM 99 図 7.26: 仮想的なグラフィカルモデル – このホテルを他の人に薦めたい。( rate_3) このような図は,CB-SEM でも見ることがあるかと思いますが,いくつか気になる点があり ます。 1 点目は,3 つの観測変数から「満足度」という潜在変数に対して矢印が刺さっている点です。 これまでの CB-SEM の説明では,矢印は必ず潜在変数から観測変数に向かって刺さっていまし た。つまり逆向きです。実は PLS-SEM では,このような逆向きの矢印もモデルに含めることが できると言われています。 では,具体的にこの矢印の向きの違いは何を表しているのでしょうか。CB-SEM で用いられ てきた矢印の向きは,「複数の観測変数の共通原因としての潜在変数が存在する」ということを 考えていました。ここでは,潜在変数を測定するために「観測変数に反映された共通部分」を見 出そうとします。そういった意味で,reflective measurement と呼ばれることがあります。 図 7.26 の中では「評価」という因子は reflective なものとみなされています。rate_1-3 の項目 を見るとわかりますが,これらの項目への回答はきっと多くの人では互いに似たものになり,そ れは「ホテルに高い評価をした人ほどいずれも『当てはまる』寄りの回答をするだろう」という 推測が立ちます。 一方で,図 7.26 に登場した逆向きの矢印は,「複数の観測変数の総体として潜在変数が形作ら れる*33 」と考えます。そのため,こちらの矢印は formative measurement を表したものだと 呼ばれます。 「満足度」を評価する sat_1-3 の項目は,一部共通する側面はあるものの,共通の 「原因」を持っていないと考えられます。つまり,「従業員の対応は良いがあまり綺麗ではないホ テル」や「ご飯は美味しいが従業員が無愛想なホテル」などが存在することは容易に想像でき, また「(全体的な)満足度」というものはこうした個別の要素を組み合わせて決まってくるはず です。「総合的に見て満足だと感じたから,ご飯は美味しかったし従業員は良くしてくれた…気 *33 その点で,PLS-SEM は composite-based SEM と呼ばれることもあるようです(Hwang et al., 2020) 。 略すと CB-SEM になってしまいますね…

100.

7.13 もう一つの SEM がする」というようにレビューをする人はいないでしょう。 reflective と formative の違いを表した図が,図 7.27 です。reflective measurement では,各 観測変数が尋ねている内容(構成概念の一側面)の共通部分(積集合)が潜在変数として表れて いる,と考えます。そして各観測変数 ( rate_1-3) は共通の原因変数( 「評価」 )の影響を受けて いるため,基本的に相関係数は高いはずです。一方で formative measurement では,そもそも各 観測変数が高い相関を持っている必要はありません。そして潜在変数は,観測変数の和集合とし て規定されている,と考えているわけです。 図 7.27: 2 つの測定方法の違い(Hair, 2017, Exhibit 2.7 をもとに作成) ここまでの話は,どちらが良いとか悪いとかの話ではなく,あくまでも潜在変数の考え方の 違いの話です。どちらの考え方も本質的にはあり得るわけですが,CB-SEM では formative measurement は表現できない,という点において PLS-SEM を積極的に使う理由が生まれる かもしれませんね。 図 7.26 のモデルの違和感の 2 点目は, 「価格」という潜在変数が 1 つの観測変数のみと,しか も矢印ではなくただの線で繋がっている点です。このように PLS-SEM では,このように単一の 観測変数をそのまま潜在変数として利用することができると言われています。一方で CB-SEM では,モデルの識別のために,各潜在変数に対して少なくとも 3 つの観測変数が必要でした。 PLS-SEM で単一の観測変数を潜在変数扱いにしている理由は,どうやら計算上の都合によると ころが大きいです。というのも後ほど説明しますが,PLS-SEM では「観測変数から潜在変数の 得点を推定する(測定モデル) 」 「潜在変数同士の関係(パス係数)を推定する(構造モデル) 」と いう 2 つの計算を別々に行い,これらを交互に繰り返します。PLS-SEM ではこのうち構造モデ ルにおいて,観測変数と潜在変数の間のパス解析(回帰)を考えないために,観測変数を便宜的 にそのまま潜在変数として扱っているような気がします。したがって,単一観測変数から潜在変 数の得点を推定するといっても結局やっていることは恒等変換にすぎません。ちなみに CB-SEM の推定では構造モデルと測定モデルを区別せずにまとめて同時に推定しているので,このような 100

101.

7.13 もう一つの SEM 101 場合はわざわざ「潜在変数に置き換える」ことはせずに,潜在変数のまま扱うことができます。 7.13.2 推定 続いて PLS-SEM のパラメータ推定のイメージを紹介します。その前に CB-SEM におけるパ ラメータ推定の基本理念をおさらいすると,CB-SEM では「推定されたパラメータから復元さ れた共分散行列 𝚺」と「データにおける観測された共分散行列 𝐒」のズレが最も小さくなるよう にパラメータを推定していました。これはいわば,データを最も良く説明できるパラメータの組 を求める行為です。 これに対して PLS-SEM の基本理念は,内生潜在変数 (endogenous latent variable) を 予測した際の分散説明率を最大化するようにパラメータを推定していきます*34 。内生潜在変数 とは,他の(外生)潜在変数からの矢印が刺さっている潜在変数(図 7.26 では「評価」)です。 PLS-SEM では,最終的に内生潜在変数を被説明変数とした(重)回帰分析における分散説明 率=決定係数(𝑅2 )の値が最大になるように,以下に示した 4 つのステップを繰り返して推定を 行います。具体的な各ステップを見てみましょう(Henseler et al., 2012) 。 ステップ 1 とりあえず各潜在変数の得点を観測変数から求める(図 7.28 ) 。この時点では矢印の向きによ らず,すべて観測変数の重み付け和として求める。初期値は全ての重みを 1 とする(=単純な和 得点から始める) 。 図 7.28: 推定のステップ 1 ステップ 2 各内生潜在変数を対応する外生潜在変数によって回帰してパス係数を求める(図 7.29 ) 。普通 に最小二乗法で回帰してあげれば自ずと決定係数(𝑅2 )が最大になるパス係数を求めることがで きる。 *34 その点で,PLS-SEM は variance-based SEM と呼ばれることもあるようです。別名が多いですね。

102.

7.13 もう一つの SEM 102 図 7.29: 推定のステップ 2 ステップ 3 得られたパス係数を使って各内生潜在変数の値を再計算する(図 7.30 ) 。ここでは,内生潜在 変数の値を外生潜在変数の重み付け和として計算し,ステップ 1 で得られた値から置き換える。 外生潜在変数の値については多分ノータッチ。 図 7.30: 推定のステップ 3 ステップ 4 ステップ 1 で用いる潜在変数得点計算時の各観測変数の重みを以下の方法で置き換える (図 7.31 )。 a. reflective measurement の箇所は潜在変数得点と観測変数との相関係数に置き換える (mode A) 。 b. formative measurement の箇所は観測変数一つ一つから潜在変数への単回帰を行った回帰 係数に置き換える(mode B) 。 以上 4 つのステップを解が変わらなくなるまで繰り返すことで,最終的な推定値を得ます。細

103.

7.13 もう一つの SEM 103 図 7.31: 推定のステップ 4 かく見ると,PLS-SEM では図 7.28 ‐ 7.31 の中の点線で囲った部分ごとに計算をしていること になります。 7.13.3 CB-SEM と PLS-SEM の使い分け これまでに紹介してきた PLS-SEM の特徴を踏まえると,CB-SEM との使い分けのポイント が見えてきます。ここでは(Hair et al., 2021, Table 1.6)をもとに,使い分けのポイントをいく つか見てみましょう。 • 分析の目的が説明(観測されたデータ全体に最もよく当てはまるモデルパラメータを推定 すること)よりも予測(外生潜在変数から内生潜在変数をできるだけ精度良く予測・説明 すること)に関心がある場合は PLS-SEM が良い。 • formative measure な潜在変数が含まれる場合は,CB-SEM では難しいので PLS-SEM を使うしかない。 • サンプルサイズが小さい場合は PLS-SEM のほうが良い。というのも PLS-SEM は基本 的に回帰分析の組み合わせなので,CB-SEM と比べると少ないサンプルサイズでもそれ なりに安定した解が出やすい,らしい。 • 観測変数の(多変量)正規性が怪しい場合は PLS-SEM のほうが良い。というのも CBSEM は変数の分散共分散行列をもとに推定を行うが,その方法として,多変量正規性を 仮定した最尤法などが用いられるため,仮定が満たされない場合は厳しい。 PLS-SEM の利用に関するいくつかのレビュー論文によれば,PLS-SEM を使う理由として最 も多く挙げられているのが「サンプルサイズが小さい」,そして「データの非正規性」「予測が目 的」「モデルが複雑」などが続いているようです(e.g., Bayonne et al., 2020; Lin et al., 2020; Magno et al., 2022)。 しかし PLS-SEM にはそれなりの反対意見もあるようで,一部の人は「PLS-SEM はくそくら えだ」という感じもあります(e.g., Rönkkö et al., 2015)。ということで,理論(研究仮説)的 に PLS-SEM のほうが適切だと言える場合には PLS-SEM を使えばよいのですが,どちらを使

104.

7.14 (おまけ)lavaan で探索的因子分析 ​ 104 ​ えば良いかわからない(どちらでもいける)場合には,とりあえず CB-SEM を試してみて,解 が得られないなど特殊な事情がある場合に初めて PLS-SEM の利用を考えるくらいで良いのかも しれません*35 。 7.13.4 PLS-SEM を実行する方法 PLS-SEM を実行するためのソフトウェアとして,SmartPLS というものがよく用いられてい るようです。一応 R でも PLS-SEM を行うためのパッケージとして plssem や seminr (SEM in R) パッケージというものが作成されているので,関心がある方はそちらのパッケージを見て みてください。ちなみに Hair et al.(2021)は seminr パッケージの使い方を紹介している OA 本です。 7.14 (おまけ)lavaan で探索的因子分析 ​ ​ 2023 年 1 月にリリースされたバージョン 0.6-13 以降では,lavaan パッケージで探索的因子分 析が可能になっています。ただの探索的因子分析なら psych::fa() で十分なのですが,lavaan では SEM の枠組みと組み合わせることで EFA と CFA や回帰分析を組み合わせることができ る点が,もしかしたら便利かもしれません。こうしたモデルは特に Exploratory SEM(ESEM: Asparouhov & Muthén, 2009)と呼ばれている比較的新しい手法です。世間の注目を集めてい るかはわかりません。ということでこのおまけセクションでは,lavaan で探索的因子分析およ び ESEM を行う方法を紹介していきます。 7.14.1 lavaan で EFA を試してみる ​ ​ まずは普通に探索的因子分析を試してみます。Chapter 6 の 10 項目 2 因子モデル を再現して みましょう。lavaan で EFA を指定する方法は大きく分けると 2 種類です。 efa() 関数 ​ ​ シンプルな方法は,efa() 関数を利用するものです。 efa() 関数 1 2 3 # 使い方はpsych::fa()とほぼ同じ res_efa <- efa(dat[, paste0("Q1_", 1:10)], nfactors = 2, rotation = "oblimin") summary(res_efa) *35 とはいえ解が得られない理由がサンプルサイズが小さいせいで,努力で増やせるようなもの(企業データなどそ もそも集めにくいものでないの)であれば,安易に PLS-SEM に逃げるよりもサンプルサイズを増やすことを 先に検討すべきだと思いますよ。

105.

7.14 (おまけ)lavaan で探索的因子分析 ​ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 105 ​ This is lavaan 0.6-18 -- running exploratory factor analysis Estimator Rotation method Oblimin gamma Rotation algorithm (rstarts) Standardized metric Row weights ML OBLIMIN OBLIQUE 0 GPA (30) TRUE None Number of observations 2432 Fit measures: aic bic sabic chisq df pvalue cfi rmsea nfactors = 2 78530.51 78698.61 78606.47 375.946 26 0 0.932 0.074 Eigenvalues correlation matrix: ev1 3.078 ev10 0.440 ev2 1.834 ev3 0.896 ev4 0.823 ev5 0.722 ev6 0.684 ev7 0.530 Standardized loadings: (* = significant at 1% level) Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 f1 0.408* 0.661* 0.779* 0.464* 0.624* * f2 * * .* 0.567* 0.623* 0.551* 0.691* 0.587* unique.var 0.846 0.558 0.408 0.723 0.603 0.690 0.615 0.689 0.527 0.634 communalities 0.154 0.442 0.592 0.277 0.397 0.310 0.385 0.311 0.473 0.366 f2 f1 total Sum of sq (obliq) loadings 1.876 1.832 3.707 Proportion of total 0.506 0.494 1.000 Proportion var 0.188 0.183 0.371 Cumulative var 0.188 0.371 0.371 Factor correlations: (* = significant at 1% level) f1 f1 1.000 f2 ev8 0.523 ev9 0.469

106.

7.14 (おまけ)lavaan で探索的因子分析 ​ 47 f2 106 ​ 0.317* 1.000 回転方法を指定する引数は rotation です。psych::fa() では rotate だったのでご注意く ださい。ということで,かなり簡単に lavaan の出力形式で EFA の結果を出すことができまし た。lavaan::efa() の利点の一つは,自動的に因子負荷の検定を行ってくれるところです。SEM の枠組みにしたがって,回転後の因子負荷が 0 であるという帰無仮説のもとで検定をしていま す。デフォルトでは 1% 水準で有意のところに *がつくようになっていますが,これも引数で調 整可能です。ついでに因子負荷が小さいところも全て表示されるように書き換えてみましょう。 全ての因子負荷を表示させる 1 2 3 # cutoff: 指定した値より小さい因子負荷を表示しない # alpha.level: (*)をつける有意水準を指定する summary(res_efa, cutoff = 0, alpha.level = 0.05) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 This is lavaan 0.6-18 -- running exploratory factor analysis Estimator Rotation method Oblimin gamma Rotation algorithm (rstarts) Standardized metric Row weights ML OBLIMIN OBLIQUE 0 GPA (30) TRUE None Number of observations 2432 Fit measures: aic bic sabic chisq df pvalue cfi rmsea nfactors = 2 78530.51 78698.61 78606.47 375.946 26 0 0.932 0.074 Eigenvalues correlation matrix: ev1 3.078 ev10 0.440 ev2 1.834 ev3 0.896 ev4 0.823 ev5 0.722 ev6 0.684 ev7 0.530 Standardized loadings: (* = significant at 5% level) Q1_1 Q1_2 Q1_3 Q1_4 f1 f2 0.408* -0.069* 0.661* 0.011 0.779* -0.032* 0.464* 0.142* unique.var 0.846 0.558 0.408 0.723 communalities 0.154 0.442 0.592 0.277 ev8 0.523 ev9 0.469

107.

7.14 (おまけ)lavaan で探索的因子分析 ​ 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 107 ​ Q1_5 0.624* Q1_6 -0.036 Q1_7 -0.008 Q1_8 0.022 Q1_9 -0.012 Q1_10 0.049* 0.019 0.567* 0.623* 0.551* 0.691* 0.587* 0.603 0.690 0.615 0.689 0.527 0.634 0.397 0.310 0.385 0.311 0.473 0.366 f2 f1 total Sum of sq (obliq) loadings 1.876 1.832 3.707 Proportion of total 0.506 0.494 1.000 Proportion var 0.188 0.183 0.371 Cumulative var 0.188 0.371 0.371 Factor correlations: (* = significant at 5% level) f1 f2 f1 1.000 0.317* f2 1.000 ちなみに lavaan のデフォルトでは,最尤法によってパラメータの推定を行っています。した がって,上記の結果は psych::fa() で fm = "ml"を指定したときに同じになるはずです。 psych::fa() 関数と比べる 1 2 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 res_fa <- psych::fa(dat[, paste0("Q1_", 1:10)], nfactors = 2, fm = "ml") # 因子負荷だけ表示する res_fa$loadings ​ ​ Loadings: ML2 ML1 Q1_1 0.408 Q1_2 0.661 Q1_3 0.779 Q1_4 0.142 0.464 Q1_5 0.624 Q1_6 0.567 Q1_7 0.623 Q1_8 0.551 Q1_9 0.691 Q1_10 0.587 ML2 ML1 SS loadings 1.863 1.819 Proportion Var 0.186 0.182

108.

7.14 (おまけ)lavaan で探索的因子分析 ​ 18 108 ​ Cumulative Var 0.186 0.368 分散説明率のところには細かい違いはあるのですが,因子負荷に関しては確かに同じ結果が得 られました。 あえて lavaan::efa() 関数を使う別の利点は,複数の因子数を一気に実行できることです。 引数 nfactors に整数のベクトルを与えてあげると,すべての因子数で実行した結果をまとめて 一つのオブジェクトで返してくれます。 色々な因子数を試す 1 2 3 4 # 一個ずつ順番にやっているだけなので指定した数が多いほど時間はかかる # ちなみにrotationのデフォルトは"geomin" res_efa <- efa(dat[, paste0("Q1_", 1:10)], nfactors = 1:3) summary(res_efa) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 This is lavaan 0.6-18 -- running exploratory factor analysis Estimator Rotation method Geomin epsilon Rotation algorithm (rstarts) Standardized metric Row weights ML GEOMIN OBLIQUE 0.001 GPA (30) TRUE None Number of observations 2432 Overview models: aic bic sabic chisq df pvalue cfi rmsea nfactors = 1 80259.06 80374.99 80311.44 2122.495 35 0 0.595 0.157 nfactors = 2 78530.51 78698.61 78606.47 375.946 26 0 0.932 0.074 nfactors = 3 78387.85 78602.32 78484.76 217.286 18 0 0.961 0.067 Eigenvalues correlation matrix: ev1 3.078 ev10 0.440 ev2 1.834 ev3 0.896 Number of factors: ev4 0.823 ev5 0.722 ev6 0.684 ev7 0.530 1 Standardized loadings: (* = significant at 1% level) f1 unique.var communalities ev8 0.523 ev9 0.469

109.

7.14 (おまけ)lavaan で探索的因子分析 ​ 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 109 ​ .* 0.502* 0.523* 0.487* 0.480* 0.439* 0.507* 0.480* 0.552* 0.531* 0.934 0.748 0.727 0.763 0.769 0.808 0.742 0.769 0.696 0.718 0.066 0.252 0.273 0.237 0.231 0.192 0.258 0.231 0.304 0.282 f1 Sum of squared loadings 2.327 Proportion of total 1.000 Proportion var 0.233 Cumulative var 0.233 Number of factors: 2 Standardized loadings: (* = significant at 1% level) Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 f1 0.407* 0.660* 0.778* 0.464* 0.623* f2 * .* 0.567* 0.622* 0.550* 0.690* 0.587* unique.var 0.846 0.558 0.408 0.723 0.603 0.690 0.615 0.689 0.527 0.634 communalities 0.154 0.442 0.592 0.277 0.397 0.310 0.385 0.311 0.473 0.366 f2 f1 total Sum of sq (obliq) loadings 1.876 1.831 3.707 Proportion of total 0.506 0.494 1.000 Proportion var 0.188 0.183 0.371 Cumulative var 0.188 0.371 0.371 Factor correlations: (* = significant at 1% level) f1 f2 f1 1.000 0.309* f2 1.000 Number of factors: 3

110.

7.14 (おまけ)lavaan で探索的因子分析 ​ 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 110 ​ Standardized loadings: (* = significant at 1% level) Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 f1 0.408* 0.671* 0.796* 0.475* 0.636* f2 .* * f3 .* 0.379* 0.472* .* 0.448* 0.492* 0.472* 0.793* 0.600* unique.var 0.798 0.555 0.400 0.725 0.601 0.637 0.496 0.709 0.386 0.614 communalities 0.202 0.445 0.600 0.275 0.399 0.363 0.504 0.291 0.614 0.386 f1 f3 f2 total Sum of sq (obliq) loadings 1.873 1.714 0.491 4.079 Proportion of total 0.459 0.420 0.120 1.000 Proportion var 0.187 0.171 0.049 0.408 Cumulative var 0.187 0.359 0.408 0.408 Factor correlations: (* = significant at 1% level) f1 f2 f3 f1 1.000 0.142 0.325* f2 f3 1.000 0.076 1.000 出 力 さ れ る オ ブ ジ ェ ク ト は, あ く ま で も lavaan の 形 式 に 沿 っ て い る た め, 例 え ば fitMeasures() 関数を利用して(SEM 的な)適合度指標を出して,因子数を決める参考にする ことも可能だったりします。 EFA で SEM 的適合度指標 1 fitMeasures(res_efa) 1 2 3 4 5 6 7 8 9 npar fmin chisq df pvalue baseline.chisq baseline.df baseline.pvalue nfct=1 20.000 0.436 2122.495 35.000 0.000 5201.585 45.000 0.000 nfct=2 29.000 0.077 375.946 26.000 0.000 5201.585 45.000 0.000 nfct=3 37.000 0.045 217.286 18.000 0.000 5201.585 45.000 0.000

111.

7.14 (おまけ)lavaan で探索的因子分析 ​ 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 ​ cfi 0.595 0.932 0.961 tli 0.480 0.883 0.903 nnfi 0.480 0.883 0.903 rfi 0.475 0.875 0.896 nfi 0.592 0.928 0.958 pnfi 0.460 0.536 0.383 ifi 0.596 0.932 0.962 rni 0.595 0.932 0.961 logl -40109.529 -39236.255 -39156.925 unrestricted.logl -39048.282 -39048.282 -39048.282 aic 80259.058 78530.510 78387.849 bic 80374.987 78698.607 78602.319 ntotal 2432.000 2432.000 2432.000 bic2 80311.443 78606.467 78484.761 rmsea 0.157 0.074 0.067 rmsea.ci.lower 0.151 0.068 0.060 rmsea.ci.upper 0.162 0.081 0.076 rmsea.ci.level 0.900 0.900 0.900 rmsea.pvalue 0.000 0.000 0.000 rmsea.close.h0 0.050 0.050 0.050 rmsea.notclose.pvalue 1.000 0.087 0.006 rmsea.notclose.h0 0.080 0.080 0.080 rmr 0.201 0.065 0.049 rmr_nomean 0.201 0.065 0.049 srmr 0.115 0.034 0.026 srmr_bentler 0.115 0.034 0.026 srmr_bentler_nomean 0.115 0.034 0.026 crmr 0.127 0.038 0.028 crmr_nomean 0.127 0.038 0.028 srmr_mplus 0.115 0.034 0.026 srmr_mplus_nomean 0.115 0.034 0.026 cn_05 58.064 252.548 324.123 cn_01 66.704 296.256 390.563 gfi 0.800 0.970 0.982 agfi 0.685 0.936 0.946 pgfi 0.509 0.458 0.322 mfi 0.651 0.931 0.960 ecvi 0.889 0.178 0.120 今回の結果では,どうやら 2 因子モデルよりも 3 因子モデルのほうがモデル適合度は高いよう です。ただこのあたりは因子分析のときにお話したように,最終的には解釈可能性までを視野に 入れて決めるようにしましょう。 111

112.
[beta]
7.14 (おまけ)lavaan で探索的因子分析
​

112

​

モデル式で指定する

lavaan で EFA を実行するもう一つの方法は,「モデル式で EFA であることを指定する」と
いうものです。これまでにこの Chapter では,変数名の前に 0*をつけることでその値を固定し
たり(Section 7.7.1 )
,名前をつけることで等値制約を置く方法(Section 7.10 )を紹介しまし
た。これと同じ要領で,因子名の前に「この因子にどの項目がかかるかは EFA 的に決めてくだ
さい」ということを指定する記号を書き足すことができるのです。
モデル式で EFA を指定する
1
2
3
4
5
6
7

# 変数名が多いとしんどいね…
model_efa <- '
efa("f12")*f1 =~
Q1_1 + Q1_2 + Q1_3 + Q1_4 + Q1_5 + Q1_6 + Q1_7 + Q1_8 + Q1_9 + Q1_10
efa("f12")*f2 =~
Q1_1 + Q1_2 + Q1_3 + Q1_4 + Q1_5 + Q1_6 + Q1_7 + Q1_8 + Q1_9 + Q1_10
'

EFA 的に推定&回転をしてほしい因子名の前に efa() という記号をかけてあげます。カッコ
の中は特に指定はありません(後で説明)。とりあえずここでは F1 と F2 の間の EFA であるこ
とがわかりやすいように "f12"としましたが,例えば efa("hoge")*f1 =~などとしても( f1
と f2 に同じ名前がついていれば)OK です。

EFA で推定
1
2

result_efa <- cfa(model_efa, data = dat, rotation = "oblimin")
summary(result_efa, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

lavaan 0.6-18 ended normally after 1 iteration
Estimator
Optimization method
Number of model parameters
Row rank of the constraints matrix
Rotation method
Oblimin gamma
Rotation algorithm (rstarts)
Standardized metric
Row weights
Number of observations
Model Test User Model:

ML
NLMINB
31
2
OBLIMIN OBLIQUE
0
GPA (30)
TRUE
None
2432

113.

7.14 (おまけ)lavaan で探索的因子分析 ​ 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 113 ​ Test statistic Degrees of freedom P-value (Chi-square) 375.946 26 0.000 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Latent Variables: f1 =~ f12 Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 f2 =~ f12 Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.574 0.775 1.017 0.686 0.788 -0.044 -0.011 0.029 -0.016 0.079 0.034 0.026 0.028 0.034 0.028 0.024 0.023 0.025 0.020 0.031 17.024 29.811 36.231 20.081 27.908 -1.878 -0.459 1.133 -0.795 2.592 0.000 0.000 0.000 0.000 0.000 0.060 0.646 0.257 0.427 0.010 0.574 0.775 1.017 0.686 0.788 -0.044 -0.011 0.029 -0.016 0.079 0.408 0.661 0.779 0.464 0.624 -0.036 -0.008 0.022 -0.012 0.049 -0.097 0.013 -0.042 0.210 0.024 0.699 0.820 0.709 0.951 0.958 0.033 0.020 0.015 0.033 0.023 0.028 0.030 0.030 0.031 0.037 -2.981 0.682 -2.731 6.430 1.056 24.527 27.497 23.759 31.181 25.724 0.003 0.495 0.006 0.000 0.291 0.000 0.000 0.000 0.000 0.000 -0.097 0.013 -0.042 0.210 0.024 0.699 0.820 0.709 0.951 0.958 -0.069 0.011 -0.032 0.142 0.019 0.567 0.623 0.551 0.691 0.587 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.317 0.025 12.921 0.000 0.317 0.317 Estimate 1.672 0.767 0.695 1.585 Std.Err 0.051 0.029 0.037 0.050 z-value 32.747 26.155 18.788 31.457 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.672 0.767 0.695 1.585 Std.all 0.846 0.558 0.408 0.723 Covariances: f1 ~~ f2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4

114.

7.14 (おまけ)lavaan で探索的因子分析 ​ 64 65 66 67 68 69 70 71 .Q1_5 .Q1_6 .Q1_7 .Q1_8 .Q1_9 .Q1_10 f1 f2 114 ​ 0.962 1.046 1.064 1.142 0.998 1.687 1.000 1.000 0.035 0.036 0.039 0.038 0.041 0.059 27.799 29.327 27.338 29.675 24.060 28.395 0.000 0.000 0.000 0.000 0.000 0.000 0.962 1.046 1.064 1.142 0.998 1.687 1.000 1.000 0.603 0.690 0.615 0.689 0.527 0.634 1.000 1.000 だいぶ lavaan の見慣れた形で出力されてくれました。結果はもちろん lavaan::efa() のと きと同じ値なので説明は省略します。 実際のところ,EFA をするだけであれば efa() 関数を使っておけば良いと思います*36 。モデ ル式での指定方法は,このあとの ESEM で必要になってくるのです…。 7.14.2 Exploratory SEM (ESEM) ESEM は,SEM と EFA を組み合わせたようなものです。この背景には,そもそも CFA を探 索的に使っているケースが割と存在する,ということがあるようです(Browne, 2001) 。例えば Section 7.7 で紹介したように,モデルの適合度を改善するためにある場所にパスを足したり引 いたりすることは,まさに explotaroty といって良いでしょう。また,自分で作成した尺度や, 手元のデータで因子構造が再現できる怪しいデータを用いて SEM を実行する場合には,通常ま ず EFA で因子構造・因子得点を出した上で,これを SEM の中に投入することが多くあります。 ならばもういっそ全部ひっくるめて一気にやってしまおう,というモチベーションもあるのかも しれません。 ということで ESEM を試してみましょう。ここでは 図 7.32 のようなモデルを考えてみます。 左側の 6 項目と右側の 6 項目は,それぞれ異なる尺度を表しています(以後,左側を尺度 A,右 側を尺度 B と呼びます)。想定する因子数だけは決まっていて,それぞれが 2 因子を測定する尺 度です。さらに,尺度 A の一方の因子が尺度 B の一方の因子に影響を与える,という因子間の 関係性(回帰)も仮説として検証したいとします。 このモデルを SEM で実行する場合には,尺度 A・B の中の各項目がそれぞれどちらの因子に 所属するかを明確に決める必要がありました。図 7.32 で言えば,青い点線のところにパスを許 容しない(=因子負荷は厳密にゼロとする)のが SEM でした。一方 ESEM では,この青い点線 のパス (cross-loadings) を許容します*37 。つまり,尺度 A に含まれる 2 因子(𝑓1 , 𝑓2 )は 6 項目 から EFA によって推定し,尺度 B の 6 項目からも同様に 2 因子(𝑓3 , 𝑓4 )を推定する,という ことです。そして,小さい因子負荷もそのまま残して SEM の適合度指標の計算などを行います。 言い換えると,ESEM は SEM の制約を緩めたモデルあるいは EFA に部分的な制約を加えた モデルという位置づけになっているわけです。 *36 もっと言えばここまでの話は psych::fa() でも何一つ問題はないんですけどね。 *37 もちろん,そもそもどこのパスが黒か青かわからない(完全に探索的な)状態でも ESEM は実行可能です。と いうか ESEM の推定ではパスの色は区別していない,はず。

115.

7.14 (おまけ)lavaan で探索的因子分析 ​ ​ 図 7.32: ESEM モデル では実際に 図 7.32 の ESEM モデルを書き下してみましょう。先程出てきた efa("")*の記 法を使って書いていきます。 ESEM のモデル式 1 2 3 4 5 6 7 8 9 10 11 12 model_esem <- ' # 尺度AのEFA efa("f12")*f1 =~ Q1_1 + Q1_2 + Q1_3 + Q1_6 + Q1_7 + Q1_8 efa("f12")*f2 =~ Q1_1 + Q1_2 + Q1_3 + Q1_6 + Q1_7 + Q1_8 # 尺度BのEFA efa("f34")*f3 =~ Q1_11 + Q1_12 + Q1_13 + Q1_16 + Q1_17 + Q1_18 efa("f34")*f4 =~ Q1_11 + Q1_12 + Q1_13 + Q1_16 + Q1_17 + Q1_18 # 因子間の回帰 f3 ~ f1 f4 ~ f2 ' 尺度 A と尺度 B はそれぞれ異なる因子を測定しているため,例えば Q1_1 が f3 や f4 にかか ることはありません(因子負荷は 0) 。そして因子の回転は,「 f1 と f2 が単純構造に近づくよ うに」「 f3 と f4 が単純構造に近づくように」を独立に実行していきます。このことを表すため に,f1 と f2 の前には efa("f12")*,f3 と f4 の前には efa("f34")*というように,異なる名 前の efa をかけているのです。 あとは推定するだけです。 115

116.
[beta]
7.14 (おまけ)lavaan で探索的因子分析
​

116

​

ESEM の推定
1
2
3

# EFA部分があるのでrotationを指定可能
result_esem <- sem(model_esem, data = dat, rotation = "oblimin")
summary(result_esem, standardized = TRUE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

lavaan 0.6-18 ended normally after 29 iterations
Estimator
Optimization method
Number of model parameters
Row rank of the constraints matrix
Rotation method
Oblimin gamma
Rotation algorithm (rstarts)
Standardized metric
Row weights

ML
NLMINB
40
4
OBLIMIN OBLIQUE
0
GPA (30)
TRUE
None

Number of observations

2432

Model Test User Model:
Test statistic
Degrees of freedom
P-value (Chi-square)

422.462
42
0.000

Parameter Estimates:
Standard errors
Information
Information saturated (h1) model

Standard
Expected
Structured

Latent Variables:
f1 =~ f12
Q1_1
Q1_2
Q1_3
Q1_6
Q1_7
Q1_8
f2 =~ f12
Q1_1
Q1_2
Q1_3

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.607
0.856
0.909
-0.021
-0.017
0.099

0.034
0.029
0.032
0.021
0.016
0.028

17.755
29.726
28.397
-0.996
-1.039
3.559

0.000
0.000
0.000
0.319
0.299
0.000

0.607
0.856
0.909
-0.021
-0.017
0.099

0.432
0.730
0.696
-0.017
-0.013
0.077

-0.067
0.003
0.013

0.033
0.015
0.019

-2.028
0.179
0.660

0.043
0.858
0.509

-0.067
0.003
0.013

-0.048
0.002
0.010

117.

7.14 (おまけ)lavaan で探索的因子分析 ​ 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 Q1_6 Q1_7 Q1_8 f3 =~ f34 Q1_11 Q1_12 Q1_13 Q1_16 Q1_17 Q1_18 f4 =~ f34 Q1_11 Q1_12 Q1_13 Q1_16 Q1_17 Q1_18 117 ​ 0.763 0.930 0.634 0.034 0.038 0.033 22.180 24.354 19.016 0.000 0.000 0.000 0.763 0.930 0.634 0.620 0.707 0.493 0.880 0.979 0.649 0.024 -0.011 -0.039 0.034 0.037 0.028 0.013 0.014 0.023 25.566 26.402 23.054 1.822 -0.788 -1.695 0.000 0.000 0.000 0.068 0.431 0.090 1.037 1.153 0.765 0.028 -0.013 -0.046 0.636 0.716 0.568 0.018 -0.008 -0.029 0.111 -0.120 0.082 1.351 1.272 1.036 0.024 0.021 0.023 0.030 0.029 0.031 4.606 -5.669 3.491 45.238 43.650 32.966 0.000 0.000 0.000 0.000 0.000 0.000 0.111 -0.121 0.082 1.355 1.277 1.040 0.068 -0.075 0.061 0.861 0.834 0.653 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.637 0.039 16.261 0.000 0.541 0.541 -0.053 0.027 -1.971 0.049 -0.052 -0.052 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.264 0.028 9.314 0.000 0.264 0.264 -0.220 0.028 -7.764 0.000 -0.220 -0.220 Estimate 1.623 0.641 0.872 0.942 0.874 1.212 1.619 1.190 1.252 0.657 0.705 1.431 Std.Err 0.051 0.037 0.045 0.045 0.059 0.043 0.066 0.066 0.045 0.044 0.041 0.048 z-value 31.654 17.164 19.547 20.888 14.784 28.146 24.478 18.083 27.828 14.817 17.221 30.098 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.623 0.641 0.872 0.942 0.874 1.212 1.619 1.190 1.252 0.657 0.705 1.431 Std.all 0.822 0.466 0.512 0.621 0.505 0.731 0.610 0.459 0.689 0.265 0.301 0.564 Regressions: f3 ~ f1 f4 ~ f2 Covariances: f1 ~~ f2 .f3 ~~ .f4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 .Q1_11 .Q1_12 .Q1_13 .Q1_16 .Q1_17 .Q1_18

118.
[beta]
7.14 (おまけ)lavaan で探索的因子分析
​

87
88
89
90

f1
f2
.f3
.f4

118

​

1.000
1.000
1.000
1.000

1.000
1.000
0.720
0.993

1.000
1.000
0.720
0.993

無事,小さい因子負荷を残して推定が完了しました。ESEM の利点は,このように小さい因子
負荷を許容することでモデル適合度が SEM よりも良くなる可能性がある,という点にあります。
試しに 図 7.32 から青い点線を取り除いた SEM モデルと適合度を比べてみましょう。
本来の SEM モデルを作って比較してみる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

model_sem <- "
# 尺度A
f1 =~ Q1_1 + Q1_2 + Q1_3
f2 =~ Q1_6 + Q1_7 + Q1_8
# 尺度B
f3 =~ Q1_11 + Q1_12 + Q1_13
f4 =~ Q1_16 + Q1_17 + Q1_18

1
2
3
4
5
6
7
8
9
10
11
12
13
14

################### Nested Model Comparison #########################

# 因子間の回帰
f3 ~ f1
f4 ~ f2
"
# 推定
result_sem <- sem(model_sem, data = dat, std.lv = TRUE)
# 適合度の比較
# SEMはESEMの特殊なケース(一部の因子負荷を0に固定)なのでnested
summary(compareFit(result_esem, result_sem))

Chi-Squared Difference Test
Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
result_esem 42 96399 96607 422.46
result_sem 50 96485 96647 524.93
102.47 0.069681
8 < 2.2e-16
result_esem
result_sem ***
--Signif. codes:

0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

119.

7.14 (おまけ)lavaan で探索的因子分析 ​ 15 16 17 18 19 20 21 22 23 24 25 ​ ####################### Model Fit Indices ########################### chisq df pvalue rmsea cfi tli srmr aic result_esem 422.462† 42 .000 .061† .944† .913† .046† 96398.512† result_sem 524.928 50 .000 .062 .931 .908 .054 96484.978 bic result_esem 96607.185† result_sem 96647.279 ################## Differences in Fit Indices ####################### df rmsea cfi tli srmr aic bic result_sem - result_esem 8 0.001 -0.014 -0.004 0.007 86.466 40.094 今回の比較では,ESEM の結果の方が適合度が良いことがわかります。特に青い点線にあたる ところに 0 ではない因子負荷があるような場合には,SEM で無理に 0 に制約をかけてしまうと 適合度が悪化してしまう可能性がある,ということですね。 119

120.

参考文献 参考文献 Adachi, K. (2020). Matrix-based introduction to multivariate data analysis (2nd ed.). Springer. https://doi.org/10.1007/978-981-15-4103-2 Akaike, H. (1998–1969). Information theory and an extension of the maximum likelihood principle. In E. Parzen, K. Tanabe, & G. Kitagawa (Eds.), Selected papers of Hirotugu Akaike (pp. 199–213). Springer (Original work published 1969). https://doi.org/10.1007/ 978-1-4612-1694-0_15(Original work published 1969) Albers, S. (2010). PLS and success factor studies in marketing. In V. Esposito Vinzi, W. W. Chin, J. Henseler, & H. Wang (Eds.), Handbook of partial least squares: concepts, methods and applications (pp. 409–425). Springer Berlin Heidelberg. https://doi.org/10.1007/9783-540-32827-8 Asparouhov, T., & Muthén, B. (2009). Exploratory structural equation modeling. Structural Equation Modeling: A Multidisciplinary Journal, 16(3), 397–438. https: //doi.org/10.1080/10705510903008204 Baron, R. M., & Kenny, D. A. (1986). The moderator–mediator variable distinction in social psychological research: Conceptual, strategic, and statistical considerations. Journal of Personality and Social Psychology, 51(6), 1173–1182. https://doi.org/10.1037/00223514.51.6.1173 Bayonne, E., Marin-Garcia, J. A., & Alfalla-Luque, R. (2020). Partial least squares (PLS) in operations management research: insights from a systematic literature review. Journal of Industrial Engineering and Management, 13(3), 565–597. https://doi.org/10.3926/ji em.3416 Bentler, P. M. (1983). Some contributions to efficient statistics in structural models: Specification and estimation of moment structures. Psychometrika, 48(4), 493–517. https://doi.org/10.1007/BF02293875 Bentler, P. M. (1990). Comparative fit indexes in structural models. Psychological Bulletin, 107 (2), 238–246. https://doi.org/10.1037/0033-2909.107.2.238 120

121.

参考文献 Browne, M. W. (2001). An overview of analytic rotation in exploratory factor analysis. Multivariate Behavioral Research, 36(1), 111–150. https://doi.org/10.1207/S15327906M BR3601_05 Haenlein, M., & Kaplan, A. M. (2004). A beginner’s guide to partial least squares analysis. Understanding Statistics, 3(4), 283–297. https://doi.org/10.1207/s15328031us0304_4 Hair, J. F. (Ed.). (2017). A primer on partial least squares structural equation modeling (PLS-SEM) (Second edition). Sage. Hair, J. F., Hult, T. M., Ringle, C. M., Sarstedt, M., Danks, N. P., & Ray, S. (2021). Partial least squares structural equation modeling (PLS-SEM) using R: a workbook. Classroom Companion: Business. Springer. Hancock, G. R., Stapleton, L. M., & Mueller, R. O. (2019). Structural equation modeling. In The reviewer’s guide to quantitative methods in the social sciences (2nd ed., pp. 445–456). Routledge. Henseler, J., Ringle, C. M., & Sarstedt, M. (2012). Using partial least squares path modeling in advertising research: basic concepts and recent issues. In S. Okazaki (Ed.), Handbook of research on international advertising (pp. 252–276). E. Elgar. 星野 崇宏・岡田 謙介・前田忠彦(2005) .構造方程式モデリングにおける適合度指標とモデル 改善について: 展望とシミュレーション研究による新たな知見 行動計量学,32(2), 209–235. https://doi.org/10.2333/jbhmk.32.209 Hu, L., & Bentler, P. M. (1999). Cutoff criteria for fit indexes in covariance structure analysis: Conventional criteria versus new alternatives. Structural Equation Modeling: A Multidisciplinary Journal, 6(1), 1–55. https://doi.org/10.1080/10705519909540118 Hwang, H., Sarstedt, M., Cheah, J. H., & Ringle, C. M. (2020). A concept analysis of methodological research on composite-based structural equation modeling: bridging PLSPM and GSCA. Behaviormetrika, 47 (1), 219–241. https://doi.org/10.1007/s41237019-00085-5 Kang, H., & Ahn, J.-W. (2021). Model setting and interpretation of results in research using structural equation modeling: a checklist with guiding questions for reporting. Asian Nursing Research, 15(3), 157–162. https://doi.org/10.1016/j.anr.2021.06.001 Lin, H.-M., Lee, M.-H., Liang, J.-C., Chang, H.-Y., Huang, P., & Tsai, C.-C. (2020). A review of using partial least square structural equation modeling in e-learning research. British Journal of Educational Technology, 51(4), 1354–1372. https://doi.org/10.1111/bj et.12890 121

122.

参考文献 Magno, F., Cassia, F., & Ringle, C. M. (2022). A brief review of partial least squares structural equation modeling (PLS-SEM) use in quality management studies. The TQM Journal, ahead-of-print(ahead-of-print). https://doi.org/10.1108/TQM-06-2022-0197 Mayekawa, S. (1994). Equivalent path models in linear structural equation models. Behaviormetrika, 21(1), 79–96. https://doi.org/10.2333/bhmk.21.79 McNeish, D., & Wolf, M. G. (2020). Thinking twice about sum scores. Behavior Research Methods, 52(6), 2287–2305. https://doi.org/10.3758/s13428-020-01398-0 Mulaik, S. A., James, L. R., Van Alstine, J., Bennett, N., Lind, S., & Stilwell, C. D. (1989). Evaluation of goodness-of-fit indices for structural equation models. Psychological Bulletin, 105(3), 430–445. https://doi.org/10.1037/0033-2909.105.3.430 Rönkkö, M., McIntosh, C. N., & Antonakis, J. (2015). On the adoption of partial least squares in psychological research: Caveat emptor. Personality and Individual Differences, 87, 76–84. https://doi.org/10.1016/j.paid.2015.07.019 Schwarz, G. (1978). Estimating the dimension of a model. The Annals of Statistics, 6(2), 461–464. https://doi.org/10.1214/aos/1176344136 Steiger, J. H., & Lind, J. C. (1980). Statistically based tests for the number of common factors. Paper Presented at the Psychometric Society Annual Meeting. 豊田 秀樹(2014) .共分散構造分析 [R 編] 東京図書 Tucker, L. R., & Lewis, C. (1973). A reliability coefficient for maximum likelihood factor analysis. Psychometrika, 38(1), 1–10. https://doi.org/10.1007/BF02291170 122