Pythonで共分散構造分析がしたい(semopy)

変数間の複数の関係性を推定するためにSEMを使いたいことがあります。

データの読み込み

RでSEMをするlavaanのデータを読み込みます。

import pandas as pd
import pyper

r = pyper.R(use_pandas=True)
r('library(lavaan) ')

df = r.get('PoliticalDemocracy')

esu-ko.hatenablog.com

モデルの定義

各変数の関係性を定義します。

  • : 構造方程式(回帰,右から左)
  • =∼ : 測定方程式(潜在変数の効果,左から右)
  • ∼∼ : 共変関係(双方向)
from semopy import Model

mod="""ind60 =~ x1 + x2 + x3
            dem60 =~ y1 + y2 + y3 + y4
            dem65 =~ y5 + y6 + y7 + y8
            dem60 ~ ind60
            dem65 ~ ind60 + dem60
            y1 ~~ y5
            y2 ~~ y4 + y6
            y3 ~~ y7
            y4 ~~ y8
            y6 ~~ y8
"""
mdl=Model(mod)

モデルの推定

モデルにデータを読み込み、推定します。

#そのままだと読み込めないので修正
df.columns = [c.strip() for c in df.columns]
mdl.load_dataset(df.astype('float32'))

from semopy import Optimizer
opt = Optimizer(mdl)
objective_function_value = opt.optimize()

from semopy.inspector import inspect
res_df = inspect(opt)
res_df.head()

結果はデータフレームで帰ってきます。

     lval  op   rval     Value        SE    Z-score       P-value
5   dem60  =~     y2  1.256759  0.182449   6.888264  5.647705e-12
6   dem60  =~     y3  1.057701  0.151394   6.986417  2.819966e-12
7   dem60  =~     y4  1.264819  0.145013   8.722092  0.000000e+00
8   dem65  =~     y6  1.185704  0.168814   7.023728  2.160272e-12
9   dem65  =~     y7  1.279501  0.159904   8.001694  1.332268e-15

パス図はpygraphvizなどで自分で書く感じになりそうです。