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

13.8K Views

July 25, 23

スライド概要

神戸大学経営学研究科で2022年度より担当している「統計的方法論特殊研究(多変量解析)」の講義資料「07_構造方程式モデリング」です。
【変更履歴】
2026/06/05: 因子負荷の添字の順序のミス,因子名の間違い,数値例が不偏推定値(cov())だったところをきちんと標本共分散行列に修正しました
2025/12/25: いくつかのタイポを修正,最初の説明に計算例を追加しました
2025/11/30: SEMのトレースルールの紹介を追加しました
2025/11/05: lavaanで形成的測定(formative measurement)を行う方法を追加しました
2025/02/05: 全体的に内容に手を入れました。RmarkdownからQuartoに変更しました。

profile-image

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

シェア

またはPlayer版

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

ダウンロード

関連スライド

各ページのテキスト
1.

Chapter 7 構造方程式モデリング 1 Chapter 7 構造方程式モデリング 複数の観測変数間の関係性について柔軟なモデルをあてはめて分析を行う構造方程式モデリング について,前半では理論的な考え方と lavaan でのやり方を説明し,後半では実践上のいくつかの トピック (モデル適合度・モデル修正・多母集団同時分析・PLS-SEM など) を解説しています。 本資料は,神戸大学経営学研究科で 2022 年度より担当している「統計的方法論特殊研究(多変 量解析)」および京都大学教育学部で 2025 年度より担当している「心理・教育測定演習」の講義資 料です。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 というパッケージを用いるのが最もメジャーです。事前にインストー   ル&読み込みをしておきましょう。合わせて,このチャプターで使用するいくつかのパッケージも インストールしておきます。 ↓本 Chapter で使用するファイルのダウンロードはこちらから chapter04.rds   事前準備 1 2 3 4 # まだインストールしていない人は # install.packages("lavaan") # install.packages("lavaanPlot") # install.packages("semTools")

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

5
6
7
8

2

# 前半ではlavaanのみ使います。
library(lavaan)
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 ⎤
⎥
𝑏32 + 𝜎𝜺23 ⎦

(7.2)

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

𝑠2𝑦1
⎡
𝐒 = ⎢𝑠𝑦2 ,𝑦1
⎣𝑠𝑦3 ,𝑦1

𝑠𝑦1 ,𝑦2
𝑠2𝑦2
𝑠𝑦3 ,𝑦2

𝑠𝑦1 ,𝑦3
𝑠𝑦2 ,𝑦3 ⎤
⎥
𝑠2𝑦3 ⎦

(7.3)

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








分散共分散は cov(dat[,paste0("Q1_",1:3)]) * ((nrow(dat) - 1) / nrow(dat)) によっ




3.

7.1 因子分析の見方を変える て*1 具体的に 3 1.975 0.581 𝐒=⎡ ⎢0.581 1.375 ⎣0.504 0.761 0.504 0.761⎤ ⎥ 1.705⎦ という値が得られます。そして構造方程式モデリングでは,𝚺 の値が 𝐒 にできるだけ近づくよう に母数 (パラメータ)を推定します。 実際に (7.2) 式の 𝚺 と (7.3) 式の 𝐒 の同じ項をイコールで結 ぶと, 2 2 2 ⎧ 𝑠𝑦1 = 𝑏1 + 𝜎𝜺1 { 2 { 𝑠𝑦2 = 𝑏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.975 = 𝑏1 + 𝜎𝜺1 { {1.375 = 𝑏22 + 𝜎𝜺22 { {1.705 = 𝑏2 + 𝜎2 𝜺3 3 ⎨0.581 = 𝑏 𝑏 1 2 { {0.504 = 𝑏 𝑏 { 1 3 { ⎩0.761 = 𝑏2 𝑏3 となり, これを解くと ⎧ 𝑏1 = 0.620 { 𝑏 = 0.937 { 2 { { 𝑏3 = 0.812 ⎨𝜎𝜺21 = 1.590 { {𝜎2 = 0.496 { 𝜺2 { 2 ⎩𝜎𝜺3 = 1.045 (7.5) という解が得られます。図 7.1 に書き加えたならば 図 7.2 のようになります。 *1 cov() 関数で得られるのは不偏共分散行列ですが,SEM の推定に用いる 𝐒 は標本共分散行列なので,𝑃 − 1/𝑃   倍する必要があります。

4.

7.1 因子分析の見方を変える 4 図 7.2: 因子分析モデルの解 もちろん (7.5) 式の値を (7.2) 式に代入すれば, 𝑏12 + 𝜎𝜺21 ⎡ 𝚺 = ⎢ 𝑏2 𝑏1 ⎣ 𝑏3 𝑏1 𝑏1 𝑏2 𝑏22 + 𝜎𝜺22 𝑏3 𝑏2 𝑏1 𝑏3 𝑏2 𝑏3 ⎤ ⎥ 𝑏32 + 𝜎𝜺23 ⎦ 0.6202 + 1.590 ⎡ = ⎢ 0.937 × 0.620 ⎣ 0.812 × 0.620 0.620 × 0.937 0.620 × 0.812 0.9372 + 0.496 0.937 × 0.812 ⎤ ⎥ 0.812 × 0.937 0.8122 + 1.045⎦ 1.975 0.581 ≈⎡ ⎢0.581 1.375 ⎣0.504 0.761 =𝐒 0.504 0.761⎤ ⎥ 1.705⎦ (7.6) というように,𝚺 は 𝐒 と (丸め誤差を除けば) 完全に一致することが確認できます。 グラフィカルモデルでは,観測変数を四角形で,潜在変数を楕円で表していました。図 7.2 とパ ラメータの関係を見てみると,2 つの観測変数の共分散は,2 つの四角形を結ぶ矢印にかかる係 数の積になっていることがわかります。つまり,グラフィカルモデル上で経路が存在する観測変 数間には非ゼロの共分散があることを仮定していたわけです。また,1 つの観測変数の分散は,そ の四角形に向かっている矢印の係数の二乗和になっています。なお,独自因子には自分自身に対す る両方向の矢印が引かれています。グラフィカルモデルでは両方向の矢印で共分散を表すので,こ れは自分自身との共分散=分散を表していることになります。 先程の結果は観測変数を標準化していない状態での解でした。 そのため, 独自因子の分散が 1 を 超えたり,因子負荷の二乗との合計が 1 にならなかったりしています。例えば項目 𝐲1 について見 てみると,因子負荷の二乗と独自因子の分散の和は 0.6202 + 1.590 ≈ 1.975 となります。これは, 𝐲1 の分散 𝑠2𝑦1 の値 1.975 に対応しているわけです。ここで前回までの因子分析と同じように全て の観測変数を標準化した状態,つまり 𝐒 に共分散行列ではなく相関行列を与えて推定をした場合 に得られる解のことを標準化解や標準化推定値などと呼びます。そして SEM では多くの場合,

5.

7.1 因子分析の見方を変える 5 結果には標準化解を載せています。絶対のルールでは無いのですが,特に潜在変数がある場合には 単位の影響を受けない標準化解を用いたほうがしっくり来る,ということなのでしょう。というこ とでこの先も,潜在変数が含まれるモデルを扱う場合には 𝐒 には相関行列を想定した,標準化解 を考えることにします。 実 際 に 先 程 の 例 で 標 準 化 解 を 計 算 し て み る と,デ ー タ に お け る 相 関 行 列 𝐒 は cor(dat[,paste0("Q1_",1:3)]) によって具体的に*2   1 0.353 𝐒=⎡ ⎢ ⎣0.274 0.353 1 0.497 0.274 0.497⎤ ⎥ 1 ⎦ という値が得られるため, 連立方程式は 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 因子 6 項目の因子分析モデルで同じように見てみましょう。ここで は, 因子 1 は最初の 3 項目にのみ, 因子 2 は後ろの 3 項目にのみ影響を与えているという仮定を置 いています。また,2 つの因子の間は両矢印でつながっています。これは因子間に相関関係 𝑟𝑓1,𝑓2 があることを表しています。このように, (共)分散を表す時には両矢印を使います。言い換えると, ここでは因子間の共分散(=相関)が 0 でなくても良いという仮定(斜交回転)を置いているので す。 このモデルでは, 因子負荷行列 𝐁 は 𝑏 𝐁 = [ 11 0 𝑏12 0 𝑏13 0 0 𝑏24 0 𝑏25 0 ] 𝑏26 (7.7) *2 もちろんこれも厳密にはポリコリック相関のほうが良い可能性が高いですが, ここでは深く考えずにとりあえずピ アソンの積率相関係数で話を進めます。

6.

7.1 因子分析の見方を変える 6 図 7.3: 2 因子モデル となります。 ちなみに SEM で多因子モデルを扱う場合の多くは,このように 1 項目が 1 因子から のみ影響を受けていると考えると思います*3 。 すると,6 つの観測変数のモデル上の相関行列 𝚺 は 𝚺 = 𝐁⊤ 𝚽𝐁 + 𝚿 𝑏11 ⎡𝑏 ⎢ 12 𝑏 = ⎢ 13 ⎢0 ⎢0 ⎣0 0 0⎤ ⎥ 1 𝑟𝑓1,𝑓2 𝑏11 𝑏12 𝑏13 0 0⎥ 0 0 [ ][ ]+𝚿 𝑏24 ⎥ 𝑟𝑓1,𝑓2 1 0 0 0 𝑏24 𝑏25 𝑏26 𝑏25 ⎥ 𝑏26 ⎦ 2 𝑏11 𝑏11 𝑏12 𝑏11 𝑏13 𝑟𝑓1,𝑓2 𝑏11 𝑏24 𝑟𝑓1,𝑓2 𝑏11 𝑏25 2 ⎡ 𝑏 𝑏 𝑏 𝑏 𝑏 𝑟𝑓1,𝑓2 𝑏12 𝑏24 𝑟𝑓1,𝑓2 𝑏12 𝑏25 12 11 12 13 12 ⎢ 2 𝑏 𝑏 𝑏 𝑏 𝑏 𝑟𝑓1,𝑓2 𝑏13 𝑏24 𝑟𝑓1,𝑓2 𝑏13 𝑏25 13 11 13 12 13 =⎢ 2 𝑟 𝑏 𝑏 𝑟 𝑏 𝑏 𝑟 𝑏 𝑏 𝑏24 𝑏24 𝑏25 ⎢ 𝑓1,𝑓2 24 11 𝑓1,𝑓2 24 12 𝑓1,𝑓2 24 13 2 ⎢𝑟𝑓1,𝑓2 𝑏25 𝑏11 𝑟𝑓1,𝑓2 𝑏25 𝑏12 𝑟𝑓1,𝑓2 𝑏25 𝑏13 𝑏25 𝑏24 𝑏25 𝑏26 𝑏24 𝑏26 𝑏25 ⎣𝑟𝑓1,𝑓2 𝑏26 𝑏11 𝑟𝑓1,𝑓2 𝑏26 𝑏12 𝑟𝑓1,𝑓2 𝑏26 𝑏13 𝜎𝜺2 0 0 0 0 0 ⎡ 01 𝜎2 0 0 0 0 ⎤ 𝜺 2 ⎢ ⎥ 2 0 𝜎 𝜺3 0 0 0 ⎥ ⎢ 0 +⎢ 0 0 𝜎𝜺24 0 0 ⎥ ⎢ 0 ⎥ 2 0 0 0 𝜎 𝜺5 0 ⎥ ⎢ 0 0 0 0 0 𝜎𝜺26 ⎦ ⎣ 0 2 𝑏11 + 𝜎𝜺2 𝑏11 𝑏12 𝑏11 𝑏13 2 2 ⎡ 𝑏 𝑏 1 𝑏12 + 𝜎𝜺2 𝑏12 𝑏13 12 11 ⎢ 2 𝑏13 𝑏12 𝑏13 + 𝜎𝜺23 ⎢ 𝑏13 𝑏11 =⎢ ⎢𝑟𝑓1,𝑓2 𝑏24 𝑏11 𝑟𝑓1,𝑓2 𝑏24 𝑏12 𝑟𝑓1,𝑓2 𝑏24 𝑏13 ⎢𝑟𝑓1,𝑓2 𝑏25 𝑏11 𝑟𝑓1,𝑓2 𝑏25 𝑏12 𝑟𝑓1,𝑓2 𝑏25 𝑏13 ⎣𝑟𝑓1,𝑓2 𝑏26 𝑏11 𝑟𝑓1,𝑓2 𝑏26 𝑏12 𝑟𝑓1,𝑓2 𝑏26 𝑏13 𝑟𝑓1,𝑓2 𝑏11 𝑏24 𝑟𝑓1,𝑓2 𝑏12 𝑏24 𝑟𝑓1,𝑓2 𝑏13 𝑏24 2 𝑏24 + 𝜎𝜺24 𝑏25 𝑏24 𝑏26 𝑏24 𝑟𝑓1,𝑓2 𝑏11 𝑏25 𝑟𝑓1,𝑓2 𝑏12 𝑏25 𝑟𝑓1,𝑓2 𝑏13 𝑏25 𝑏24 𝑏25 2 𝑏25 + 𝜎𝜺25 𝑏26 𝑏25 𝑟𝑓1,𝑓2 𝑏11 𝑏26 𝑟𝑓1,𝑓2 𝑏12 𝑏26 ⎤ ⎥ 𝑟𝑓1,𝑓2 𝑏13 𝑏26 ⎥ 𝑏24 𝑏26 ⎥ 𝑏25 𝑏26 ⎥ 2 𝑏26 ⎦ 𝑟𝑓1,𝑓2 𝑏11 𝑏26 𝑟𝑓1,𝑓2 𝑏12 𝑏26 ⎤ ⎥ 𝑟𝑓1,𝑓2 𝑏13 𝑏26 ⎥ 𝑏24 𝑏26 ⎥ ⎥ 𝑏25 𝑏26 ⎥ 2 𝑏26 + 𝜎𝜺26 ⎦ (7.8) となります。 例えば y_1 と y_4 の繋がりを 図 7.3 で見てみると,y_1 → f_1 → f_2 → y_4 という経路に             *3 理論的には 𝑇 因子構造の場合,因子負荷行列のうち最低でも 𝑇 (𝑇 − 1) 個の値を固定したら推定は可能です。

7.

7.1 因子分析の見方を変える 7 なっており,この 2 変数の共分散はそれぞれの矢印に係る係数の積である 𝑟𝑓1,𝑓2 𝑏24 𝑏11 となって いることがわかります。 もし因子間に相関がなければ,y_1 と y_4 を結ぶ経路は存在せず, 数式的     には 𝑟𝑓1,𝑓2 = 0 となることからも,この 2 変数が完全に無相関であることを意味するようになり ます。 このモデルの重要なポイントは,分散共分散行列が 𝐁⊤ 𝚽𝐁 + 𝚿 という形で分解可能だという 点は前回までの因子分析と全く同じだという点です。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 0 𝑏12 0 𝑏13 𝑏23 0 𝑏24 0 𝑏25 0 ] 𝑏26 (7.9) *4 残念ながら固有値分解によって因子負荷行列を求めることはできなくなりますが, コンピュータによる反復計算な らば力技で近い値を求めることができるでしょう。

8.

7.1 因子分析の見方を変える 8 となります。このとき共分散行列はどうなるでしょうか。(7.8) 式と同じ要領で 𝚺 は計算できる のですが, すべて書くのは面倒ですね。 例えば項目 1 と 3 の共分散だけ抜き出してみると 𝜎𝑦1,𝑦3 = 𝑏13 𝑏11 + 𝑟𝑓1,𝑓2 𝑏23 𝑏11 (7.10) という形になっています。改めて図 7.4 で y_1 と y_3 の経路を見てみると,     • y_1 → f_1 → y_3 (𝑏13 𝑏11 )       • y_1 → f_1 → f_2 → y_3(𝑟𝑓1,𝑓2 𝑏23 𝑏11 )         という 2 つの経路が存在しており,それに対応した係数の積の和がこの 2 変数の共分散を表す ようになっています。 また, 項目 3 の分散は 2 2 2 𝜎𝑦3 = 𝑏13 + 𝑏23 + 2𝑟𝑓1,𝑓2 𝑏13 𝑏23 + 𝜎𝜺23 (7.11) となります。1 因子モデルのときも分散は係数の二乗和になっていましたが,より正確に言えば 2 • y_3 → f_1 → y_3 (𝑏13 )       2 • y_3 → f_2 → y_3 (𝑏23 )       • y_3 → e_3 → y_3 (𝜎𝜺23 )       • y_3 → f_1 → f_2 → y_3 (𝑟𝑓1,𝑓2 𝑏13 𝑏23 )         • y_3 → f_2 → f_1 → y_3 (𝑟𝑓1,𝑓2 𝑏13 𝑏23 )         という要領で,その変数を出発してから戻るまでの経路の全パターンに関して同様の計算をし ていたわけです。 INFO 構造方程式モデリングにおけるトレース・ルール SEM において 2 つの観測変数の共分散がモデル上でどのように表現されるかの考え方は, Wright’s tracing rules として知られています(Wright, 1934)。これは,以下の 3 つのシンプ ルなルールによって表されます (Loehlin & Beaujean, 2016) 。 1. ループの禁止 (No loops):同じ変数を通過して元の場所に戻ったり、同じ変数を二 度経由してはならない。 2. 逆流の禁止 (No going forward then backward):一度矢印の向きに従って進 んだら (順方向) , その経路内で矢印を遡る動き (逆方向) をしてはいけない。 3. 双方向矢印の制限 (A maximum of one curved arrow per path):双方向の 矢印 (共分散・相関) は、1 つの経路につき 1 回しか通れない。 特に潜在変数が絡む因子分析のようなモデルでは,上記のルールを満たしながら考えるこ とができる観測変数間の経路を全て列挙し,その経路にかかる係数の積を計算していくわ けです。

9.

7.2 R でやってみる(検証的因子分析) 9 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 の構文では,潜在   変数を規定する場合にはイコールチルダ(=~)を使用します。つまり,上のコードの 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 lavaan 0.6-21 ended normally after 38 iterations Estimator Optimization method Number of model parameters ML NLMINB 13 *5 本当は lavaan パッケージの基本関数は同名の lavaan() というものです。 この関数ではモデルの推定のための設     定をいろいろと細かく変更できるのですが,その設定が割と細い上にデフォルトでは思っていたような設定になか なかたどり着けません。いわば上級者向けの関数です。 

10.

7.2 R でやってみる(検証的因子分析) 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 10 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: 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 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 f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 Q1_7 Q1_8 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 結果を上から見ていきましょう。 3 4 Estimator Optimization method ML NLMINB

11.

7.2 R でやってみる(検証的因子分析) 5 11 Number of model parameters 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)と嬉しいのですが,統計的仮説検 定の仕組み上サンプルサイズが多いほど帰無仮説が棄却されやすかったりとなかなか使い勝手の 良いものではないので, 基本的には無視でも良いでしょう。 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|) 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 因子負荷です。lavaan はデフォルトでは,パラメータの制約として「因子の分散が 1」の代わり   に「各因子の第 1 項目に対する因子負荷が 1」という制約を置いています。因子分析の資料の 3 ペ ージで潜在変数のスケールの不定性を説明しましたが,lavaan のデフォルトでは因子ごとに最   初の項目の 𝑏 の値を一つ固定することによってその不定性を封じているわけです。ですが一般的 には「因子の分散が 1」の方がよく用いられる制約なので,そのようにした場合の推定値も出力し てみます。 その方法は 2 種類あり,1 つ目の方法は「推定時に引数 std.lv = TRUE を与える」と  いうものです。 

12.

7.2 R でやってみる(検証的因子分析) 12 推定時に潜在変数の分散を 1 にする 1 2 result_cfa <- cfa(model_cfa, data = dat, std.lv = TRUE) 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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 lavaan 0.6-21 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|) 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 Std.Err 0.051 0.054 0.050 z-value 31.229 9.151 20.917 P(>|z|) 0.000 0.000 0.000 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3

13.

7.2 R でやってみる(検証的因子分析) 42 43 44 45 46 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 0.950 0.888 1.205 1.000 1.000 13 0.043 0.055 0.044 22.233 16.193 27.532 0.000 0.000 0.000 std.lv = TRUE とすることで,潜在変数 (latent variable) を標準化 (standardized) すること   ができます。 また, もう一つの方法は「summary() 時に引数 standardized = TRUE を与える」と     いうものです。この方法では因子の分散を 1 に調整した場合の推定値を事後的に変換して出力し てくれます。 事後的に推定値を変換する 1 2 3 # 説明のためstd.lv = TRUEを消して再推定 result_cfa <- cfa(model_cfa, data = dat) 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 lavaan 0.6-21 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: Estimate f_1 =~ Q1_1 Q1_2 Q1_3 f_2 =~ Q1_6 1.000 1.548 1.348 1.000 Std.Err 0.106 0.082 z-value 14.538 16.362 P(>|z|) Std.lv Std.all 0.000 0.000 0.607 0.939 0.818 0.432 0.801 0.626 0.753 0.611

14.

7.2 R でやってみる(検証的因子分析) 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 Q1_7 Q1_8 14 1.220 0.894 0.075 0.053 16.316 16.756 0.000 0.000 0.919 0.673 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 を入れるようにすると良いのではないかと思います。というのも cfa(std.lv = TRUE)    のみだと観測変数まで標準化した標準化解が出力されません。一方 summary(standardized =  TRUE) のみだと各因子の第 1 項目の因子負荷が推定されなくなるため,仮説検定を行ってくれな  いためです。 標準化解の出し方 (おすすめ) 1 2 result_cfa <- cfa(model_cfa, data = dat, std.lv = TRUE) summary(result_cfa, standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 lavaan 0.6-21 ended normally after 27 iterations Estimator Optimization method Number of model parameters Number of observations Model Test User Model: ML NLMINB 13 2432

15.

7.2 R でやってみる(検証的因子分析) 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 15 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 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 Covariances: f_1 ~~ f_2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 ということで改めて因子負荷から見ていきます。 21 22 23 24 25 26 Latent Variables: f_1 =~ Q1_1 Q1_2 Q1_3 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

16.

7.2 R でやってみる(検証的因子分析) 27 28 29 30 f_2 =~ Q1_6 Q1_7 Q1_8 0.753 0.919 0.673 16 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: Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.251 0.028 8.852 0.000 0.251 0.251 f_1 ~~ f_2 共分散です。Std.lv と Std.all では潜在変数の分散は 1 になっているため,ここに表示され     ている 0.251 は 2 因子の因子間相関を表しています。  37 38 39 40 41 42 43 44 45 46  Variances: Estimate 1.607 0.492 1.036 0.950 0.888 1.205 1.000 1.000 .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 f_1 f_2 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 各変数の分散です。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 となります。 実際に cfa() 関数によって推定されたパラメータの値 (Std.all) を,(7.8) 式に代入して 𝚺 を     計算してみましょう (添字の項目番号はデータに合わせて変えています) 。

17.

7.2 R でやってみる(検証的因子分析) 17 𝚺 = 𝐁⊤ 𝚽𝐁 + 𝚿 2 𝑏211 + 𝜎𝜺 1 ⎡ 𝑏 𝑏 12 11 ⎢ ⎢ 𝑏13 𝑏11 =⎢ 𝑟 𝑏 𝑏 ⎢ 𝑓1,𝑓2 26 11 ⎢𝑟𝑓1,𝑓2 𝑏27 𝑏11 ⎣𝑟𝑓1,𝑓2 𝑏28 𝑏11 𝑏11 𝑏12 2 𝑏212 + 𝜎𝜺 2 𝑏13 𝑏12 𝑟𝑓1,𝑓2 𝑏26 𝑏12 𝑟𝑓1,𝑓2 𝑏27 𝑏12 𝑟𝑓1,𝑓2 𝑏28 𝑏12 𝑏11 𝑏13 𝑏12 𝑏13 2 𝑏213 + 𝜎𝜺 3 𝑟𝑓1,𝑓2 𝑏26 𝑏13 𝑟𝑓1,𝑓2 𝑏27 𝑏13 𝑟𝑓1,𝑓2 𝑏28 𝑏13 0.4322 + 0.814 ⎡ 0.801 × 0.432 ⎢ 0.626 × 0.432 =⎢ ⎢0.251 × 0.611 × 0.432 ⎢0.251 × 0.698 × 0.432 ⎣0.251 × 0.523 × 0.432 0.432 × 0.801 0.8012 + 0.358 0.626 × 0.801 0.251 × 0.611 × 0.801 0.251 × 0.698 × 0.801 0.251 × 0.523 × 0.801 1 ⎡0.346 ⎢0.270 ≈⎢ ⎢0.066 ⎢0.076 ⎣0.057 0.066 0.123 0.096 1 0.426 0.320 0.346 1 0.501 0.123 0.140 0.105 0.270 0.501 1 0.096 0.110 0.082 0.076 0.140 0.110 0.426 1 0.365 𝑟𝑓1,𝑓2 𝑏11 𝑏26 𝑟𝑓1,𝑓2 𝑏12 𝑏26 𝑟𝑓1,𝑓2 𝑏13 𝑏26 2 𝑏226 + 𝜎𝜺 6 𝑏27 𝑏26 𝑏28 𝑏26 𝑟𝑓1,𝑓2 𝑏11 𝑏27 𝑟𝑓1,𝑓2 𝑏12 𝑏27 𝑟𝑓1,𝑓2 𝑏13 𝑏27 𝑏26 𝑏27 2 𝑏227 + 𝜎𝜺 7 𝑏28 𝑏27 0.432 × 0.626 0.801 × 0.626 0.6262 + 0.608 0.251 × 0.611 × 0.626 0.251 × 0.698 × 0.626 0.251 × 0.523 × 0.626 𝑟𝑓1,𝑓2 𝑏11 𝑏28 𝑟𝑓1,𝑓2 𝑏12 𝑏28 ⎤ ⎥ 𝑟𝑓1,𝑓2 𝑏13 𝑏28 ⎥ ⎥ 𝑏26 𝑏28 ⎥ 𝑏27 𝑏28 ⎥ 2 2 𝑏28 + 𝜎𝜺8 ⎦ 0.251 × 0.432 × 0.611 0.251 × 0.801 × 0.611 0.251 × 0.626 × 0.611 0.6112 + 0.626 0.698 × 0.611 0.523 × 0.611 0.251 × 0.432 × 0.698 0.251 × 0.801 × 0.698 0.251 × 0.626 × 0.698 0.611 × 0.698 0.6982 + 0.513 0.523 × 0.698 0.057 0.105⎤ 0.082⎥ ⎥ 0.320⎥ 0.365⎥ 1 ⎦ そして,cor() 関数でデータの相関行列 𝐒 を出力してみると以下のようになります。   観測変数の相関行列 1 2 # 上の式と比較するため,小数点第3位まで表示 round(cor(dat[, paste0("Q1_", c(1:3, 6:8))]), 3) 1 2 3 4 5 6 7 Q1_1 Q1_2 Q1_3 Q1_6 Q1_7 Q1_8 Q1_1 1.000 0.353 0.274 -0.011 -0.011 0.024 Q1_2 0.353 1.000 0.497 0.098 0.124 0.185 Q1_3 0.274 0.497 1.000 0.110 0.142 0.126 Q1_6 -0.011 0.098 0.110 1.000 0.435 0.313 Q1_7 -0.011 0.124 0.142 0.435 1.000 0.359 Q1_8 0.024 0.185 0.126 0.313 0.359 1.000 ということで, モデルから計算された相関行列 𝚺 と, 実際のデータの相関行列 𝐒 の差を取ると, 0 ⎡−0.007 ⎢ −0.004 𝚺−𝐒=⎢ ⎢ 0.077 ⎢ 0.087 ⎣ 0.033 −0.007 0 0.004 0.025 0.016 −0.080 −0.004 0.077 0.087 0.033 0.004 0.025 0.016 −0.080⎤ ⎥ 0 −0.014 −0.032 −0.044⎥ −0.014 0 −0.009 0.007 ⎥ −0.032 −0.009 0 0.006 ⎥ −0.044 0.007 0.006 0 ⎦ (7.12) と,多くの要素が 0 に近い値になっていることがわかります。これは,モデルによってデータの共 分散構造がかなり良く再現されていることを意味します。一方で,もしも 𝚺 − 𝐒 の値が大きくな ってしまう場合には,そもそもモデルの構造自体がデータに合っていないために, 頑張って 「𝚺 と 𝐒 ができるだけ近い値になるように」パラメータを推定しても,あまり良い結果が得られなかった 可能性が高いのです。 ということで SEM では,推定したパラメータをもとに復元したモデル上の共分散行列 𝚺 と, データにおいて観測された実際の共分散行列 𝐒 がきちんと近い値になっているかの確認が非常 0.251 × 0.432 × 0.523 0.251 × 0.801 × 0.523⎤ 0.251 × 0.626 × 0.523⎥ ⎥ 0.611 × 0.523 ⎥ ⎥ 0.698 × 0.523 ⎦ 0.5232 + 0.727

18.

7.3 回帰分析の見方を変える 18 に重要になります (詳細はセクション 7.6 で) 。 ちなみに因子得点は,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 で回帰してみましょう。     図 7.5: 単回帰モデル このモデルの回帰式は 𝑥𝐴 = 𝑏0 + 𝑏1 𝑥age + 𝜀𝐴 (7.13)

19.

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

20.

7.3 回帰分析の見方を変える 20 析をくっつけたようなモデルです。ちなみにこのように,単一の回帰式で表せないような,回帰分 析をくっつけたモデルは,SEM の中でも特にパス解析 (path analysis) と呼ばれることがあり ます。 図 7.6: パス解析モデル 回帰式はそれぞれ { 𝑥𝐴 = 𝑏0𝐴 + 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝜀𝐴 𝑥𝐶 = 𝑏0𝐶 + 𝑏𝐴 𝑥𝐴 + 𝜀𝐶 (7.15) となりますが, さらに下の式の 𝑥𝐴 を展開することで ⎧𝑥𝐴 = 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝑏0𝐴 + 𝜀𝐴 { 𝑥 = 𝑏𝐴 (𝑏0𝐴 + 𝑏gender 𝑥gender + 𝑏age 𝑥age + 𝜀𝐴 ) + 𝑏0𝐶 + 𝜀𝐶 ⎨ 𝐶 { = 𝑏𝐴 𝑏0𝐴 + 𝑏𝐴 𝑏gender 𝑥gender + 𝑏𝐴 𝑏age 𝑥age + 𝑏𝐴 𝜀𝐴 + 𝑏0𝐶 + 𝜀𝐶 ⎩ (7.16) となります。なお,検証的因子分析での独自因子と同じように,パス解析でも内生変数に誤差項を *7 。 明示することがあります(図 7.7 ) こうすることによって,各変数の分散および共分散を考え るのが多少楽になります (後述) 。 図 7.7: パス解析モデル (誤差項を追加) *7 パス解析での誤差項は潜在変数としても扱われないため, 楕円で囲わないのが一般的です。

21.

7.3 回帰分析の見方を変える 21 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.17) となります。これを 図 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_C → Q1_A → gender → Q1_A (𝑏𝐴 𝑏gender 𝜎𝑥2 gender )         2 • Q1_C → Q1_A → age → Q1_A (𝑏𝐴 𝑏age 𝜎𝑥2 age )         • Q1_C → Q1_A → gender → age → Q1_A (𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age )           • Q1_C → Q1_A → age → gender → Q1_A (𝑏𝐴 𝑏gender 𝑏age 𝜎𝑥gender ,𝑥age )           • Q1_C → Q1_A → e_A → Q1_A (𝑏𝐴 𝜎𝜀2𝐴 )         という感じで,Q1_C から Q1_A への全経路での係数の和の形になっていると見ることができま     す*8 。 というわけで,モデル上の共分散行列 𝚺 を求めることが出来ました。あとはこれに対応するデ ータ上の分散(4 つ)と共分散(6 つ)を用いて,5 つのパラメータ (𝑏𝐴 , 𝑏age , 𝑏gender , 𝜎𝜀2𝐴 , 𝜎𝜀2𝐶 ) を 推定 (プラス外生変数の計 3 つの分散共分散:𝜎𝑥2 age , 𝜎𝑥2 gender , 𝜎𝑥gender ,𝑥age を計算) するだけです。 *8 「途中で Q1_A を通っているじゃないか」 という点は大目に見てください。SEM では全ての内生変数の分散・共分   散を外生変数の分散の関数で表す必要があるため,パスの経路で考える場合には必ず外生変数を通過する必要があ るのです。

22.

7.4 R でやってみる(回帰分析・パス解析) 実際に計算してみると, 22 𝜎𝑥2 age = 120.254 ⎧ { { 𝜎𝑥2 gender = 0.221 { { {𝜎𝑥gender ,𝑥age = 0.204 { { 𝑏𝐴 = 0.272 ⎨ 𝑏age = 0.071 { { 𝑏gender = 1.891 { { { 𝜎𝜀2𝐴 = 19.210 { { 𝜎𝜀2𝐶 = 21.595 ⎩ という解が得られます(上 3 つはデータから直接求めた値) 。これを (7.17) 式に当てはめてみる と, 𝜎𝑥2 age ⎡𝜎 𝑥gender ,𝑥age 𝚺=⎢ ⎢ 𝜎 ⎢ 𝑥𝐴 ,𝑥age ⎣ 𝜎𝑥𝐶 ,𝑥age 𝜎𝑥2 gender 𝜎𝑥𝐴 ,𝑥gender 𝜎𝑥𝐶 ,𝑥gender 𝜎𝑥2 𝐴 𝜎𝑥𝐶 ,𝑥𝐴 120.254 ⎤ ⎡ 0.221 ⎥ = ⎢ 0.204 ⎥ ⎢ 8.902 0.432 ⎥ 0.117 𝜎𝑥2 𝐶 ⎦ ⎣ 2.418 20.658 5.611 ⎤ ⎥ ⎥ 23.119⎦ となります。 また, データ上の共分散行列の値は 120.254 ⎡ 0.204 0.221 𝐒=⎢ ⎢ 8.902 0.432 6.203 0.181 ⎣ 20.658 5.611 ⎤ ⎥ ⎥ 23.119⎦ となり, まあまあ近い値が得られました。 7.4 R でやってみる(回帰分析・パス解析) それでは,lavaan を使って回帰分析をやってみましょう。sem() 関数を使うと, 回帰分析を含     むパス解析に適した設定で自動的に推定を行ってくれます。 モデル構文では,lm() や glm() のときと同じように,両辺をチルダ(~)でつなげることで観測       変数どうしの回帰を表します。 ということで, 単回帰分析であれば以下のように 1 文だけのモデル 構文を書けばよいわけです。 lavaan で単回帰分析 1 2 3 4 model <- "Q1_A ~ age" 1 2 3 lavaan 0.6-21 ended normally after 1 iteration result_lm <- sem(model, data = dat) summary(result_lm) Estimator ML

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

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

23

Optimization method
Number of model parameters

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" を加えると,切片項を明示的に推定するように指示することが出




来ます。
切片項も出してください
1
2
3
4
5
6

model <- "
Q1_A ~ age + 1
"

1
2
3

lavaan 0.6-21 ended normally after 1 iteration

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

Estimator

ML

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

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

24

Optimization method
Number of model parameters

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:
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

Q1_A ~
age
Intercepts:
.Q1_A
Variances:
.Q1_A

出力を見ると,新たに Intercepts: という欄ができています。これが切片を表している部分で




す。
一応,
ここまでの結果を,lm() で普通に回帰分析を行った場合と比較してみましょう。




lm() で回帰分析
1
2
3
4
1
2
3
4
5
6

# できるだけ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

Median

3Q

Max

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

7
8
9
10
11
12
13
14
15
16
17
18

-18.565

-2.602

0.621

3.361

25

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
8
9
10

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

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

lavaan 0.6-21 ended normally after 23 iterations

age ~~ age + gender
gender ~~ gender
"
result_sem <- sem(model, data = dat)
summary(result_sem)

Estimator
Optimization method
Number of model parameters
Number of observations

ML
NLMINB
8
2432

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

15.989
2
0.000

26.

7.5 回帰分析と因子分析を組み合わせる 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 26 Parameter Estimates: Standard errors Information Information saturated (h1) model Standard Expected Structured Regressions: Q1_A ~ gender age Q1_C ~ 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.272 0.021 13.100 0.000 Estimate Std.Err z-value P(>|z|) 0.204 0.105 1.945 0.052 Estimate 120.254 0.221 19.210 21.595 Std.Err 3.449 0.006 0.551 0.619 z-value 34.871 34.871 34.871 34.871 P(>|z|) 0.000 0.000 0.000 0.000 Covariances: gender ~~ age Variances: age gender .Q1_A .Q1_C 7.5 回帰分析と因子分析を組み合わせる 図 7.6 に基づくパス解析では, 因子 A と因子 C に関する変数として和得点 (Q1_A と Q1_C) を使     用しました。ですが和得点には独自因子(構成概念からすると誤差)の影響が残っているため,可 能であれば因子得点を用いた方が「純粋」な構成概念得点であると考えられます。あるいは(構成概 念)妥当性の考え方の根底にあった「観測得点はあくまでも構成概念の顕在化」という考えに従え ば,仮説モデルでは構成概念そのもの同士の関係(法則定立ネットワーク)を見るべきだと言える でしょう。 いま,手元には構成概念(因子)を構成する各項目の回答そのものがあります。そこで,図 7.3 の 因子分析と 図 7.6 の回帰分析を組み合わせて,図 7.8 のようなモデルを考えてみましょう。

27.

7.5 回帰分析と因子分析を組み合わせる 27 図 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 1 0.274 0.497 −0.011 0.098 −0.011 0.124 0.024 0.185 1 0.110 0.142 0.126 1 0.435 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.18) = (𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 )𝑏2 + 𝜀2 となり,これを頑張って展開して相関を求める必要がありそうです。しかしよく考えてみる

28.

7.5 回帰分析と因子分析を組み合わせる 28 と,因子分析モデルでは潜在変数の分散を 1 に固定する,という制約がありました。つまり 𝑓𝐴 = (𝑏age 𝑥age + 𝑏gender 𝑥gender + 𝜀𝐴 ) の部分は,これをすべて合わせて分散 1 になるように調整 されるということです。したがってこの 2 項目の相関を求めると,結局 Chapter 6 で示した 1 因 子モデルにおける観測変数間の相関 に帰着して*9 𝑟𝑦1,𝑦2 = 𝑟(𝑓𝐴 𝑏1 +𝜀1 ),(𝑓𝐴 𝑏2 +𝜀2 ) = 𝑟(𝑓𝐴 𝑏1 ),(𝑓𝐴 𝑏2 ) (7.19) = 𝑏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.20) 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.21) となります。 ここでもやはり • Q1_8 → f_C → f_A → age (𝑏𝐴 𝑏8 𝑏age )         • Q1_8 → f_C → 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_C =~ Q1_6 + Q1_7 + Q1_8 f_A ~ age + gender *9 共通因子と独自因子の間は無相関であり, またモデル上独自因子間も無相関と仮定しているため,これらの項が全 て消えています。

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

6
7
8

29

f_C ~ 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

lavaan 0.6-21 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_C =~
Q1_6
Q1_7
Q1_8

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

30.

7.5 回帰分析と因子分析を組み合わせる 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 30 Regressions: 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 ~ age gender f_C ~ f_A Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_C 結果の見方も同じなので省略します。一応全ての標準化解を図 7.8 に書き加えると,図 7.9 の ようになるわけです。実際に論文などで報告する際には,全ての値を載せるとごちゃごちゃしてし まう可能性があります。そこで,以下のような省略を行い簡潔化することがあります。このあたり は自由というか,どういう基準で簡略化したかがハッキリわかれば OK です。 • 因子分析の部分は書かない(因子だけ残す) • 係数が一定以下のところには矢印をひかない • 統計的に有意ではない係数のところは矢印をひかない lavaan の関数(cfa() や sem())によって得られた結果のオブジェクトから,自動的にパス図       を作ってくれるものとして,lavaanPlot パッケージというものが用意されています。こういっ   たものを利用して,自分で書いたモデルのコードが正しいものだったかをきちんと確認しておく と良いでしょう。lavaanPlot パッケージは,図 7.10 のように比較的そのまま論文にも載せら   れそうなレベルのきれいな図を書いてくれます。ただ,見た目の点では変数名を変えたり,微妙に 矢印の位置を調整したりする必要が出てくることが多いと思うので,最終的には PowerPoint や Illustrator などを使って自分で図を作ったほうが良さそうです。

31.

7.5 回帰分析と因子分析を組み合わせる 31 図 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_C 0.61 0.7 Q1_6 Q1_7 図 7.10: lavaanPlot による出力 0.52 Q1_8

32.

7.5 回帰分析と因子分析を組み合わせる 32 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) # あとは好きなようにいじってください。

33.

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

34.

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

35.

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

36.

7.6 モデルの適合度 36 と表せるので,𝐯𝑝 𝐁 を移項させてから両辺に逆行列をかけると (7.30) 𝐯𝑝 = 𝜺𝑝 (𝐈(𝑇 +𝐼) − 𝐁)−1 と変形させることができます。ここで, 𝐯𝑝 = [𝐟𝑝 (7.31) 𝐲𝑝 ] であることを踏まえると,𝐯𝑝 のうち 𝐟𝑝 に当たる部分が 0 になったものが 𝐲𝑝 なので,(𝑇 × 𝑇 ) のゼロ行列 𝟎(𝑇 ) と,(𝐼 × 𝐼) の単位行列 𝐈(𝐼) を縦に並べた行列 𝐇 を使って, 𝐲𝑝 = [𝐟𝑝 𝟎 𝐲𝑝 ] [ (𝑇 ) ] 𝐈(𝐼) (7.32) = 𝐯𝑝 𝐇 と表せます。 あとは, これに (7.30) 式を代入することで, (7.33) 𝐲𝑝 = 𝜺𝑝 (𝐈(𝑇 +𝐼) − 𝐁)−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.34)

37.

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

38.

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

39.

7.6 モデルの適合度 39 ては √ 𝐼 𝐼 √ 2 RMR = √ ∑ ∑(𝜎𝑖𝑗 − 𝑠𝑖𝑗 )2 𝐼(𝐼 − 1) 𝑖=1 𝑗=1 ⎷ (7.41) と表されます。 ここで 𝜎𝑖𝑗 , 𝑠𝑖𝑗 はそれぞれ 𝚺, 𝐒 の (𝑖, 𝑗) 成分の値を意味しています。 しかし,RMR は変数のスケールの影響を受けてしまいます。例えば全ての変数の値を 10 倍(=分散は 100 倍) にしたとしたら,𝐒 と 𝚺 の各要素の値は単純に 100 倍されてしまうため,𝐄 の平均である RMR も 100 倍になってしまいます。 これでは基準を決められないので,RMR を標準化することで生まれたのが SRMR(stan- dardized RMR: Bentler, 1995)です。標準化の仕方は, 「共分散から相関係数を導出する時」 と同様 にすることで, √ 𝐼 𝐼 𝜎𝑖𝑗 − 𝑠𝑖𝑗 2 √ 2 SRMR = √ ∑∑( ) 𝐼(𝐼 − 1) 𝑖=1 𝑗=1 𝑠𝑖𝑖 𝑠𝑗𝑗 ⎷ (7.42) と定式化されます。Hu & Bentler(1999) のシミュレーションでは, 適合度指標の組み合わせとし て SRMR プラス何か(TLI とか CFI とか RMSEA とか)を目的に応じて組み合わせることが推 奨されています。他の適合度指標と比べてもやや毛色が違うので,複数の適合度指標を報告する中 には, まずは SRMR は入れておくのが良いかもしれません。 SRMR の他にもよく使われる指標としては,GFI(Goodness of fit index: Bentler, 1983)が あります。 これも基本的な考え方は同じで,𝐒 と 𝚺 の各要素の値が近いほど良くなります。 GFI = 1 − 𝑡𝑟 [(𝐒 − 𝚺)2 ] 𝑡𝑟[𝐒2 ] 𝐼 𝑖 ∑𝑖=1 ∑𝑗=1 (𝑠𝑖𝑗 − 𝜎𝑖𝑗 )2 =1− 𝐼 𝑖 ∑𝑖=1 ∑𝑗=1 𝑠2𝑖𝑗 (7.43) 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.44) これは,自由度調整済み決定係数のような感じで,推定するパラメータ数が多くなるほど相関行列 の乖離度 (1 − GFI) を過大評価するような調整がされているわけです。

40.

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

41.

7.6 モデルの適合度 41 には,標本誤差によって大小関係が変わりうるため,単一の情報量規準だけを用いてモデルを選択 するのは危険なときがあるかもしれません。 少しだけ注意しましょう。 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 を与えても良いのですが, この方法だと一部の適合度指標しか出してくれません。    

42.

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

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

13

43

result2 <- cfa(model2, data = dat)

続いて 2 つのモデルの適合度を比較していきましょう。とはいえ,一つ一つ fitmeasures() し




て出力を見比べるのは大変なので,
複数のモデルの適合度を並べてくれる semTools::compareFit()


という関数を使ってみます*15 。

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

################### Nested Model Comparison #########################
Chi-Squared Difference Test
Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
result2 7 46682 46764 57.197
result1 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 の特殊なケースといえます。
このように,
あるモデルが別のモデルに内包




されているとき,
そのモデルは
「ネスト」
の関係にあると呼んだりします。
ネストされたモデル間の比較では,尤度比検定を行うことができます。ネストされたモデルで
*15 2026 年 6 月時点では,compareFit() 関数を実行するといくつかの Warning が出ます。
これは多分 lavaan 本体








のバージョンアップに伴って削除された引数を semTools::compareFit() 関数の内部でまだ使用しているためと
考えられます。ただ結果自体は問題なく出力されているのでとりあえずは無視で OK です。






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

44

は,パラメータ数の減少に伴い少なからずデータに対する当てはまりが悪化(尤度が減少)してい
るはずですが,もしも尤度比検定が有意にならない場合,その当てはまりの悪化が「減らしたパ
ラメータ数的に許容できる」という感じになり,それならばより節約的なモデルを選ぼう,という
流れになります。今回の場合,Pr(>Chisq) が 0.05 より小さいため検定は有意になっています。




result2 を基準に見ると result1 のモデルは f_1 =~ Q1_6 のパスを 0 にしたことによって当












てはまりが有意に悪化している,ということです。したがって,尤度比検定的には 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

################### Nested Model Comparison #########################
Chi-Squared Difference Test
Df
AIC
BIC Chisq Chisq diff
RMSEA Df diff Pr(>Chisq)
result2 7 46682 46764 57.197
result1 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

45.

7.6 モデルの適合度 15 16 17 18 45 ################## Differences in Fit Indices ####################### gfi agfi result1 - result2 -0.001 0.001 引数 fit.measures に指定できるのは,fitmeasures() 関数で表示されるものの名前です。 そ     して実は fitmeasures() 関数自体も同じ引数 fit.measures を受け付けるので,同様に一部の     指標のみを表示したい場合には設定してあげると良いでしょう。 7.6.6 (おまけ)モデル上の共分散行列とデータの共分散行列のズレを確認する 言うまでもないことですが,以上のモデル適合度は,モデル上の共分散行列 𝚺 とデータの共分 散行列 𝐒 のズレを評価したものです。 そのため, もしもモデルの適合度が悪い場合には,具体的に どの変数間の相関をうまくモデル化できていないかを確認すると,後述するモデル修正などの参 考になるかもしれません。 ということで,先ほど実行した 図 7.3 の 2 因子モデル(result1)を用いて見ていきましょう。   まずは観測された共分散行列 𝐒 です。 これは, この Chapter の最初の方で何度か出てきたように, cov() 関数を用いると計算可能です。   観測された共分散行列の確認 1 2 3 S_mat <- cov(dat[, paste0("Q1_", c(1:3, 6:8))]) * ((nrow(dat) - 1) / nrow(dat)) round(S_mat, 3) 1 2 3 4 5 6 7 Q1_1 Q1_2 Q1_3 Q1_6 Q1_7 Q1_8 Q1_1 1.975 0.581 0.504 -0.020 -0.020 0.043 Q1_2 0.581 1.375 0.761 0.141 0.191 0.279 Q1_3 0.504 0.761 1.705 0.177 0.244 0.211 Q1_6 -0.020 0.141 0.177 1.517 0.704 0.496 Q1_7 -0.020 0.191 0.244 0.704 1.732 0.608 Q1_8 0.043 0.279 0.211 0.496 0.608 1.658 なお,cov() 関数が返す共分散行列は,不偏分散共分散行列であることに注意してください。   不偏分散共分散行列は, 分母が 𝑛 − 1 になっていますが,SEM の適合度指標の計算では分母が 𝑛 になっている共分散行列を用いているため,cov() 関数で計算した共分散行列に 𝑛−1 𝑛 をかけて   あげる必要があります。 ちなみに, 実際に lavaan が計算に使用した共分散行列を確認するためには,lavInspect() と     いう関数を用います。 この関数は, 引数 what にキーワードを指定すると,lavaan の出力オブジェ     クトの中からいろいろな情報を取り出すことができる関数です。今回は,使用したデータの標本統 計量 (のうちの共分散行列) を取り出したいので,what = "sampstat" と指定してあげましょう。  

46.

7.6 モデルの適合度 46 lavaan が計算に使用した共分散行列の確認 1 2 # 返り値の中のcovというところに共分散行列が入っています lavInspect(result1, what = "sampstat")$cov 1 2 3 4 5 6 7 Q1_1 Q1_1 1.975 Q1_2 0.581 Q1_3 0.504 Q1_6 -0.020 Q1_7 -0.020 Q1_8 0.043   Q1_2 Q1_3 Q1_6 Q1_7 Q1_8 1.375 0.761 0.141 0.191 0.279 1.705 0.177 0.244 0.211 1.517 0.704 0.496 1.732 0.608 1.658 出力はもちろん (少なくともデータの中に NA が無いならば)cov() 関数で直接計算した値と一     致するはずです。もし一致しない場合には,データをきちんと確認してみる必要があるかもしれま せん。 続いては,モデルパラメータから計算されたモデル上の共分散行列 𝚺 を確認してみましょう。 これも lavInspect() で抽出可能です。観測変数(observed variables)の共分散(covariance)を   取り出したいので, 引数 what には cov.ov と指定します。     モデル上の共分散行列の確認 1 lavInspect(result1, what = "cov.ov") 1 2 3 4 5 6 7 Q1_1 Q1_2 Q1_3 Q1_6 Q1_7 Q1_8 Q1_1 1.975 Q1_2 0.570 1.375 Q1_3 0.496 0.768 1.705 Q1_6 0.115 0.178 0.155 1.517 Q1_7 0.140 0.217 0.189 0.692 1.732 Q1_8 0.103 0.159 0.138 0.507 0.618 1.658 最後はモデル上の共分散行列 𝚺 とデータの共分散行列 𝐒 のズレの確認です。ここまでの計算 で得られた 𝚺 と 𝐒 を用いて直接引き算しても良いのですが,lavaan にはこのズレを直接計算し  てくれる関数もあります。 モデル上の共分散行列とデータの共分散行列のズレの確認 1 lavResiduals(result1, type = "raw")$cov 1 2 3 Q1_1 Q1_2  Q1_1 0.000 0.011 Q1_2 0.000 Q1_3 Q1_6 Q1_7  Q1_8 

47.

7.6 モデルの適合度 4 5 6 7 47 Q1_3 0.007 -0.007 Q1_6 -0.134 -0.036 Q1_7 -0.160 -0.025 Q1_8 -0.060 0.121 0.000 0.022 0.000 0.055 0.013 0.000 0.073 -0.011 -0.010 0.000 lavResiduals() 関数は,デフォルトでは SRMR のときの考え方で標準化したズレ(相関係数   のスケール)を返すようになっています。そのため,もし共分散のスケールでのズレを確認したい 場合には, 引数 type に "raw" を指定してあげる必要があります。     こうしてズレが確認できたら,あとは絶対値の大きなペアを見るだけです。ただ,共分散はもと の変数のスケールの影響を受けてしまうので, (先程はわざわざ type = "raw" を設定させてお   いて恐縮ですが) 基本的には相関係数のスケールでズレを確認したほうが良い気がします。 標準化してズレを確認 1 2 # 引数typeをデフォルトにしておけば相関係数のスケールでのズレが確認できます lavResiduals(result1)$cov 1 2 3 4 5 6 7 Q1_1 Q1_2 Q1_1 0.000 Q1_2 0.007 0.000 Q1_3 0.004 -0.004 Q1_6 -0.078 -0.025 Q1_7 -0.087 -0.016 Q1_8 -0.033 0.080  Q1_3  Q1_6 Q1_7 Q1_8 0.000 0.014 0.000 0.032 0.008 0.000 0.043 -0.007 -0.006 0.000 ということで,このモデルにおいては Q1_1 と Q1_6 および Q1_7 のペア,および Q1_2 と Q1_8           のズレが相対的に大きめになっている事がわかります。もしかしたら,共通因子では説明できない 何らかの関係がこれらのペアの間に存在しているのかもしれません。ただし,この結果を踏まえ て実際にモデルを修正するかどうかは慎重に考える必要があります(詳しくはセクション 7.7 に て) 。 INFO (おまけ)適合度指標の関係 図 7.14 に,各種適合度指標の関係を表してみました。無理やり 1 つの図にまとめたので多 少変なところがあるかもしれませんが… • 相対的指標は「独立モデルを0,飽和モデルを1」としたときの仮説モデルの位置づ けを表しています。 • 絶対的指標は「飽和モデル=データ」からのズレを表す指標です。理論上はたぶん下 限は決まっていませんが, 基本的に0から1の範囲内に収まるはずです。 • 倹約的指標はものによります。自由度で調整した値です。 • 情報量規準は独立モデル・飽和モデルと何の関係もありません。尤度を自由度で調整

48.

7.7 モデルの修正 48 しただけです。図の例では,モデル B のほうが絶対的な当てはまりは良いのですが, 自由度による調整の結果情報量規準の値はモデル A のほうが良い,という状態を表 しています。 図 7.14: 適合度指標の関係 7.7 モデルの修正 (ここからはプラクティカルな話題です。 ) SEM では,まずドメイン知識に基づいた仮説を立てて,その仮説をモデルを落とし込んでいく (パス図に線を引く)ことになります。そして,実際のデータと仮説モデルとで共分散行列がどの程

49.

7.7 モデルの修正 49 度ずれているかを評価し,ズレが小さければ「問題ないモデル」と判断します。ズレの大きさを評価 する適合度指標には,大きく分けると「絶対的なズレの大きさを評価するもの(SRMR や GFI な ど) 」 と 「パラメータ数 (自由度) を考慮して評価するもの (AGFI や RMSEA) 」 の 2 種類がありまし た。 もしも仮説モデルにおいて適合度指標の値が悪ければ,モデルを修正してデータとの整合性 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_C =~ Q1_6 + Q1_7 + Q1_8 f_A ~ age + gender f_C ~ f_A age ~~ gender " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 lavaan 0.6-21 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

50.

7.7 モデルの修正 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 50 Parameter Estimates: Standard errors Information Information saturated (h1) model 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_C =~ Q1_6 Q1_7 Q1_8 Regressions: f_A ~ age gender f_C ~ f_A Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A .f_C 適合度はすでにかなり良いんですが… 1 Standard Expected Structured fitmeasures(result1)

51.

7.7 モデルの修正 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 51 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 7.7.1 不要なパスを消す 普通に考えると年齢 age と性別 gender は無相関だと考えるのが自然ですね。先程の分析の結     果を見ても, 共分散 age ~~ gender の検定結果は有意にはなっていません。summary(sem()) で     出力される検定では,帰無仮説に「そのパラメータの母数が 0 に等しい」を設定した Wald 検定の 結果を出しています。Wald 検定の中身はともかく, とりあえずこの P(>|z|) 列を見れば, そのパ   ラメータを削除してよいかにアタリをつけられそうかが分かります。 ということで,検定結果が有意ではなかった age ~~ gender の共分散をゼロに固定して再度  推定してみましょう。 

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

52

パラメータを制約する
1
2
3
4
5
6
7

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

lavaan の記法では,このように右辺の変数名の前に 0* を付けると,そのパラメータの値を 0








に固定することが出来ます*16 。
修正後のモデルで再度推定
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

lavaan 0.6-21 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

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

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




53.

7.7 モデルの修正 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 53 f_C =~ Q1_6 Q1_7 Q1_8 0.728 0.888 0.651 0.031 0.035 0.031 23.763 25.602 21.259 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.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_C ~ 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_C 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 ################### 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 .

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

8
9
10
11
12
13
14
15
16
17
18
19
20
21

--Signif. codes:

54

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

####################### 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-21 ended normally after 35 iterations
Estimator
Optimization method
Number of model parameters
Number of observations
Model Test User Model:

ML
NLMINB
18
100

55.

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 55 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_C =~ 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_C ~ f_A Covariances: age ~~ gender Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_6 .Q1_7 .Q1_8 age gender .f_A

56.

7.7 モデルの修正 56 56 .f_C 1.000 0.828 0.828 7.7.2 新しいパスを増やす 続いて,新しいパスを追加することを考えたいと思います。パスを追加する場合,基本的に絶対 的な適合度は上昇するため,先程の尤度比検定の考え方とは反対に「パラメータを 1 個追加する 価値があるだけの適合度の改善が見られる」ようなパラメータは追加してあげればよいわけです。 modificationIndices() という関数は,現状モデル内でパラメータが自由推定になっていない   全てのパス*17 について, 「そこにパスを追加するとどれだけ適合度が改善するか」をまとめて表し てくれます。 修正指標 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_C =~ 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_C =~ 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_C =~ Q1_1 というパスを追加すると適合   度が最も改善する, ということです。 出力では mi 列に続いて,  epc    そのパスを自由推定にした際のパラメータの変化量の予測値。パスが引かれていない場合 は 「0 からの変化量」 なので推定値そのものの予測値を意味する。 sepc.lv 潜在変数 lv を標準化した際の EPC (standardized EPC)。     sepc.all 全ての変数を標準化した際(標準化解)の EPC。   *17 「自由推定になっていない」 ということは,例えば 1* によって係数を 0 以外の定数に固定している場所も検討対象  にしてくれる,ということです。 

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

57

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




が表示されています。
きっと多くの場合では mi が大きいところは sepc.all が大きくなってい








ることでしょう。ということで,パスを追加する際には mi が大きいほうから試してみると良いで




しょう。
さっそく f_C =~ Q1_1 を追加して推定してみます。




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

model3 <- "
f_A =~ Q1_1 + Q1_2 + Q1_3
f_C =~ Q1_6 + Q1_7 + Q1_8 + Q1_1
f_A ~ age + gender
f_C ~ 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-21 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_C =~

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

58.

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 58 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_C ~ 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_C 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 *** ---

59.

7.7 モデルの修正 9 10 11 12 13 14 15 16 17 18 19 20 21 59 Signif. codes: 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_C =~ Q1_1 を追加したことによって図 7.15 のような状態になりました。つまり完全な単   純構造ではないと考えたほうがデータ的には当てはまりが良い,ということです。ですが修正指標 (mi)も,尤度に基づく指標です。つまりサンプルサイズが大きいほど当てはまりは大幅に改善す   るように見えてしまいます。したがって,本質的には無意味なパスが手元のデータにおいては偶然 それなりの改善を示しただけの可能性もあります。同様に,モデルが複雑になるほど自由度も大き くなり共分散構造の乖離度も大きくなりやすいと考えられます。 「f_C =~ Q1_1 を追加すると良   い」ということが,本当に「Q1_1 が因子 C を反映した項目である」ことを示しているのかは,実質   的な意味に基づいてよく考える必要があるでしょう。 ということで,モデルの修正の際には,パスを追加・削除することが自分の仮説と照らし合わせ て受け入れられるかをよく考えるようにしましょう。 実践場面でよく見られる―が適切に用いられていないことも多い(吉田他,2020)―修正とし ては,図 7.16 のように独自因子の間の相関を追加するパターンがあります。例えば時系列モデル において,異なる時期に聞かれた同一の項目間においたり,あるいは DIF のように特定の属性な どが影響していると言えそうな場合には妥当なパスの追加だと思われます。このような場合にも, パスを追加する場合にはなぜそのパスを追加するべき(しても問題ない)と考えたかをきちんと説 明するようにしましょう。裏を返せば,そのパスが意味するところが説明できないような場所に は, いくら適合度が改善するにしてもパスを追加しないほうが良いだろう, ということです。 また,モデルの修正は割と終わりなき戦いです。というのも,modificationIndices() で出力  

60.

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

61.

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

62.

7.8 カテゴリカル変数の SEM 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 62 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: 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|) education ~ gender Q1_C Thresholds: education|t1 education|t2 education|t3 education|t4 Variances: .education 結果を見ると,Variances: のところにある education に,潜在変数であることを示す . がつ       いて .education になっており,その値が 1 に固定されています。また,表示はされていないので   すが,.education の平均値は自動的に 0 に固定されてパラメータ推定が行われます*19 。すなわ   ちカテゴリカルな内生変数を扱う場合には,その変数(ここでは education)の背後にある連続的   なものが平均 0, 分散 1 に標準化された値として考慮されている, ということです。 そのもとで,Thresholds: のところには各カテゴリの閾値が表示されています。Chapter 4 で   説明した I-T 相関の背後の連続量の図 4.14 に当てはめると図 7.18 のような状態だということで す。 *19 以前のバージョンでは,Intercepts: にも自動的に .education の値が表示されていたような気がするのですが,     いつの間にか無くなっていました。ただ,モデル式に education ~ 0 を追加(切片を 0 に固定)しても結果は全く変 わらないことから,平均値は 0 に固定されていることが分かります。  

63.

7.8 カテゴリカル変数の SEM 63 図 7.18: education の閾値 7.8.2 (おまけ)外生変数がカテゴリカルな回帰分析・パス解析 「外生変数がカテゴリカル」ということは,回帰分析の説明変数がカテゴリカルな場合と同じよ うに考えたら OK です。すなわち,その変数が二値カテゴリカルであればそのまま使用してよく, 多値カテゴリカルであればダミー変数に置き換えることで対応可能です。例えば多値カテゴリカ ル変数である education を説明変数とする, 図 7.19 の回帰分析モデルを考えます。   図 7.19: 外生変数がカテゴリカルな場合 education は順序カテゴリカル変数ですが,いったん順序を無視してダミー変数へ変換してみ   ます(順序性を考慮したダミー変数化はあとで説明)。ダミー変数をデータフレームに追加する簡 単な方法として,contr.treatment() 関数を利用する方法があります*20 。   一気にダミー変数を作る 1 2 3 # ダミーコーディングの形を作る関数 # 数字はカテゴリ数 contr.treatment(5) 1 2 3 4 2 3 4 5 1 0 0 0 0 2 1 0 0 0 3 0 1 0 0 *20 ダミー変数を作るためのパッケージとして makedummies というものもあります。 こちらはデータフレーム内の   factor 型変数を一気に全部ダミー変数に変えてくれるものです。用途に応じて使い分けると良いでしょう(ただ 2019 年が最終更新なので急に使えなくなるかも)。  

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

5
6

64

4 0 0 1 0
5 0 0 0 1

contr.treatment() 関数では第一カテゴリを基準カテゴリとしたダミー変数を作成してくれ




ます。
ダミー変数化
1

contr.treatment(5)[dat$education, ]

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 'max' / 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 の行










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

65

• education == NA の人なら NA NA NA NA の行








が返ってくるわけです。
これをもとの dat の存在しない列名に代入してあげれば OK ですね。


1



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

こうして作成したダミー変数を入れたモデルを作成して実行しましょう。
ダミー変数を入れて回帰モデル
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

lavaan 0.6-21 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

Total
2432

66.

7.8 カテゴリカル変数の SEM 30 31 32 33 34 35 36 66 Intercepts: .Q1_A 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 Variances: .Q1_A 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)) という感じで指定しても   良いのですが,もし全ての内生変数である観測変数がカテゴリの場合*21 ,ordered  = TRUE とす  *21 因子得点から観測変数への回帰を含むモデルにおいて ordered = TRUE にすると, 内生変数となった観測変数も自   動的にカテゴリ変数として扱われます。このように観測変数の回帰と因子分析を組み合わせた場合には意図せぬカ

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

67

ることで全てカテゴリカルになります。
カテゴリカル検証的因子分析
1
2
3
4
5
6
7
8

# まずは普通にモデル式を作成
model <- "
f_1 =~ Q1_1 + Q1_2 + Q1_3
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

lavaan 0.6-21 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
NA

Test Statistic
Degrees of freedom
P-value (Unknown)
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 =~

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

テゴリ化を行ってしまう可能性があるので気をつけましょう。

68.

7.9 多母集団同時分析 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 Q1_6 Q1_7 Q1_8 68 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 Estimate Std.Err z-value P(>|z|) Std.lv Q1_1|t1 -1.887 0.051 -36.934 0.000 -1.887 Q1_1|t2 -1.234 0.034 -36.437 0.000 -1.234 Q1_1|t3 -0.743 0.028 -26.414 0.000 -0.743 Q1_1|t4 -0.326 0.026 -12.588 0.000 -0.326 Q1_1|t5 0.434 0.026 16.487 0.000 0.434 Q1_2|t1 -2.144 0.064 -33.743 0.000 -2.144 Q1_2|t2 -1.534 0.040 -38.430 0.000 -1.534 Q1_2|t3 -1.179 0.033 -35.716 0.000 -1.179 Q1_2|t4 -0.478 0.027 -18.047 0.000 -0.478 Q1_2|t5 0.481 0.027 18.127 0.000 0.481 Q1_3|t1 -1.829 0.049 -37.433 0.000 -1.829 Q1_3|t2 -1.303 0.035 -37.181 0.000 -1.303 Q1_3|t3 -0.963 0.030 -31.885 0.000 -0.963 Q1_3|t4 -0.328 0.026 -12.668 0.000 -0.328 [ reached 'max' / getOption("max.print") -- omitted 16 rows ] 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 Covariances: f_1 ~~ f_2 Thresholds: 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|) 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 ordered を指定せずにやった結果と比べると,因子負荷の値(Std.all 列)が少し大きくなって     いることがわかります。 このあたりは探索的因子分析のときと同じですね。 7.9 多母集団同時分析 分析結果の一般化可能性を高めるためには「異なる属性間で一貫して同じ結果が得られるか」を 検討するのが一つの手段となります。あるいは異なる属性・集団の間での差異に関心がある場合

69.

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

70.

7.9 多母集団同時分析 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 47 48 49 70 Optimization method Number of model parameters NLMINB 24 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 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 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 Std.all 0.852 0.534 0.465 0.735 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4

71.

7.9 多母集団同時分析 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 f_A 71 1.000 1.000 1.000 Group 2 [2]: 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 行目)。そのため,当然ながら平均値な どの比較はできません。そして因子得点をグループ間で比較可能にするためには,因子負荷と切 片がともにグループ間で等しいという制約を置く必要があります。多母集団同時分析の目的の一 つは,因子構造が同じかどうかを検証することですが,同一性が満たされて初めて,異なるグルー プ間での因子得点の平均が比較可能になります。 因子負荷が等しいという条件は,そもそも因子自体がグループ間で異なっていないことを示す ために必要です。これが満たされていないと, (仮にモデルの矢印が同じであっても)因子に占める 各項目の重みが変わってしまうため, 完全に同じ因子とは言えないのです。 では,切片が同じという制約はなぜ必要なのでしょうか。ここでいう「切片」は,回帰分析の「切 片」と同じようなものです。因子分析では説明変数にあたる因子得点が潜在変数のため,少し厄介

72.

7.9 多母集団同時分析 72 なことになっているのです。 これまで 1 因子の因子分析モデルは (7.48) 𝐲𝑖 = 𝐟 𝑏𝑖 + 𝜺𝑖 という形を取っていました。 ですが本当は, 回帰分析での 𝑏0 にあたる切片項 (ここでは 𝜏 と表記し ます) が存在しており, (7.49) 𝐲𝑖 = 𝜏 + 𝐟 𝑏𝑖 + 𝜺𝑖 という式になっています。 通常 SEM(因子分析) では, 観測変数 𝐲𝑖 は標準化されていれば (あるい は標準化解を出す場合には),暗黙に 𝜏 = 0 となります。そのためにこれまでは 𝜏 を無視してきま した。ですが多母集団同時分析では,観測変数 𝐲𝑖 が標準化されていたとしても,切片項まで考慮し ないと因子得点の比較ができなくなってしまいます*22 。 例えば,データ全体で標準化された(全体平均が 0 の)観測変数 𝐲𝑖 の平均値が,男性のみで計算 すると 0.3, 女性のみで計算すると-0.3 だった,つまり男性のほうが平均的に高い得点をつけてい たとしましょう。これは心理尺度で言えば,男性のほうが「当てはまる」寄りの回答をしがち,とい う状況に相当します。そう考えるとこの 0.6 の差は「男性のほうが関連する因子得点 𝐟 が高い」と いうことを意味しているように見えるかもしれませんが,まだそうではない可能性を持っていま す。 もしグループごとに異なる切片 𝜏 (𝑔) があるとすると, 先程の式は (7.50) 𝐲𝑖 = 𝜏 (𝑔) + 𝐟 𝑏𝑖 + 𝜺𝑖 となります。ここで,もし男性の切片 𝜏 (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】因子負荷が同じ *22 多母集団同時分析以外でも切片を考えても良いのですが, グループ間での比較をしない限りはさほど重要ではない のでこれまで無視してきました。

73.

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

74.

7.9 多母集団同時分析 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 47 48 49 50 51 74 Number of equality constraints 4 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 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 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A

75.

7.9 多母集団同時分析 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 75 Group 2 [2]: Latent Variables: f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 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.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 (.p1.) (.p2.) (.p3.) (.p4.) 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 にした」時の推定値なので,グループ間で値が変わってしまいます。せっかく等値制約を 置いたのに,これでは多少違和感がありますが,そういうものなのであまり気にしないでくださ

76.

7.9 多母集団同時分析 76 い。実際に弱測定不変モデルの結果を報告する際には,たぶん因子負荷は Estimate 列の値を載せ   て, 各グループの因子得点の分散を記入することが多いと思います。 続いて,弱測定不変モデルと配置不変モデルの間で適合度が著しく悪化していないかを検証し ます。比較の方法は セクション 7.6.5 と同じです。多母集団モデルでは,各パラメータをグループ ごとに異なるものとしてそれぞれ自由に推定していました。ここに等値制約を置くということは, 自由に推定できるパラメータの数が減少していることを意味するので,それだけ適合度は悪くな るはずです。 モデル修正におけるパスの削除が「そのパスの係数を 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 result_base result_weak Df AIC BIC Chisq Chisq diff RMSEA Df diff Pr(>Chisq) 4 31636 31775 34.458 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 は改善しました。尤度比検定も有意ではなか ったということで, 弱測定不変性が確認されたと言って良いでしょう。 続いて, 強測定不変モデル (因子負荷+切片) の検討に移ります。

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

77

強測定不変モデル
1
2

3
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

# group.equalに"intercepts"を追加
result_strong <- cfa(model, data = dat, group = "gender", std.lv = TRUE,
group.equal = c("loadings",
"intercepts"))
summary(result_strong, standardized = TRUE)

lavaan 0.6-21 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
Intercepts:

(.p1.)
(.p2.)
(.p3.)
(.p4.)

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

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

78.

7.9 多母集団同時分析 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 76 77 78 .Q1_1 .Q1_2 .Q1_3 .Q1_4 78 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 1.710 0.804 0.883 1.616 1.000 Std.Err 0.092 0.062 0.066 0.092 z-value 18.510 13.057 13.277 17.663 P(>|z|) 0.000 0.000 0.000 0.000 Std.lv 1.710 0.804 0.883 1.616 1.000 Std.all 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 (.10.) (.11.) (.12.) (.13.) 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 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 とい うことは,女性の方が各観測変数のグループ平均が高かったのは確かに因子得点が平均的に高い ためだ,といえそうです。一方で,もしも適合度がひどく悪化していたら「切片がグループ間で同じ というのはおかしい」ということになり,観測変数のグループ間の差は,むしろ切片項に起因する

79.

7.9 多母集団同時分析 ものだと言えそうです。 強測定不変モデルも加えて 3 つのモデル比較 1 2 # 3モデル以上でも一気に出来ます summary(compareFit(result_base, result_weak, 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 26 27 28 29 ################### 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 も強測定不変モデルを支持しているた め, ここは強測定不変性が認められたと結論付けて先に進んでみましょう。 あとはどこまで測定不変性が認められるかを試すだけです。とりあえず一気に残りの全てのモ デルを推定してみます。 79

80.

7.9 多母集団同時分析 80 残りのモデルも一気にやってしまう 1 2 3 4 5 6 7 8 9 10 11 12 13 14 # group.equalに"intercepts"を追加 # 厳密な測定不変モデル # 独自因子の分散共分散を制約に追加 # 独自因子の共分散を追加している場合は"residual.covariances"も入れる result_strict <- cfa(model, data = dat, group = "gender", std.lv = TRUE, group.equal = c("loadings", "intercepts", "residuals")) # (ほぼ完全な測定不変モデル) # 共通因子の分散共分散を制約に追加 # 2因子以上の場合は"lv.covariances"も入れる result_almost <- cfa(model, data = dat, group = "gender", std.lv = TRUE, group.equal = c("loadings", "intercepts", "residuals", "lv.variances")) # (完全な測定不変モデル) # 因子得点の平均を制約に追加 result_complete <- cfa(model, data = dat, group = "gender", std.lv = TRUE, group.equal = c("loadings", "intercepts", "residuals", "lv.variances", "means")) そして全部一気に適合度を比較してみます*24 。 全てのモデルを比較 1 2 3 4 5 6 7 8 summary(compareFit( result_base, result_weak, result_strong, result_strict, result_almost, result_complete )) 1 2 3 4 5 6 7 ################### Nested Model Comparison ######################### Chi-Squared Difference Test result_base result_weak Df AIC BIC 4 31636 31775 7 31631 31753 Chisq Chisq diff RMSEA Df diff 34.458 35.925 1.468 0.000000 3 *24 ここまでのプロセスの大半を一度にやってくれる関数として,semTools::measurementInvariance() という関    数があります。一応今のところは使えるのですが,やがて消えることが公式にアナウンスされています。 「代わりに measEq.syntax() を使え」とアナウンスされているのですが,これは「指定した等値制約を置いたモデル式を作っ てくれる関数」のようです。つまり,機械的にとりあえずいろいろな不変モデルを試すのではなく,一つ一つの結果 を見て能動的に判断していけよということなのかもしれません。 

81.

7.9 多母集団同時分析 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 47 48 49 50 result_strong 10 31638 31743 48.938 13.012 0.052389 result_strict 14 31652 31733 70.463 21.526 0.060026 result_almost 15 31657 31732 77.395 6.931 0.069841 result_complete 16 31760 31830 183.159 105.765 0.293522 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 *** --Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 81 3 4 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 この結果を踏まえてどこまでの測定不変性を認めるかについては諸説ありそうです。基本的に は適合度指標が許容範囲内にある中で最も制約の強いモデルを選べば良いのではないか,と思い

82.

7.9 多母集団同時分析 82 ますが,人によって許容範囲内であっても前のモデルから適合度指標が著しく低下している場合 にはアウトとする人もいます。 7.9.3 (おまけ)部分的な測定不変性 測定不変性がどこまで満たされるかをもっと厳密に検証しようとすると,ギリギリ許容できる レベルはきっと上で見たいくつかのモデルの間にあるでしょう。例えば弱測定不変モデルの適合 度は許容範囲だが強測定不変モデルまでいくと許容範囲から外れてしまう場合,置くことのでき る等値制約は 「全ての因子負荷+一部の切片」 ということになる可能性が高いです。 ここからは,そのような部分的な測定不変性を lavaan で推定する方法を紹介していきます。こ   こでは,仮に「弱測定不変までは認められるが強測定不変性は認められなかった」として,その間の 部分的な強測定不変性を検証していきます。 考え方としては,許容されなかったモデルをベースに「どこの等値制約を外すと良さそうか」を 見ていくことになります。 そのために有用な関数が lavTestScore() です*25 。   外すべき等値制約を見つける 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 ここで表示されているのはスコア検定(またの名をラグランジュ乗数検定)と呼ばれるもので *25 パラメータを自由推定にした際の適合度の改善を見るわけなので modificationindices() も使えそうなのです  が,こいつは「等値制約を外したとき」を評価してはくれないのでここでは使えません。 

83.

7.9 多母集団同時分析 83 す。 compareFit() 関数で出てくる検定(尤度比検定)は,複数のネストされたモデルについて,   「制約のないモデル」を基準として,(a) グループ間で等値制約を置く,(b) 矢印を消す(あるパラ メータの値を 0 に制約する)など「制約を増やしたときに,増やした制約の数の割に尤度が低下し ていないか」 を確かめるものでした。 スコア検定はこれとは反対に,「制約のあるモデル」を基準として, 「制約を減らしたときに,減 らした制約の数に合った尤度の改善が見られるか」を確かめるものです。帰無仮説自体は尤度比検 定のときと同じで「2 つのモデルの尤度(厳密には最尤推定値)が同じであるか」なので,スコア検 定が有意だった場合には 「制約を減らしたほうが良さそう」 と判断できるわけです。 一番上に出ている $test は,モデル全体での検定の結果です。今回は全ての因子負荷と切片に   等値制約が置かれた強測定不変モデル(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 3 4 1 2 3 4 5 6 7 8 9 10 11 # group.partialにモデル式の形で指定する # 切片は "~ 1"で指定可能でした result_strong_p <- cfa(model, data = dat, group = "gender", std.lv = TRUE, group.equal = c("loadings", "intercepts"), group.partial = "Q1_1 ~1") summary(result_strong_p, standardized = TRUE) lavaan 0.6-21 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 26 7 802 1630

84.

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 84 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) Test statistic for each group: 1 2 39.596 9 0.000 11.227 28.369 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.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 (.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:

85.

7.9 多母集団同時分析 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 f_A =~ Q1_1 Q1_2 Q1_3 Q1_4 85 (.p1.) (.p2.) (.p3.) (.p4.) 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 (.12.) 4.310 (.13.) 4.450 0.476 Std.Err 0.044 0.040 0.042 0.041 0.053 z-value 100.948 112.334 102.718 108.457 8.927 P(>|z|) 0.000 0.000 0.000 0.000 0.000 Std.lv 4.463 4.522 4.310 4.450 0.515 Std.all 3.273 4.110 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 Intercepts: .Q1_1 .Q1_2 .Q1_3 .Q1_4 f_A 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 ################### 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

86.

7.10 lavaan の記法  16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 86  ####################### 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 ################## 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 つしかあり ません。 つまりそのままでは推定に失敗する, ということです*26 。 試しに 2 項目 1 因子の (うまくいかない) モデルをやってみましょう。 *26 一応他の因子との因子間相関 (両方向の矢印)があれば,2 項目でも問題なく推定できるようになりますが,安定し ないことも多々あります…

87.
[beta]
7.10 lavaan の記法


87



うまくいかない 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.

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-21 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 項目の

88.
[beta]
7.10 lavaan の記法


88



因子負荷に等値制約をかけることで推定するパラメータ数を減らす事ができます。
等値制約をかける
1

model <- "f_A =~ b1 * Q1_1 + b1 * Q1_2"

モデルの修正のところで,右辺の変数名の前に 0* をかけることで共分散をゼロに固定する方




法を紹介しました。
それと同じように,
ここでは右辺の変数名の前に共通の b1 をかけています。




等値制約をかけて推定
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-21 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) という表記が追加さ




89.

7.10 lavaan の記法  89  れています。パラメータ数を減らしたことによって,Degrees of freedom が 0(つまり飽和モ   デル) になり, 晴れてパラメータの検定が行われるようになりました。 INFO (意見)尺度得点を和得点にするなら因子負荷の等値制約が必要じゃないか 尺度得点として,因子得点ではなく和得点を使うケースが多いことはすでに説明したとお りです。このような場合でも,尺度作成論文では通常「1 項目が 1 因子にのみ負荷している 状態(完全な単純構造)」で CFA を行い,モデル適合度を確認しています。ですがよく考える と,尺度得点が和得点であるならば,CFA を行う際に因子負荷には等値制約をかけたほう がよいのではないかという気がしています。 因子負荷の大きさは,その項目が因子得点の推定に与える影響の強さを表しています。言い 換えると,因子負荷はその項目の重みという見方ができるということです。そう考えると, 等値制約を置かない CFA によるモデル適合度の検証は「重み付け得点を使用した場合の 適合度」であり,もしも項目の重みが極端に異なる場合は,重み付けない単純な和得点では 著しく適合度が悪化する可能性があります。 したがって, 「和得点でのモデル適合度」を検証するために,因子ごとに全ての因子負荷に等 値制約をおいた状態でのモデル適合度を評価すべきではないか,という気がするのですが 実際にそのようにしている研究は見たことが無い気が…と思っていたらこんな論文があり ました。→ McNeish & Wolf(2020) 等値制約は他にも,多母集団同時分析で特定の回帰係数が同じかどうかを評価する際や,複数時 点で同一のモデルを測定する場合に共通のパスが同じ値かを検討する際にも使ったりします。多 母集団同時分析に関して, 例えば 図 7.19 の回帰分析モデルを性別ごとに行い, 「age が Q1_A にお     よぼす影響」が男女間で同じかを検討したい場合には,以下のようにして,等値制約あり/なしの モデルを比較すると良いですね。 部分的な等値制約の検討 1 2 3 4 5 6 7 8 9 10 11 12 13 # 制約なしモデル model_base <- ' Q1_A ~ age + education ' # 制約ありモデル model_const <- ' Q1_A ~ c(b,b) *age + education ' result_base <- sem(model_base,data=dat,group="gender") result_const <- sem(model_const,data=dat,group="gender") summary(compareFit(result_base, result_const))

90.

7.10 lavaan の記法  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 90  ################### Nested Model Comparison ######################### 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 ####################### 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: 間違えちゃった このモデルを推定すると, (設定をミスっているので) 推定値が変なことになります。

91.
[beta]
7.10 lavaan の記法


91



間違えたまま推定しちゃった
1
2
3
4
5

model <- "
f_A =~ Q1_1 + Q1_7 + Q1_3
f_C =~ Q1_6 + Q1_2 + Q1_8
"
result <- cfa(model, data = dat, std.lv = TRUE)

1
2
3

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

lavaan 0.6-21 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

Estimate

Std.Err

z-value

P(>|z|)

Std.lv

Std.all

0.500
0.407

0.033
0.030

15.207
13.355

0.000
0.000

0.500
0.407

0.356
0.309

92.

7.10 lavaan の記法  26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 92  Q1_3 f_C =~ Q1_6 Q1_2 Q1_8 0.726 0.034 21.515 0.000 0.726 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 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 Covariances: f_A ~~ f_C Variances: .Q1_1 .Q1_7 .Q1_3 .Q1_6 .Q1_2 .Q1_8 f_A f_C Covariances: の推定値(35 行目)が 1.290 になっています。この値は,2 つの因子 f_A と f_C         の相関係数を表しているはずなので 1 を超えるのは明らかにおかしな話です。 このように, モデル の設定をめちゃめちゃ失敗すると不適解が発生してしまいます。不適解が生じた場合には,基本的 にはモデルに誤設定がある(あまりに変なパスを引いてしまっている or 絶対に必要なパスを引い ていなかったり, 変な変数が入っていたり) 可能性が高いので, まずはそれを修正するべきです。 ただ場合によってはモデルの設定は問題ないという自負があるにも関わらず不適解が生じるこ とがあります。よくあるのはデータが悪い状況です。SEM では,データにおいて観測された分散 共分散をもとにして,モデル上の分散共分散を推定していきます。したがって,データが酷い(サン プルサイズが小さい・欠測値が多すぎる・適当な回答が見られる)ときには,モデルが正しくても うまく推定できないことがあります*27 。Chapter 3 において,事前に適当な回答をしているデー タを除外する方法を紹介したのはこのような事態を回避するためでもあったのです。 そして特にモデルが複雑な場合やデータがひどい場合には,独自因子の分散がマイナスになっ たり相関係数が 1 を超えるなどの事態 (Heywood case) が起こることがあります。 基本的には不 適解はそのまま報告してはいけないのですが, • どう考えてもモデルは正しいし, • データには問題ない(と思っている)し, • 不適解の部分以外はいい感じの推定値だし, *27 R に慣れた方は, 試しに「変数間の相関関係を完全に無視してデータのサイズだけ合わせたデータ」を乱数生成して 試してみてください。ほぼ確実に推定失敗すると思います。

93.
[beta]
7.10 lavaan の記法


93



• 不適解といってもギリギリアウト(独自因子の分散が-0.005 とか)
という感じで,自分は悪くないと言い切れる自信がある状況であれば,多少の不適解には目をつ
ぶって*28 不等式制約をかけてとりあえず結果を報告することがあります。そういう場合には,パ
ラメータに上限・下限を定めて推定するという方法をとります。
パラメータの上限・下限を決める
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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

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

lavaan 0.6-21 ended normally after 29 iterations

# 制約をかけたいパラメータにラベルを付ける
f_A ~~ cor * f_C
# パラメータの制約を不等号で記述する
cor < 1
# 同様に,独自因子の分散を0以上にしたいなら
Q1_1 ~~ var_e1 * Q1_1
var_e1 > 0
"
result <- cfa(model, data = dat, std.lv = TRUE)
summary(result, standardized = TRUE)

Estimator
Optimization method
Number of model parameters
Row rank of the constraints matrix
Number of observations

ML
NLMINB
13
2
2432

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

862.410
8
0.000

Parameter Estimates:
Standard errors

Standard

*28 独自因子の分散の真値がほぼゼロの場合,
標本誤差の影響などで 0 を下回ってしまうことが実際にあるのです。そ

うだと言い切れるなら仕方ないのです。

94.

7.10 lavaan の記法  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 94  Information Information saturated (h1) model Expected Structured Latent Variables: Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.585 0.315 0.843 0.033 0.031 0.032 17.760 10.041 26.209 0.000 0.000 0.000 0.585 0.315 0.843 0.416 0.239 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 f_A =~ Q1_1 Q1_7 Q1_3 f_C =~ Q1_6 Q1_2 Q1_8 Covariances: f_A ~~ f_C (cor) 1.000 Variances: .Q1_1 .Q1_7 .Q1_3 .Q1_6 .Q1_2 .Q1_8 f_A f_C (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 ということで,Warning も出ずに無事推定できました。 ただ, この方法はあくまでも対処療法で   す。まずはモデルの誤設定の可能性を完全に消し去るのが第一です。 不等式制約と同じように,等式制約や四則演算による制約を置くことも可能です。例えば(意味 があるかはともかく) 「項目 1 の因子負荷」が「項目 2 と項目 3 の因子負荷の平均」よりも大きいと いうことが仮説から言えるとしたら, 次のような書き方が出来ます。 等式制約も置けないことはない 1 2 3 4 model <- " f_A =~ b1*Q1_1 + b2*Q1_2 + b3*Q1_3 + Q1_4 + Q1_5 b1 > (b2 + b3)/2 "

95.

7.10 lavaan の記法  95  7.10.3 推定しないパラメータの定義(媒介分析) SEM でよくあるのが,ある変数が別の変数に及ぼす効果を「直接的な効果(直接効果)」と「別の 変数を介して及ぼす効果 (間接効果) 」 に分解して考えるモデルです。 図 7.22 では, 学歴に性別が及 ぼす効果について, 「性別が勤勉性 (Q1_C) を介して学歴に影響している」 という間接効果を考えて   います。 図 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 

96.

7.10 lavaan の記法  96  を全て示すことができれば,Q1_C による媒介効果を認めることができるわけです*29 。   それでは lavaan で媒介分析を行ってみましょう。   媒介分析 1 2 3 4 5 6 7 8 model <- " education ~ b*Q1_C + c*gender Q1_C ~ a*gender # 制約ではなく事後的な計算をして欲しい ab := a*b total := ab + c " ここでのポイントは ":=" という記号です。これをを使うと,ラベル付けしたパラメータの推定   値に基づいて計算をしてくれます。 上の例では, まず 図 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 lavaan 0.6-21 ended normally after 7 iterations Estimator Optimization method Number of model parameters Number of observations ML NLMINB 5 Used 2232 Total 2432 Model Test User Model: Test statistic Degrees of freedom 0.000 0 Parameter Estimates: *29 もしこれに加えて 𝐻 ∶ 𝑐 = 0 が示せれば, 完全な媒介効果だといえます。因果関係における中継点を見つけた,と 5 いう意味で因果関係のメカニズム解明にかなり役立つ情報になりえます。

97.

7.11 同値モデル 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 97 Standard errors Information Information saturated (h1) model Standard Expected Structured Regressions: education ~ Q1_C gender Q1_C ~ gender 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 Estimate 0.005 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 Variances: .education .Q1_C Defined Parameters: ab total Defined Parameters: という箇所が増えました。定義されたパラメータについても,自由推定   されたパラメータと同じように仮説検定まで行ってくれます。ということで,これを使えば先程の 仮説群をまとめて検証することが出来ます。ただ今回の場合では,そもそも total の推定値から,   𝐻1 ∶ 𝑎𝑏 + 𝑐 ≠ 0 が有意ではないことが分かるのでおしまいです*30 。 7.11 同値モデル 突然ですが,同じ 4 つの観測変数について,図 7.23 に 2 つの異なるモデルを考えました。上は 「gender が education に及ぼす影響」を考えるモデルです。これに対して下のモデルでは矢印の     向きを全てひっくり返して「education が gender に及ぼす影響」を推定するモデルになっていま     す。 図 7.23: 矢印の向きを変えてみた 普通に考えたら,少なくとも「学歴によって性別が影響を受ける」よりは「性別によって学歴が影 *30 当然ですが,total の値は lm(education ~ gender,data=dat) の結果と一致します。    

98.

7.11 同値モデル 98 響を受ける」上のモデルのほうが自然な気がしますが,とりあえずこれらのモデルを分析してみま しょう。 とりあえず 2 つのモデルを推定して比較 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 model1 <- " education ~ Q1_C Q1_C ~ Q1_A Q1_A ~ gender " 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 をつけて summary(compareFit(result1, result2, nested = FALSE)) 実はこの 2 つのモデルでは,RMSEA, CFI, TLI, SRMR といった適合度指標は全て完全に同 じ値になります*31 。ダガー( † )がついているのは,数値計算上の細かいズレのためであり,これ   も小数点第 9 位くらいでやっと差が出る程度の違いしかありません。適合度指標が完全に一致し ているということは,モデル上の共分散行列(𝚺)に関しても全く同じ値になっているということ なので,これらの 2 つのモデルは統計的には優劣をつけることが出来ません。こうしたモデルの ことを同値モデル (equivalent model) と呼びます。 基本的には,回帰を含む SEM のモデルには多少なりとも同値モデルが存在しており,可能であ ればこうした同値モデルに関しても議論をしておくべきだという意見もあります(Kang & Ahn, 2021)*32 。多くの場合,同値モデルは 図 7.23 のように,どこかしらの矢印の向きを反対にしたモ デルです。一部の人は SEM(あるいは回帰分析)の矢印を「因果関係」かのように扱ってしまいま すが,これは誤った考え方です。統計的にはデータに対する当てはまり(=モデルの「良さ」)が完全 *31 AIC や BIC がぜんぜん違う値になっているのですが, この理由は分かりません…何か計算方法のせいだとは思う のですが,とりあえず今回のケースでは AIC や BIC はあてにならないと思ってください。 *32 ちなみに同値モデルの作り方に関しては Mayekawa(1994) などにあります。

99.

7.12 𝜔ℎ を求める 99 に同じモデルがあるということは,分析上は矢印の向きはどちらでも良いといえます。これは回帰 分析の 𝑥 と 𝑦 は入れ替えても問題ないのと同じです。したがって,特に SEM を実施する際に は,分析者は統計以外の側面から,つまり先行研究などを踏まえてなるべく理論的に矢印の向きを 指定する必要があります。 「同値モデルに関しても議論をしておくべき」というのは「なぜ矢印の 向きが逆ではいけないのか」 をきちんと説明しておく必要があるということです。 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)

100.

7.12 𝜔ℎ を求める 100 𝜔 係数を算出するためには semTools::compRelSEM() という関数を使います*33 。   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 について式を展開すると(因子 𝑓𝐴 は内生変 *33 少し前までは semTools:reliability() という関数もあったのですが, すでに deprecated になっているので   semTools::compRelSEM() を使います。  

101.

7.12 𝜔ℎ を求める 101 数となっているために誤差 𝜺𝐴 を追加して) , 𝐲 1 = 𝐟 𝐴 𝑏1 + 𝜺 1 𝑔 = (𝐆𝑏𝐴 + 𝜺𝐴 )𝑏1 + 𝜺1 (7.51) error 𝑔 ⏞⏞ = 𝐆𝑏𝐴 𝑏1 + ⏞ 𝑏1⏞ 𝜺⏞ 𝐴 + 𝜺1 となるため,真値 𝑡 に相当する部分は 𝐆𝑏𝐴 𝑏1 となります。したがって,その係数 𝑏𝐴 𝑏1 を使って, 𝑔 𝑔 高次因子モデルにおける 𝜔ℎ𝑜 は 2 𝜔ℎ𝑜 = (∑𝐼𝑖=1 𝑏⋅𝑔 𝑏𝑖 ) (7.52) 𝜎𝑦2total となります。𝑏⋅𝑔 は項目によって 𝑏𝐴 か 𝑏𝐶 になるものです。 𝑔 𝑔 数理的にはそういう扱いですが,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() を利用することで, 「完全な単純構造ではない場合の   𝜔」や「独自因子の間に相関を認めた場合の 𝜔」などもフレキシブルに計算可能です。

102.

7.13 もう一つの SEM 102 7.13 もう一つの SEM これまでに紹介してきた SEM は,共分散構造分析という別名にも表れているように,観測変数 間の共分散(相関係数)をうまく復元できるようにモデルのパラメータを推定する方法です。この 共分散に基づく SEM (Covariance Based SEM: CB-SEM) に対して, 主にマーケティングの分野 として(とはいえ今では様々な分野で使われている) ,異なる SEM が独自に発展しているようで す。ということで最後に,もう一つの SEM こと PLS-SEM(Partial Least Squares SEM: Wold, 1975)を簡単に紹介します。 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 は,ホテル利用者が行う評価に及ぼす影響をイメージした仮想的なグラフィカ ルモデルです*34 。このモデルには,以下の 3 つの潜在変数およびそれらを測定する計 7 項目の観 測変数があるとします。 •【満足度】ホテルのサービスに対する満足度。以下の 3 項目によって,それぞれ 7 段階評価 で測定される。 – スタッフの対応は良かった。(sat_1)   – ホテルは綺麗だった。(sat_2)   – 食事は美味しかった。(sat_3)   •【価格】(主観的な)価格。 「1 泊あたりの価格はどう感じましたか。(price)」という 1 項目   に対して 「とても安かった」 から 「とても高かった」 までの 7 段階評価。 •【評価】ホテルの評価。以下の 3 項目によって,それぞれ 7 段階評価で測定される。 – このホテルのファンになった。(rate_1)   – 機会があればまたこのホテルに泊まりたい。(rate_2)   *34 このモデルはあくまでも仮想です。 一応元ネタは Albers(2010)ですが,皆さんの知見に照らし合わせたときに「そ んな因果関係なわけないだろ!」といった批判は甘んじて受け入れます。

103.

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

104.

7.13 もう一つの SEM 104 reflective と formative の違いを表した図が,図 7.27 です。reflective measurement では,各観 測変数が尋ねている内容(構成概念の一側面)の共通部分(積集合)が潜在変数として表れている, と考えます。そして各観測変数 (rate_1-3) は共通の原因変数( 「評価」)の影響を受けているため,   基本的に相関係数は高いはずです。一方で formative measurement では,そもそも各観測変数が 高い相関を持っている必要はありません。そして潜在変数は,観測変数の和集合として規定されて いる, と考えているわけです。 図 7.27: 2 つの測定方法の違い (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 の推定では構造モデル と測定モデルを区別せずにまとめて同時に推定しているので,このような場合はわざわざ「潜在変 数に置き換える」 ことはせずに, 潜在変数のまま扱うことができます。

105.

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

106.

7.13 もう一つの SEM 106 図 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 つのステップを解が変わらなくなるまで繰り返すことで, 最終的な推定値を得ます。 細か

107.

7.13 もう一つの SEM 107 図 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 のほうが良い。というのも CB-SEM は変数の分散共分散行列をもとに推定を行うが,その方法として,多変量正規性を仮定した 最尤法などが用いられるため, 仮定が満たされない場合は厳しい。 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 による推定値 には一致性がないことが昔から知られており(e.g., Dijkstra, 1983; Rönkkö et al., 2016) ,一般

108.

7.13 もう一つの SEM 108 的にはパス係数や相関係数を過小推定する傾向があります。ということで,理論(研究仮説)的に PLS-SEM のほうが適切だと自信を持って言い切れるかつ場合には PLS-SEM を使えばよいの ですが,どちらを使えば良いかわからない(どちらでもいける)場合には,とりあえず CB-SEM を 試してみて,よほど特殊な事情がある場合に初めて PLS-SEM の利用を考えるくらいで良いのか もしれません。 INFO (私見込み)PLS-SEM を使用する理由に対する反論の例 • formative measurement を行いたいんだ! – →後述するように,CB-SEM(lavaan)でも formative measurement ができる   ようになりつつありますよ。 • サンプルサイズが小さいから仕方ないんだ! – CB-SEM で安定しないくらいの結果しか出せないサンプルサイズなのだと したら, PLS-SEM でもあまり良いとは言えないのではないでしょうか(e.g., Goodhue et al., 2012)。安易に PLS-SEM に逃げるよりもサンプルサイズを増 やすことを先に検討すべきだと思いますよ。 • データの正規性が怪しいのです。 – CB-SEM にも,正規性の逸脱に対して頑健なパラメータ推定法(MLR など)は 用意されていますよ。 • モデルが複雑なので,CB-SEM だと解が出ないんですよねぇ。 – 確かに PLS-SEM は何かしらの解を出してくれますが,そもそも CB-SEM で 解が得られないということ自体が「モデルが不適切である」ことのシグナルであ る可能性もあります。PLS-SEM で出てきた解が理論的に 「本当に欲しかったも の」 であるかはきちんと確認する必要がありそうです。 どうやら今のところは,PLS-SEM を使う積極的な理由は「予測精度の最大化が目的であ る」という点くらいなようです。ただ,その理由のために biased な推定を行うことが理論的 にどの程度許容されるかは分かりません…… 7.13.4 PLS-SEM を実行する方法 PLS-SEM を実行するためのソフトウェアとして,SmartPLS というものがよく用いられてい るようです。一応 R でも PLS-SEM を行うためのパッケージとして plssem や seminr (SEM in     R) パッケージというものが作成されているので,関心がある方はそちらのパッケージを見てみて ください。ちなみに Hair et al.(2021)は seminr パッケージの使い方を紹介している OA 本で  す。 

109.

7.13 もう一つの SEM 109 7.13.5 lavaan で formative な測定   2025 年 9 月にリリースされたバージョン 0.6-20 以降では,lavaan のやり方(つまり CB-SEM   の枠組み) で formative measurement ができるようになりました。 いよいよ PLS-SEM を積極的 に利用する必要性が分からなくなってきましたね。 理論的な詳細は Schamberger et al.(2025) を見ていただくとして (私もまだ十分にはチェック できていない&まだプレプリントなので),以下に示すいくつかの制約を満たす限り(バージョン 0.6-20 時点で)は,formative measurement を含んだ CB-SEM を実行することができます。 • formative な因子は,それぞれが少なくとも 1 つの「自身を構成している観測変数」以外と 矢印でつながっている • formative な因子と reflective な因子の両方に関係するような観測変数は存在しない • formative な因子を構成する観測変数と,reflective な因子を構成する観測変数の間に共分 散は全く無い ということで, ここでは以下のシンプルなモデル (図 7.32 ) を考えてみましょう。 図 7.32: formative な測定を含むモデル グラフィカルモデルにおいて formative な構成概念は,一般的には六角形で示されているよ うです。したがってこのモデルでは,gender,age,education の 3 つの変数の(重み付け)合計       点のような形で,demo という構成概念を形作っていると考えています。これは,社会経済的地位   (SCS) が複数の側面から評価されているのと構造的には同じことです*37 。 あとはこのモデルを lavaan の形式に落とし込んでいくだけです。lavaan で formative な測     定を行う場合には,<~ という記号を使用します。   *37 もちろん,SCS とは全く無関係なので,このあとに示す結果は 「どちらの性別のほうが優れている」 「若いほうがナ ントカ」といったことを含意するものではありません。

110.

7.13 もう一つの SEM 110 lavaan で formative な測定を定式化 1 2 3 4 5 6 7 8 9 10 model <- " # reflectiveな測定(因子分析) f_A =~ Q1_1 + Q1_2 + Q1_3 # formativeな測定 demo <~ gender + age + education # 回帰 f_A ~ demo # もちろん共分散(f_A ~~ demo)もアリ " あとは通常通り sem() 関数を実行するだけです。ただし,ここもいくつかの(lavaan パッケー     ジ側の) 制約があるため, 引数に注意してください。 •(勾配の)計算を数値計算で行う必要があるため optim.gradient = "numerical" を与え   る • std.lv = TRUE に対応していないので,これは入れない(つまり必ず各構成概念の最初の   項目の因子負荷・重みを 1 とした計算が行われる) – 標準化解を出したい場合は,summary() 関数で対応する   lavaan で formative な測定 1 2 result_formative <- sem(model, data = dat, optim.gradient = "numerical") summary(result_formative, standardized = TRUE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 lavaan 0.6-21 ended normally after 56 iterations Estimator Optimization method Number of model parameters Number of observations ML NLMINB 9 Used 2232 Model Test User Model: Test statistic Degrees of freedom P-value (Chi-square) 61.362 6 0.000 Parameter Estimates: Standard errors Standard Total 2432

111.

7.13 もう一つの SEM 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 111 Information Information saturated (h1) model Expected Structured Latent Variables: Estimate f_A =~ Q1_1 Q1_2 Q1_3 Std.Err z-value P(>|z|) Std.lv Std.all 0.452 0.774 0.608 1.000 1.415 1.242 0.104 0.078 13.666 15.860 0.000 0.000 0.628 0.889 0.780 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 1.000 0.017 0.035 0.005 0.040 3.805 0.877 0.000 0.381 1.933 0.033 0.068 0.908 0.356 0.076 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.357 0.033 10.864 0.000 0.294 0.294 Estimate Std.Err z-value P(>|z|) Std.lv Std.all 0.228 0.003 0.228 0.003 0.046 0.005 2.954 2.954 0.249 Std.lv 1.537 0.530 1.037 0.220 113.790 1.236 0.914 1.000 Std.all 0.796 0.402 0.630 1.000 1.000 1.000 0.914 1.000 Composites: demo <~ gender age education Regressions: f_A ~ demo Covariances: gender ~~ age education age ~~ education Variances: .Q1_1 .Q1_2 .Q1_3 gender age education .f_A demo Estimate 1.537 0.530 1.037 0.220 113.790 1.236 0.361 0.268 Std.Err 0.053 0.056 0.052 z-value 28.833 9.436 19.995 P(>|z|) 0.000 0.000 0.000 0.043 8.401 0.000 ということで得られた推定値 (標準化解) を図 7.33 に書き入れると, 以下のようになります。

112.

7.14 (おまけ)lavaan で探索的因子分析  112  図 7.33: formative な測定の結果 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) 1 2 3 4 This is lavaan 0.6-21 -- running exploratory factor analysis Estimator Rotation method ML OBLIMIN OBLIQUE

113.

7.14 (おまけ)lavaan で探索的因子分析  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 47 113  Oblimin gamma Rotation algorithm (rstarts) Standardized metric Row weights 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 ev8 0.523 ev9 0.469 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 * unique.var 0.846 0.558 0.408 0.723 0.603 0.690 0.615 0.689 0.527 0.634 * .* 0.567* 0.623* 0.551* 0.691* 0.587* 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 f2 f1 1.000 0.317* f2 1.000 回転方法を指定する引数は rotation です。psych::fa() では rotate だったのでご注意くだ       さい。ということで,かなり簡単に lavaan の出力形式で EFA の結果を出すことができました。  

114.

7.14 (おまけ)lavaan で探索的因子分析  114  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 30 31 32 33 34 35 This is lavaan 0.6-21 -- 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) f1 f2 Q1_1 0.408* -0.069* Q1_2 0.661* 0.011 Q1_3 0.779* -0.032* Q1_4 0.464* 0.142* Q1_5 0.624* 0.019 Q1_6 -0.036 0.567* Q1_7 -0.008 0.623* Q1_8 0.022 0.551* Q1_9 -0.012 0.691* Q1_10 0.049* 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 ev8 0.523 ev9 0.469

115.

7.14 (おまけ)lavaan で探索的因子分析  36 37 38 39 40 41 42 43 44 45 46 47 115  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 1.000 0.317* f1 f2 f2 1.000 ちなみに lavaan のデフォルトでは,最尤法によってパラメータの推定を行っています。したが   って, 上記の結果は psych::fa() で fm = "ml" を指定したときに同じになるはずです。     psych::fa() 関数と比べる 1 2 3 res_fa <- psych::fa(dat[, paste0("Q1_", 1:10)], nfactors = 2, fm = "ml") # 因子負荷だけ表示する res_fa$loadings 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18   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 Cumulative Var 0.186 0.368 分散説明率のところには細かい違いはあるのですが,因子負荷に関しては確かに同じ結果が得 られました。 あえて lavaan::efa() 関数を使う別の利点は,複数の因子数を一気に実行できることです。 引   数 nfactors に整数のベクトルを与えてあげると,すべての因子数で実行した結果をまとめて一  

116.

7.14 (おまけ)lavaan で探索的因子分析  116  つのオブジェクトで返してくれます。 色々な因子数を試す 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 30 31 32 33 34 35 36 37 This is lavaan 0.6-21 -- 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) Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 f1 .* 0.502* 0.523* 0.487* 0.480* 0.439* 0.507* 0.480* unique.var 0.934 0.748 0.727 0.763 0.769 0.808 0.742 0.769 communalities 0.066 0.252 0.273 0.237 0.231 0.192 0.258 0.231 ev8 0.523 ev9 0.469

117.

7.14 (おまけ)lavaan で探索的因子分析  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 76 77 78 79 80 81 82 83 Q1_9 Q1_10 117  0.552* 0.531* 0.696 0.718 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 Standardized loadings: (* = significant at 1% level) Q1_1 Q1_2 Q1_3 Q1_4 f1 0.408* 0.671* 0.796* 0.475* f2 .* * f3 .* unique.var 0.798 0.555 0.400 0.725 communalities 0.202 0.445 0.600 0.275

118.

7.14 (おまけ)lavaan で探索的因子分析  84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 118  0.636* 0.379* 0.472* .* 0.448* 0.492* 0.472* 0.793* 0.600* 0.601 0.637 0.496 0.709 0.386 0.614 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 10 11 12 13 14 15 16 17 npar fmin chisq df pvalue baseline.chisq baseline.df baseline.pvalue cfi tli nnfi rfi nfi pnfi ifi rni nfct=1 19.000 0.436 2122.495 35.000 0.000 5201.585 45.000 0.000 0.595 0.480 0.480 0.475 0.592 0.460 0.596 0.595 nfct=2 29.000 0.077 375.946 26.000 0.000 5201.585 45.000 0.000 0.932 0.883 0.883 0.875 0.928 0.536 0.932 0.932 nfct=3 37.000 0.045 217.286 18.000 0.000 5201.585 45.000 0.000 0.961 0.903 0.903 0.896 0.958 0.383 0.962 0.961

119.

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 119  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.888 0.178 0.120 今回の結果では,どうやら 2 因子モデルよりも 3 因子モデルのほうがモデル適合度は高いよう です。ただこのあたりは因子分析のときにお話したように,最終的には解釈可能性までを視野に 入れて決めるようにしましょう。 モデル式で指定する lavaan で EFA を実行するもう一つの方法は, 「モデル式で EFA であることを指定する」とい   うものです。 これまでにこの Chapter では, 変数名の前に 0* をつけることでその値を固定したり   (セクション 7.7.1 ) ,名前をつけることで等値制約を置く方法(セクション 7.10 )を紹介しまし た。これと同じ要領で,因子名の前に「この因子にどの項目がかかるかは EFA 的に決めてくださ い」ということを指定する記号を書き足すことができるのです。

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


120



モデル式で 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
18
19
20
21
22
23
24
25

lavaan 0.6-21 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

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

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

375.946
26
0.000

Parameter Estimates:
Standard errors
Information

Standard
Expected









121.

7.14 (おまけ)lavaan で探索的因子分析  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 68 69 70 71 121  Information saturated (h1) model 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.647 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 0.962 1.046 1.064 1.142 0.998 1.687 1.000 1.000 Std.Err 0.051 0.029 0.037 0.050 0.035 0.036 0.039 0.038 0.041 0.059 z-value 32.747 26.155 18.788 31.457 27.799 29.327 27.338 29.675 24.060 28.395 P(>|z|) 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 Std.lv 1.672 0.767 0.695 1.585 0.962 1.046 1.064 1.142 0.998 1.687 1.000 1.000 Std.all 0.846 0.558 0.408 0.723 0.603 0.690 0.615 0.689 0.527 0.634 1.000 1.000 Covariances: f1 ~~ f2 Variances: .Q1_1 .Q1_2 .Q1_3 .Q1_4 .Q1_5 .Q1_6 .Q1_7 .Q1_8 .Q1_9 .Q1_10 f1 f2

122.

7.14 (おまけ)lavaan で探索的因子分析  122  だいぶ lavaan の見慣れた形で出力されてくれました。結果はもちろん lavaan::efa() のとき     と同じ値なので説明は省略します。 実際のところ,EFA をするだけであれば efa() 関数を使っておけば良いと思います*38 。モデ   ル式での指定方法は, このあとの ESEM で必要になってくるのです…。 7.14.2 Exploratory SEM (ESEM) ESEM は,SEM と EFA を組み合わせたようなものです。この背景には,そもそも CFA を探索 的に使っているケースが割と存在する,ということがあるようです(Browne, 2001) 。例えば セク ション 7.7 で紹介したように,モデルの適合度を改善するためにある場所にパスを足したり引い たりすることは,まさに exploratory といって良いでしょう。また,自分で作成した尺度や,手元の データで因子構造が再現できる怪しいデータを用いて SEM を実行する場合には,通常まず EFA で因子構造・因子得点を出した上で,これを SEM の中に投入することが多くあります。ならばも ういっそ全部ひっくるめて一気にやってしまおう,というモチベーションもあるのかもしれませ ん。 ということで ESEM を試してみましょう。ここでは 図 7.34 のようなモデルを考えてみます。 左側の 6 項目と右側の 6 項目は,それぞれ異なる尺度を表しています(以後,左側を尺度 A,右側 を尺度 B と呼びます)。想定する因子数だけは決まっていて,それぞれが 2 因子を測定する尺度で す。さらに,尺度 A の一方の因子が尺度 B の一方の因子に影響を与える,という因子間の関係性 (回帰) も仮説として検証したいとします。 図 7.34: ESEM モデル このモデルを SEM で実行する場合には,尺度 A・B の中の各項目がそれぞれどちらの因子に 所属するかを明確に決める必要がありました。図 7.34 で言えば,青い点線のところにパスを許 *38 もっと言えばここまでの話は psych::fa() でも何一つ問題はないんですけどね。  

123.

7.14 (おまけ)lavaan で探索的因子分析  123  容しない(=因子負荷は厳密にゼロとする)のが SEM でした。一方 ESEM では,この青い点線の パス (cross-loadings) を許容します*39 。つまり,尺度 A に含まれる 2 因子(𝑓1 , 𝑓2 )は 6 項目から EFA によって推定し,尺度 B の 6 項目からも同様に 2 因子(𝑓3 , 𝑓4 )を推定する,ということです。 そして,小さい因子負荷もそのまま残して SEM の適合度指標の計算などを行います。言い換える と,ESEM は SEM の制約を緩めたモデルあるいは EFA に部分的な制約を加えたモデルとい う位置づけになっているわけです。 では実際に 図 7.34 の 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 を             かけているのです。 あとは推定するだけです。 ESEM の推定 1 2 3 # EFA部分があるのでrotationを指定可能 result_esem <- sem(model_esem, data = dat, rotation = "oblimin") summary(result_esem, standardized = TRUE) 1 2 3 4 lavaan 0.6-21 ended normally after 29 iterations Estimator Optimization method ML NLMINB *39 もちろん, そもそもどこのパスが黒か青かわからない(完全に探索的な) 状態でも ESEM は実行可能です。 というか ESEM の推定ではパスの色は区別していない,はず。

124.

7.14 (おまけ)lavaan で探索的因子分析  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 47 48 49 50 124  Number of model parameters Row rank of the constraints matrix Rotation method Oblimin gamma Rotation algorithm (rstarts) Standardized metric Row weights 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 Q1_6 Q1_7 Q1_8 f3 =~ f34 Q1_11 Q1_12 Q1_13 Q1_16 Q1_17 Q1_18 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.763 0.930 0.634 0.033 0.015 0.019 0.034 0.038 0.033 -2.028 0.179 0.660 22.180 24.354 19.016 0.043 0.858 0.509 0.000 0.000 0.000 -0.067 0.003 0.013 0.763 0.930 0.634 -0.048 0.002 0.010 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.823 -0.787 -1.694 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

125.

7.14 (おまけ)lavaan で探索的因子分析  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 87 88 89 90 f4 =~ f34 Q1_11 Q1_12 Q1_13 Q1_16 Q1_17 Q1_18 125  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 1.000 1.000 1.000 1.000 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 1.000 1.000 0.720 0.993 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 1.000 1.000 0.720 0.993 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 f1 f2 .f3 .f4 無事,小さい因子負荷を残して推定が完了しました。ESEM の利点は,このように小さい因子 負荷を許容することでモデル適合度が SEM よりも良くなる可能性がある,という点にあります。 試しに 図 7.34 から青い点線を取り除いた SEM モデルと適合度を比べてみましょう。

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




本来の 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
15
16
17
18
19
20
21
22
23
24

################### 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
####################### 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

126

127.

7.14 (おまけ)lavaan で探索的因子分析   今回の比較では,ESEM の結果の方が適合度が良いことがわかります。特に青い点線にあたる ところに 0 ではない因子負荷があるような場合には,SEM で無理に 0 に制約をかけてしまうと 適合度が悪化してしまう可能性がある, ということですね。 127

128.

参考文献 参考文献 Adachi, K. (2020). Matrix-based introduction to multivariate data analysis (2 番目 版). 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. E. Parzen, K. Tanabe, & G. Kitagawa (編), Selected papers of Hirotugu Akaike (pp. 199–213). Springer (Original work published 1969). https://doi.org/10.1007/978-14612-1694-0_15(Original work published 1969) Albers, S. (2010). PLS and success factor studies in marketing. V. Esposito Vinzi, W. W. Chin, J. Henseler, & H. Wang (編), 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/jiem .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 Bentler, P. M. (1995). EQS structural equations program manual. Multivariate Software, Inc. 128

129.

129 参考文献 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 Dijkstra, T. (1983). Some comments on maximum likelihood and partial least squares methods. Journal of Econometrics, 22(1), 67–90. https://doi.org/10.1016/0304-4076(83)9 0094-5 Goodhue, D. L., Lewis, W., & Thompson, R. (2012). Does PLS have advantages for small sample size or non-normal data? MIS Quarterly, 36(3), 981–1001. https://doi.org/10.230 7/41703490 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. (編). (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. The reviewer’s guide to quantitative methods in the social sciences (2nd 版, 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. S. Okazaki (編), 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

130.

参考文献 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 Loehlin, J. C., & Beaujean, A. A. (2016). Latent Variable Models (0 番目 版). Routledge. https://doi.org/10.4324/9781315643199 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 Rönkkö, M., McIntosh, C. N., Antonakis, J., & Edwards, J. R. (2016). Partial least squares path modeling: Time for some serious second thoughts. Journal of Operations Management, 47–48, 9–27. https://doi.org/10.1016/j.jom.2016.05.002 Schamberger, T., Schuberth, F., Henseler, J., & Rosseel, Y. (2025). Structural equation modeling with latent variables and composites (arXiv:2508.06112). arXiv. https://doi.org/ 10.48550/arXiv.2508.06112 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 編] 東京図書 130

131.

参考文献 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 Wold, H. (1975). Path models with latent variables: the NIPALS approach. H. M. Blalock, A. Aganbegian, F. M. Borodkin, R. Boudon, & V. Capecchi (Eds.), Quantitative Sociology (pp. 307–357). Elsevier. https://doi.org/10.1016/B978-0-12-103950-9.50017-4 Wright, S. (1934). The method of path coefficients. The Annals of Mathematical Statistics, 5(3), 161–215. https://doi.org/10.1214/aoms/1177732676 吉田 寿夫・村井 潤一郎・宇佐美 慧・荘島 宏二郎・小塩真司・鈴木 雅之・椎名乾平(2020) . SEM は心理学に何をもたらしたか? 教育心理学年報,59, 292–303. https://doi.org/10.5 926/arepj.59.292 131