You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python的semopy.multigroup()中实现标量测量不变性?

如何在semopy中实现多组CFA的标量测量不变性

问题背景

我有一个包含21个项目的合并数据集,通过wave变量划分为15个双周调查波次。合并数据的CFA模型拟合效果良好,但需要验证不同波次间的纵向测量不变性。目前已通过semopy的multigroup()默认设置实现度量不变性(仅因子载荷跨组相等),但不知道如何实现标量测量不变性(因子载荷与观测变量截距均跨组相等),尝试修改模型语法和查询参数均未成功。

解决方案

semopy实现标量不变性有两种简洁方式:


方式1:直接指定invariance参数

multigroup()函数内置了invariance参数,可直接指定不变性级别:

  • 'metrics':默认,仅约束因子载荷跨组相等(度量不变性)
  • 'scalar':约束因子载荷+观测变量截距跨组相等(标量不变性)

修改代码调用部分即可:

model_multi = multigroup(model_dict, df_pool, group='wave', invariance='scalar')
print(model_multi.stats)

方式2:在模型语法中显式约束截距

如果需要更精细的控制(比如仅约束部分变量的截距),可以在模型语法中给每个观测变量的截距指定全局参数名,强制跨组相等:

# 原二阶CFA模型部分(因子载荷默认跨组相等)
F1_effic =~ F1A5_2 + F1A10_2r + F3A18_1
F21_resent =~ F1A10_1 + F1A16_1r + F1A17_1 + F5A5_1
F22_affec =~ F1A9_1 + F1A15_1
F4_cosmo  =~ F3A7_1 + F3A8_1 + F3A34_1
F5_consp  =~ F1A17_2 + F5eA3_1 + F5eA4_1 + F5cA3_1 + F1A16_2 + F5A11_1r
F6_envir =~ F2A11 + F2A12 + F3A10_1r
F2_rebel =~ F21_resent + F22_affec

# 约束每个观测变量的截距跨组相等
F1A5_2 ~ int_F1A5_2*1
F1A10_2r ~ int_F1A10_2r*1
F3A18_1 ~ int_F3A18_1*1
F1A10_1 ~ int_F1A10_1*1
F1A16_1r ~ int_F1A16_1r*1
F1A17_1 ~ int_F1A17_1*1
F5A5_1 ~ int_F5A5_1*1
F1A9_1 ~ int_F1A9_1*1
F1A15_1 ~ int_F1A15_1*1
F3A7_1 ~ int_F3A7_1*1
F3A8_1 ~ int_F3A8_1*1
F3A34_1 ~ int_F3A34_1*1
F1A17_2 ~ int_F1A17_2*1
F5eA3_1 ~ int_F5eA3_1*1
F5eA4_1 ~ int_F5eA4_1*1
F5cA3_1 ~ int_F5cA3_1*1
F1A16_2 ~ int_F1A16_2*1
F5A11_1r ~ int_F5A11_1r*1
F2A11 ~ int_F2A11*1
F2A12 ~ int_F2A12*1
F3A10_1r ~ int_F3A10_1r*1

每个int_xxx是全局参数名,确保对应观测变量的截距在所有组中取值一致。


验证不变性

运行模型后,通过model_multi.stats查看拟合指标(如CFI、RMSEA、TLI等),与度量不变性模型对比:

  • 若CFI下降≤0.01,RMSEA上升≤0.015,通常认为标量不变性成立。

完整测试代码

import pandas as pd
import numpy as np
import semopy
from semopy.multigroup import multigroup

# Generate dataset
np.random.seed(42)
num_wave = 15
n_per_wave = 100
items = [
    "F1A5_2", "F1A10_2r", "F3A18_1", "F1A10_1", "F1A16_1r", "F1A17_1",  
    "F5A5_1", "F1A9_1", "F1A15_1", "F3A7_1", "F3A8_1", "F3A34_1",  
    "F1A17_2", "F5eA3_1", "F5eA4_1", "F5cA3_1", "F1A16_2", "F5A11_1r",  
    "F2A11", "F2A12", "F3A10_1r"
]

df_pool = pd.DataFrame({
    "wave": np.repeat(np.arange(1, num_wave + 1), n_per_wave)
})
for item in items:
    df_pool[item] = np.random.normal(3, 1, len(df_pool))

# CFA Model with Second-Order-Factors 
model_dict = """
    F1_effic =~ F1A5_2 + F1A10_2r + F3A18_1
    F21_resent =~ F1A10_1 + F1A16_1r + F1A17_1 + F5A5_1
    F22_affec =~ F1A9_1 + F1A15_1
    F4_cosmo  =~ F3A7_1 + F3A8_1 + F3A34_1
    F5_consp  =~ F1A17_2 + F5eA3_1 + F5eA4_1 + F5cA3_1 + F1A16_2 + F5A11_1r
    F6_envir =~ F2A11 + F2A12 + F3A10_1r
       
    F2_rebel =~ F21_resent + F22_affec
"""

# 实现标量不变性
model_multi = multigroup(model_dict, df_pool, group='wave', invariance='scalar')
print(model_multi.stats)

内容的提问来源于stack exchange,提问作者ghost_trevor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:39:52