semパッケージが激しく進化!version3になり超実用的に

semパッケージはオワコン。通はOpenMxかlavaanを使う。そう思っていた時期が私にもありました。

ところが,semパッケージがこの半年の間に2回もメジャーバージョンアップを行っており,凄まじい進化を遂げていました。こういう定番パッケージは大幅な更新はないものと思い込んでいましたが,恥ずかしい見当違いでした。

ざっとヘルプに目を通したところ,以下のようなすばらしい更新点があります。

  • 待ち望まれていた多母集団同時解析に対応!
  • CFA用のモデル記法の追加
  • LISREL風のモデル記法の追加
  • モデルの結合や更新の機能
  • 誤差項を自動的に追加するオプション
  • その他多数

以下,Osaka.R #4の発表資料に対応させる形で解説していきます。

LISREL風記法について

まず,LISREL風記法については,回帰式をそのまま書くような記法が使えるようになりました。

ものすごく簡潔でわかりやすいですね!説明の必要もあまりないくらいですが,左辺に従属変数,右辺にパラメータ名*独立変数の形で回帰式を書いていきます。分散(誤差項)はV(変数)=パラメータ名で表し,共分散はC(変数1, 変数2)=パラメータ名で表します。ちなみにこのときのVとCは大文字でも小文字でもかまいません。

モデルの更新

次に,モデルを更新してみましょう。前述の重回帰分析にパスを足して,パス解析にしてみます。

addはパスを追加する,という命令です。他にもパスを削除するdelete,変数やパラメータ名を置換するreplace,パスを固定するfix,パスを自由にするfreeがあります。ここで注意点として,追加したパラメータ名が元のモデルのパラメータ名と(意図せず)重複しないようにしなければなりません。パラメータ名を重複させた場合,それらのパスには等値制約を課すという意味になります。

モデルの結合

ちなみにupdateでは従来の記法しか使うことができませんが,ただパスを足すだけならば,モデルを結合するcombineModelsを使うことで簡潔な表現が可能になります。

さて,お気づきのとおり,上記のモデルでは教育年数と職業威信の誤差項を書いていません。endog.variancesにTRUEを指定すると,内生変数に誤差項が付いていない場合に自動的に誤差項を付けてくれるようになりました(初期値がTRUEなので実際には上記のようにわざわざ指定する必要はありません)。Mplusでは標準でそうなっているのですが,この機能があるのとないのとではモデル構築の効率が大きく変わってきます。

combineModelsは名前の通りの関数ですが,これもupdateと同じくパラメータ名の重複に注意が必要です。また,この関数はなぜか返り値がmatrixです。ただ,matrixのままでもsem関数に使うことはできます。とはいえ,結合したモデルにupdateを使う予定がある場合などは,ちょっと不便です。そこで,removeRedundantPaths関数を使うと,標準的なsemmodクラスに変換することができます。removeRedundantPaths関数の本来の機能は,名前の通り重複しているパスの削除なのですが,こういう使い方もできるようです。

ここまでLISREL風記法を中心に見てきましたが,注意しなければならないのは,この記法では,構造方程式(回帰の部分)は書けますが,測定方程式(因子分析の部分)は書けません。厳密には書けなくはないのですが,左辺は必ず従属変数かつ1変数でなければならないので,因子分析を表現するためには測定変数の数だけ式を書かなければなりません。

しかし,がっかりする必要はありません。強化されたsemパッケージには,CFA(検証的因子分析)用の記法も用意されています。

CFA用の記法

ものすごく簡潔ですね。reference.indicatorsはTRUEにすると,モデルの識別のために1つめの測定変数のパラメータを1に固定します。初期値はFALSEで,この場合は因子の分散を1に固定します。これだけだと因子間相関や誤差相関はどうすればいいんだ,という話になりますが,covsオプションに"変数1, 変数2"という形で共分散を指定することができます。c("変数1", "変数2")ではないことに注意してください。1つの文字列で1つの共分散を指定するので,複数の共分散を指定するときにc関数などを使ってベクトルで指定する,ということになります。ちなみにcovsオプションはcfa関数限定ではなく,specifyModelやspecifyEquationsでも使うことができます。

応用

ここまでのモデルを結合し,少し大きめのモデルを作ってみます。

多母集団の同時解析

最後に多母集団同時解析の解説です。

まずグループのカテゴリ数だけモデルを用意します。基本は同じで,同じパラメータ名の場合に等値制約が課せられます。いままでは1つのモデル内だけの話でしたが,多母集団同時解析なので,複数のモデル間でも等値制約が課せられることになります。

次に,multigroupModel関数で複数のモデルをひとまとめにします。groupsオプションは単にグループに名前を付けるだけで,サンプルを分割する変数のカテゴリ名に合わせる必要はありません。もっとも合わせない理由はほとんどないと思いますが,カテゴリの順番に気をつけてください。ちゃんと確かめていませんが,分析の出力はlevels関数の出力の順序で行われていると思います。

あとはsem関数を走らせるだけですが,データの渡し方に注意が必要です。共分散行列で渡す場合には,matrixのlistで渡します。生データを使う場合には,dataオプションにdata.framを指定し,formulaオプションに分析で使用する変数を指定します。groupオプションにはグループ分けに使う変数を文字列で指定します。

まとめ

さて,ここまで解説しつつ試した感じでは,いままで私が使ってきたソフトウェアやパッケージの中で,もっともモデルが書きやすかったです。その理由として考えられるのは,「構造方程式,測定方程式,共分散がそれぞれ別の書き方で書けること」なのではないかと思います。複雑なモデルを統一的な数式で表せるのがSEMのすばらしさなのですが,実際に分析するときにはそれが徒となって,モデルが複雑になるにつれどの式が何を表していたのかさっぱりわからなくなってきます。semパッケージの新機能では,因子は因子,回帰式は回帰式ではっきり書き分けることができ,また研究上大した意味を持たないことが多い(そのわりに分量が多い)共分散や誤差項も書き分けで隠蔽したり隔離したりできます。モデルの結合や更新も,SEMの鉄則である,小さなモデルを組み合わせて徐々に大きくしていく,という過程をそのままスクリプトで表現できるので,後から見ても非常に読みやすいように自然となります。

semパッケージは初学者の勉強用にはいいけど研究に使うには物足りないな,とずっと思っていたのですが,これならば万人にお勧めできます。足りないのは,混合効果とカテゴリカルな分析ぐらいでしょうか。そのあたりを必要とするのはかなりマニアックな人たちになってくるので,まあおとなしくMplusを使っておくべきでしょう。

これらの新機能の情報はウェブ等にはほとんどないのですが,ヘルプにはexampleが豊富に付いているので,あまり困ることはありませんでした。help(sem)とhelp(specifyModel)を一通り読んでexampleを走らせれば,だいたい理解できると思います。あとはhelp(package="sem")をざっと見て興味をひかれる関数のヘルプを読めば完璧です。進化したsemパッケージをぜひお試しください!