含有序变量的CFA问题:观测变量频率异常排查求助
有序变量CFA分析空类别报错问题解决
问题场景
- 环境:RStudio(R 4.2.0),使用lavaan包做验证性因子分析(CFA)
- 模型配置:10个因子、103个有序观测变量,样本量n=284
- 模型代码:
library(lavaan) modelshort <- ' comm=~Comm3+Comm5+Comm6+Comm8+Comm10+Comm19+Comm20+Comm21+Comm23 rc=~RC2+RC6+RC7+RC9+RC10+RC11+RC12+RC13+RC14+RC15+RC16+RC17+RC19+RC20+RC21+RC24 as=~AS6+AS8+AS9+AS14+AS15+AS16+AS17+AS18+AS19+AS20+AS21+AS22+AS23+AS24+AS26 vd=~VD1+VD2+VD3+VD4+VD5+VD9+VD10+VD12+VD16+VD21+VD23 ss=~SS5+SS7+SS8+SS9+SS10+SS13+SS15+SS16+SS17+SS19+SS20 loisirs=~Loisirs6+Loisirs7+Loisirs8+Loisirs12+Loisirs13+Loisirs14+Loisirs15+Loisirs16+Loisirs17+Loisirs18 auto=~Auto15+Auto16+Auto17+Auto18+Auto20+Auto22+Auto23+Auto24 ri=~RI2+RI3+RI4+RI7+RI14+RI17+RI18+RI21+RI22+RI23+RI24+RI25 asoc=~ASoc6+ASoc7+ASoc8+ASoc9+ASoc11+ASoc15+ASoc16+ASoc17+ASoc18+ASoc19+ASoc20 travail=~Travail1+Travail3+Travail4+Travail5+Travail6+Travail8+Travail9+Travail10+Travail11+Travail20+Travail22+Travail23'
出现的问题
- 不指定有序变量时,模型运行正常:
fitshortord <- cfa(modelshort, data=abas6)
- 添加
ordered=TRUE参数后触发报错:
fitshortord <- cfa(modelshort, data=abas6, ordered=TRUE)
Error in lav_samplestats_step1(Y = Data, wt = wt, ov.names = ov.names, :
lavaan ERROR: some categories of variable `ASoc6' are empty in group 1; frequencies are [21 70 113 0]
- 用plyr包查看频数时结果异常:
library(plyr) count(ASoc6) # Error in count(ASoc6) : object 'ASoc6' not found count('ASoc6') # x freq # 1 ASoc6 1
- 原始SPSS文件中ASoc6的频数为[1,30,101,152],变量已确认导入RStudio;移除ASoc6后,ASoc11出现相同报错。
问题原因与解决步骤
1. 频数查看错误的纠正
plyr::count()需要传入数据框+变量名的组合,单独传变量名或字符串无法获取真实数据的频数。正确操作:
# 方式1:用plyr查看 count(abas6, ASoc6) # 方式2:用base R更直接可靠 table(abas6$ASoc6, useNA = "ifany")
之前的错误操作导致你无法看到R中变量的真实分布,这是定位问题的关键。
2. lavaan报错的核心原因
lavaan提示空类别,说明R的abas6数据中,该变量确实存在无观测值的类别,和SPSS数据不符,大概率是数据导入时的编码/类型问题:
- SPSS中的有序分类变量带标签,导入R后标签与数值编码不匹配,导致类别被错误转换;
- 导入时缺失值处理不当,某类别的观测值被误判为缺失;
- 变量在R中是数值型而非因子型,lavaan识别有序变量时按数值区间划分,出现空区间。
3. 具体解决步骤
步骤1:确认变量的真实状态
先查看变量的类型和准确频数:
# 查看变量类型 class(abas6$ASoc6) # 查看包含缺失值的频数分布 table(abas6$ASoc6, useNA = "ifany")
步骤2:修复变量的类别编码
如果变量是数值型,转换为有序因子,确保和SPSS的类别一致:
# 假设SPSS中类别为1-4,按顺序定义 abas6$ASoc6 <- factor(abas6$ASoc6, levels = c(1,2,3,4), ordered = TRUE) # 再次验证频数 table(abas6$ASoc6)
若存在缺失值,根据研究需求处理:
- 缺失值少的话,可删除对应行:
abas6 <- na.omit(abas6) - 缺失值多的话,考虑多重插补,不建议直接删除变量。
步骤3:精准指定有序变量
如果不是所有变量都是有序的,不要用ordered=TRUE,而是指定具体的有序变量列表,避免lavaan误判:
# 替换为你的103个有序变量名称 ordered_vars <- c("Comm3", "Comm5", "Comm6", ..., "ASoc6", ...) fitshortord <- cfa(modelshort, data=abas6, ordered=ordered_vars)
步骤4:处理空类别(若确实存在)
如果确认某类别无观测值(比如导入时编码错误导致),可合并相邻类别:
# 示例:将第4类合并到第3类,根据实际情况调整 library(forcats) abas6$ASoc6 <- fct_collapse(abas6$ASoc6, "3" = c("3", "4")) # 验证合并后的频数 table(abas6$ASoc6)
内容的提问来源于stack exchange,提问作者claudio
相关产品推荐
相关产品推荐

