简介:这份文档资料聚焦因子分析中常见的非正定矩阵问题,面向使用SPSS进行多元统计分析的社科、经济、心理及医学领域研究者与数据分析学习者。资源以真实案例为主线,完整呈现某运营商无线增值业务31个省份、35个变量的因子分析过程,梳理非正定矩阵的成因、判断依据与解决思路。压缩包内仅含1个docx文档,约25KB,内容涵盖案例介绍、问题描述、疑问梳理、解决办法与总结五个部分,重点讲解一一淘汰法识别问题变量、特征值过小与负值的判定逻辑,以及增加样本、剔除强相关变量、数据标准化、改用主成分分析等应对策略。已有419人学习下载,适合正在处理KMO值无法输出、相关系数矩阵报错等问题的读者参考,帮助理解非正定矩阵对因子分析结果的实际影响,并掌握可落地的排查与修正方法。
1. 因子分析撞上非正定矩阵:一份案例文档能帮你省下多少试错时间
做问卷分析或者量表开发的人,迟早会撞上一个报错:相关矩阵不是正定的。软件弹出一行红字,因子分析直接跑不下去。你盯着那个矩阵看,每个相关系数都正常,KMO 也过了,偏偏就是非正定。这时候大多数人会去搜“非正定矩阵怎么解决”,搜出来的答案五花八门——有的说删题项,有的说加样本,有的说换提取方法,但没有一个能告诉你“为什么会出现”以及“出现之后按什么顺序排查”。这份《因子分析出现非正定矩阵案例》文档,就是专门拆这个问题的。它不是教科书里那种一笔带过的“注意事项”,而是把非正定矩阵的成因、诊断路径和修复方案串成了一条完整的排查链。适合正在做因子分析、结构方程模型前处理,或者带学生做毕业论文数据分析的从业者。如果你已经被这个报错卡过半天以上,这份文档值得花时间过一遍。
2. 非正定矩阵的成因拆解:从相关矩阵到特征值的排查逻辑
2.1 为什么相关矩阵会“非正定”
正定矩阵的定义是:对于任意非零向量,二次型都大于零。放到因子分析的语境里,一个正定的相关矩阵意味着所有特征值都大于零。一旦出现零特征值或者负特征值,矩阵就变成半正定或非正定,因子分析的数学基础就塌了。
常见成因有四个。第一,变量之间存在完全线性相关,比如两个题项问的是同一件事,相关系数接近 1.00。第二,样本量太小,变量数接近甚至超过样本量,矩阵秩不足。第三,缺失值处理不当,成对删除和整列删除混用导致协方差矩阵不一致。第四,量表题项方向不一致,反向计分题没有反转,导致相关系数矩阵内部矛盾。
这份文档的价值在于,它没有停留在“列出原因”这个层面,而是给出了每个成因对应的诊断指标。比如,它会让你先看相关矩阵中是否有绝对值超过 0.95 的相关系数对,再看样本量与变量数的比值是否低于 5:1,最后检查特征值分解结果中负特征值的个数和量级。这套顺序很关键,因为不同成因对应的修复成本完全不同。
2.2 诊断路径:三个命令定位问题源头
拿到一份数据,不要急着删题项。先跑诊断,把问题定位清楚再动手。以下是我常用的 R 代码片段,文档里也给出了对应的 SPSS 和 Python 操作路径。
# 读取数据,假设数据框名为 df,包含所有量表题项 # 第一步:检查相关矩阵是否存在高相关对 cor_matrix <- cor(df, use = "pairwise.complete.obs") high_cor <- which(abs(cor_matrix) > 0.9 & abs(cor_matrix) < 1, arr.ind = TRUE) print(high_cor) # 输出高相关变量对的行列索引 # 第二步:计算特征值,检查是否有负值 eigen_values <- eigen(cor_matrix)$values print(eigen_values) # 负特征值出现即确认非正定 # 第三步:检查样本量与变量数比值 n_samples <- nrow(df) n_vars <- ncol(df) cat("样本量/变量数 =", n_samples / n_vars) # 低于5需要警惕这段代码的逻辑是:先用cor()计算相关矩阵,use = "pairwise.complete.obs"表示成对删除缺失值,这是因子分析前的常见做法。然后找出相关系数绝对值大于 0.9 的变量对,这些是嫌疑对象。接着用eigen()做特征值分解,只要出现负值,非正定就坐实了。最后算一下样本量和变量数的比值,低于 5:1 的话,矩阵秩不足的风险很高。
参数说明:use参数可以换成"complete.obs"做整列删除,但要注意两种方式得到的相关矩阵可能不同,混用会导致后续分析不一致。high_cor的阈值 0.9 不是固定的,样本量小的时候可以放宽到 0.85,样本量大的时候可以收紧到 0.95。
文档里还提到了一个容易被忽略的点:如果相关矩阵是通过成对删除得到的,即使每个相关系数都基于足够的样本,整体矩阵也可能非正定。这是因为成对删除不保证矩阵的一致性。解决办法是改用整列删除,或者用 EM 算法做缺失值插补。这个细节在很多教程里被跳过了,但它是实际分析中最常见的坑之一。
2.3 修复方案的选择逻辑
定位到成因之后,修复方案不是随便挑一个就行。文档给出了一个决策树:如果是高相关对导致的,优先考虑删除其中一个题项或者合并题项;如果是样本量不足,优先增加样本或者减少变量数;如果是缺失值处理不当,改用整列删除或插补;如果是反向计分问题,先反转再重跑。
这里有一个取舍:删除题项会损失内容效度,减少变量数会影响因子结构的完整性。所以文档建议,在删除任何题项之前,先检查该题项在内容上的必要性。如果两个题项确实测量的是同一维度,删掉一个不会有大问题;但如果它们测量的是不同维度但经验上高度相关,删除就需要谨慎。
另一个方案是改用主成分分析(PCA)代替因子分析。PCA 不要求相关矩阵正定,因为它不做逆运算。但 PCA 和因子分析的理论基础不同,PCA 是降维技术,因子分析是潜变量模型。如果研究目的是探索因子结构,换 PCA 只是绕过了问题,没有解决它。文档对这个取舍讲得很清楚,适合在方法部分需要交代清楚的研究场景。
3. 从案例文档到实操:SPSS、R、Python 三套复现路径
3.1 SPSS 操作路径与参数设置
SPSS 是很多从业者的主力工具,但它在非正定矩阵的提示上比较隐晦。你点“分析 → 降维 → 因子分析”,把题项拖进去,点“描述”勾选“相关系数矩阵”和“KMO 和 Bartlett 球形检验”,然后点“提取”选“主成分”或“主轴因子”。如果矩阵非正定,SPSS 可能不会直接报错,而是给出一个警告说“矩阵不是正定的”,然后继续输出结果。这时候结果里的特征值会出现负数,累积方差解释率可能超过 100%。
文档里给出的 SPSS 排查步骤是:第一步,在“描述”里勾选“反映像”矩阵,看对角线上的值(即 KMO 个体测度),低于 0.5 的题项是嫌疑对象。第二步,在“提取”里把“提取固定因子数”设为变量数,强制输出全部特征值,看是否有负值。第三步,如果确认非正定,回到“选项”里把“缺失值”从“成对排除”改为“整列排除”,重跑一次看是否解决。
参数设置上,SPSS 的“成对排除”是默认选项,但它正是导致非正定的常见原因。改成“整列排除”会损失样本,但能保证矩阵一致性。如果样本量本来就紧张,可以考虑用“替换均值”做缺失值插补,但会低估方差。文档建议,如果缺失率低于 5%,整列排除的损失可以接受;如果高于 10%,优先考虑插补。
3.2 R 语言完整复现流程
R 的优势在于诊断和修复可以脚本化,适合需要反复调试的场景。以下是一个完整的复现流程,从读取数据到输出修复后的因子分析结果。
library(psych) library(mice) # 读取数据 df <- read.csv("scale_data.csv", header = TRUE) # 检查缺失值模式 md_pattern <- md.pattern(df) print(md_pattern) # 方案一:整列删除 df_complete <- na.omit(df) cor_complete <- cor(df_complete) eigen_complete <- eigen(cor_complete)$values cat("整列删除后最小特征值:", min(eigen_complete), "\n") # 方案二:EM 插补 df_imputed <- mice(df, method = "pmm", m = 1, seed = 123) df_completed <- complete(df_imputed) cor_imputed <- cor(df_completed) eigen_imputed <- eigen(cor_imputed)$values cat("EM 插补后最小特征值:", min(eigen_imputed), "\n") # 如果特征值仍为负,检查高相关对 high_pairs <- which(abs(cor_completed) > 0.9 & abs(cor_completed) < 1, arr.ind = TRUE) if (nrow(high_pairs) > 0) { cat("高相关变量对:\n") print(high_pairs) } # 最终因子分析 fa_result <- fa(df_completed, nfactors = 5, rotate = "varimax", fm = "ml") print(fa_result$loadings)这段代码的逻辑是:先用mice包检查缺失值模式,然后分别用整列删除和 EM 插补两种方式处理缺失值,对比特征值的最小值。如果整列删除后特征值仍为负,说明问题不只是缺失值,需要进一步检查高相关对。最后用fa()做最大似然因子分析,fm = "ml"指定提取方法,rotate = "varimax"做正交旋转。
参数说明:m = 1表示生成一个插补数据集,实际研究中通常建议m = 5或更多,但诊断阶段用 1 就够。method = "pmm"是预测均值匹配,适合连续变量。如果题项是 Likert 量表,也可以考虑"polr"做有序回归插补。nfactors = 5需要根据理论或平行分析确定,不能随便设。
文档里还提到了一个进阶技巧:用fa.parallel()做平行分析,辅助确定因子数。平行分析不依赖相关矩阵的逆运算,所以在非正定情况下仍然可用。这个技巧在样本量小的时候特别有用。
3.3 Python 路径与 statsmodels 实现
Python 在因子分析上的生态不如 R 成熟,但factor_analyzer包提供了完整的实现。以下是一个诊断和修复的示例。
import pandas as pd import numpy as np from factor_analyzer import FactorAnalyzer from factor_analyzer.factor_analyzer import calculate_kmo, calculate_bartlett_sphericity # 读取数据 df = pd.read_csv("scale_data.csv") # KMO 和 Bartlett 检验 kmo_all, kmo_model = calculate_kmo(df) chi_square, p_value = calculate_bartlett_sphericity(df) print(f"KMO: {kmo_model:.3f}, Bartlett p: {p_value:.4f}") # 检查相关矩阵特征值 cor_matrix = df.corr() eigen_values = np.linalg.eigvals(cor_matrix) print(f"最小特征值: {min(eigen_values):.6f}") # 如果非正定,检查高相关对 high_cor = np.where(np.abs(cor_matrix) > 0.9) high_pairs = [(cor_matrix.index[i], cor_matrix.columns[j]) for i, j in zip(*high_cor) if i < j] print("高相关对:", high_pairs) # 修复后做因子分析 fa = FactorAnalyzer(n_factors=5, rotation="varimax", method="ml") fa.fit(df) print(fa.loadings_)这段代码的逻辑和 R 版本类似,先做 KMO 和 Bartlett 检验,再检查特征值。np.linalg.eigvals()返回的特征值可能是复数,取实部即可。factor_analyzer的FactorAnalyzer默认用最小残差法,改成method="ml"用最大似然。如果矩阵非正定,fit()可能会抛出LinAlgError,这时候需要先修复矩阵再重跑。
参数说明:n_factors=5需要根据理论或平行分析确定。rotation="varimax"是正交旋转,如果因子之间允许相关,可以改成"promax"。method可选"minres"、"ml"、"principal",其中"principal"是主成分法,不要求正定。
文档里特别提醒:Python 的factor_analyzer在缺失值处理上不如 R 灵活,默认要求完整数据。如果数据有缺失,需要先用sklearn的SimpleImputer或pandas的fillna()处理。这个限制在实际使用中需要注意。
4. 避坑与排查:非正定矩阵处理中的五个血泪教训
4.1 现象:删了题项还是非正定
原因:删题项只解决了高相关对的问题,但如果样本量本身不足,删题项反而让变量数更接近样本量,矩阵秩更不够。解决:先检查样本量与变量数的比值,低于 5:1 的话,优先增加样本或减少变量数,而不是删单个题项。
4.2 现象:SPSS 不报错但结果异常
原因:SPSS 对非正定矩阵的提示很隐晦,有时候只在输出里给一行警告,容易被忽略。结果里的特征值出现负数,累积方差解释率超过 100%。解决:每次跑因子分析之前,手动在“描述”里勾选“反映像”矩阵,检查对角线上的 KMO 个体测度,低于 0.5 的题项标记出来。跑完之后检查特征值表格,有负值就说明矩阵有问题。
4.3 现象:成对删除和整列删除结果差异巨大
原因:成对删除利用所有可用数据,但不同相关系数基于不同的样本子集,导致矩阵不一致。整列删除保证一致性,但损失样本。解决:如果缺失率低于 5%,直接用整列删除;如果高于 10%,用 EM 插补或多次插补。不要混用两种方式,更不要在用成对删除得到非正定矩阵后,换成整列删除却不检查样本量是否还够。
4.4 现象:反向计分题导致矩阵内部矛盾
原因:反向计分题没有反转,和其他题项的相关系数为负,但理论上它们应该正相关。矩阵内部出现矛盾,特征值分解时出现负值。解决:在跑因子分析之前,先用psych::reverse.code()或手动反转反向题项。检查方法很简单:如果某个题项和大多数题项的相关系数都是负的,它很可能是反向题。
4.5 现象:换 PCA 后问题消失但结论不可靠
原因:PCA 不做矩阵求逆,所以非正定不影响它。但 PCA 和因子分析的模型假设不同,PCA 的载荷不能解释为潜变量的效应。解决:如果研究目的是探索因子结构,不要用 PCA 绕过问题。如果只是做降维,PCA 可以接受,但要在方法部分说明用的是 PCA 而非因子分析。文档里对这个区别讲得很清楚,适合在论文方法部分引用。
5. 进阶技巧:用平行分析和 Bootstrap 验证因子结构稳定性
非正定矩阵修复之后,因子结构是否稳定,需要额外验证。这里分享两个我常用的技巧。
第一个是平行分析。平行分析通过模拟随机数据,比较真实数据的特征值和随机数据的特征值,确定保留因子数。它不依赖相关矩阵的逆运算,所以在非正定情况下仍然可用。R 里的fa.parallel()和 Python 里的factor_analyzer都支持。
# 平行分析确定因子数 fa.parallel(df_completed, fa = "fa", n.iter = 100, show.legend = TRUE)n.iter = 100表示模拟 100 次,次数越多结果越稳定。fa = "fa"指定做因子分析的平行分析,如果改成"pc"就是主成分的平行分析。输出图里,真实数据的特征值曲线和随机数据的特征值曲线的交点,就是建议保留的因子数。
第二个是 Bootstrap 验证。对样本做有放回抽样,重复跑因子分析,看因子载荷的置信区间。如果某个题项的载荷在不同样本中波动很大,说明它不稳定,考虑删除。
library(boot) boot_fa <- function(data, indices) { d <- data[indices, ] fa_result <- fa(d, nfactors = 5, rotate = "varimax", fm = "ml") return(fa_result$loadings[, 1]) } boot_result <- boot(df_completed, boot_fa, R = 1000) boot.ci(boot_result, type = "perc")R = 1000表示重抽样 1000 次,type = "perc"用百分位法计算置信区间。如果某个题项的载荷置信区间跨过零,说明它在不同样本中不稳定。
这两个技巧在论文里可以作为稳健性检验的一部分。我一般会在修复非正定矩阵之后,先跑平行分析确认因子数,再用 Bootstrap 检查载荷稳定性。如果两者都通过,因子结构基本可以放心。从那以后我每次处理非正定矩阵,都会把诊断、修复、验证三步走完,不再急着删题项或者换方法。希望帮到你。
本文还有配套的精品资源,点击获取