文章目录

  • 前言
  • 数据标准化
  • KMO检验
  • 代码
  • 调库实现

  • Bartlett球形检验
  • 代码
  • 调库实现
  • 未通过检验
  • 不能通过KMO检验的数据处理建议
  • 代码


前言

近期在做PCA综合评分相关的项目,关于数据是否合适进行PCA综合评分,通常会要求对数据进行KMO和Bartlett球形检验,当KMO检验值大于0.6或0.7且Bartlett球形检验的显著性小于0.05表明该数据适合进行PCA综合评分或因子分析。

网上存在大量将PCA综合评分和因子分析搞混的文章,笔者对因子分析没有深入了解,在这里不多赘述。

本文主要是将关于数据如何进行检验,以及对于不通过检验的数据如何进行修改的问题。

需要注意的是,本篇所有的数据都是对数据进行标准化之后再进行检验。实验过程中,也存在如果同样的数据先进行标准化后再KMO检验无法计算出结果,但如果不标准化可能会获得一个较差的结果。个人认为主要原因是进行了Z-score标准化后的数据消除了量纲差异,将所有的属性都圈定到了较低的范围,所以会对计算产生影响。

至于PCA综合评分前进行检验是否先标准化,这里不进行讨论,请根据具体情况具体处理。

数据标准化

Z-score是一种常用的标准化方法,也称为标准差标准化或零均值单位方差标准化。通过减去均值并除以标准差,将原始数据转换为具有均值为0、标准差为1的标准正态分布。

z-score 标准化过程:

  1. 计算均值(mean): 对于每个属性(特征),计算其所有观测值的平均值。均值代表数据集在该属性上的中心位置。
  2. 计算标准差(standard deviation): 对于每个属性,计算其所有观测值的标准差。标准差度量了数据在该属性上的分散程度。
  3. 应用 z-score 公式: 对于每个数据点 KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差,应用 z-score 公式:
    KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_02
    其中:
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_03是原始数据点的值。
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_04
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_因子分析_05
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据分析_06是标准化后的值。

KMO检验

KMO检验是一种用于评估数据集中变量之间相关性的方法,它可以帮助确定是否适合进行因子分析或主成分分析。KMO值的计算公式如下:
KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_07
其中,

  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_08表示变量 KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据分析_09 和变量 KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_10之间的简单相关系数。
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_11是变量的总数。

KMO值的范围通常在0到1之间,越接近1表示变量之间的相关性越高,适合进行因子分析或主成分分析;越接近0表示变量之间的相关性较低,不适合进行因子分析或主成分分析。

KMO值的度量标准表如下:

KMO值

适用性

0.9以上

适用性好

0.8-0.9

适用性良好

0.7-0.8

适用性中等

0.6-0.7

适用性一般

0.5-0.6

适用性不好

0.5以下

不能进行分析

代码
调库实现

本文代码默认excel第一列为各样本名称,第一行记录样本属性名称,例如下表。

姓名

语文

数学

lumos

88

92

0.0

63

75

我是谁

98

64

import pandas as pd
from factor_analyzer.factor_analyzer import calculate_kmo


def kmo_test(file_path):
    # 读取Excel文件
    df = pd.read_excel(file_path)
    # 选择属性列(假设属性列从第二列开始)
    data = df.iloc[:, 1:]
    # 执行KMO检验
    kmo_results = calculate_kmo(data)

    # 返回KMO值和KMO均值
    return {'KMO': kmo_results[0], 'KMO_Mean': kmo_results[1]}


# 调用函数进行KMO检验,传入Excel文件路径
kmo_results = kmo_test('04标准化后.xlsx')

print("KMO值:", kmo_results['KMO'])
print("KMO均值:", kmo_results['KMO_Mean'])

Bartlett球形检验

Bartlett球形检验是一种用于检验因子分析模型中变量之间协方差矩阵是否为单位矩阵(即球形)的统计检验方法。在因子分析中,球形假设意味着所有变量之间的方差相等,即它们的方差-协方差矩阵为单位矩阵。

Bartlett球形检验的原假设KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据分析_12是变量之间的协方差矩阵为单位矩阵,即球形假设成立。备择假设KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_13是协方差矩阵不是单位矩阵,即变量之间存在相关性。

Bartlett球形检验的统计量由以下公式给出:
KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_14
其中:

  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_15
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_11
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_17
  • KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据分析_18是相关系数矩阵KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_17的行列式。

该统计量服从自由度为KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_20的卡方分布。在计算出卡方统计量后,可以使用卡方分布的累积分布函数来计算对应的 p 值。如果 p 值小于所选的显著性水平(通常是 0.05),则拒绝原假设,即认为变量之间的协方差矩阵不是单位矩阵,存在相关性。否则,不能拒绝原假设,即认为变量之间的协方差矩阵是单位矩阵,符合球形假设。

代码
调库实现
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
import pandas as pd


def bartlett_sphericity_test(dataset):
    # 执行Bartlett球形检验
    chi_square_value, p_value = calculate_bartlett_sphericity(dataset)
    return chi_square_value, p_value


# 读取标准化后的数据
standardized_data = pd.read_excel('04标准化后.xlsx').iloc[:, 1:]

# 进行Bartlett球形检验
chi_square_value, p_value = bartlett_sphericity_test(standardized_data)

# 打印结果
print("Bartlett球形检验的卡方值:", chi_square_value)
print("Bartlett球形检验的p值:", p_value)

未通过检验

对于KMO值小于0.6的数据或Bartlett球形检验显著性大于0.05的数据,普遍认为不适合进行主成分分析求综合评分。

在实际计算当中,笔者发现大多数的数据都能够满足Bartlett球形检验的要求,KMO值可能会计算不出来或者过低。

根据实验当中的经验,这里给出对不通过KMO检验的数据如何进行处理的建议。如果对当前数据无法进行删除或修改,请直接选择换一个方法,主成分分析综合评分不适合使用。

不能通过KMO检验的数据处理建议

首先请检查输入数据的样本数目是否小于属性数目,即行数小于列数。如果样本数目过少,属性数目过多,会导致无法计算出结果。

数据之间的相关性过高或过低。在前面的KMO检验当中有列出KMO值计算的公式,公式计算中使用的数据KMO 检验和 Bartlett 球形度检验可以用accessm吗_python_21表示变量 KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_22和变量 KMO 检验和 Bartlett 球形度检验可以用accessm吗_数据_23之间的简单相关系数,也就是说该数值是会受到变量之间的相关系数的影响。

在之前的计算KMO值的代码当中,我们除了返回KMO均值还返回了各属性的KMO值。

计算的KMO均值是我们需要的检验结果,而KMO值如下图所示,是一个列表。他计算了每一列属性对应的结果。因此如果存在哪个属性的KMO值较低,可以适当删除掉。下图当中的倒数第四个数据“0.36486746”,该KMO值明显小于其他情况,可以选择删除倒数第四列属性,再重新计算KMO均值。(一些偷懒的小技巧)

KMO 检验和 Bartlett 球形度检验可以用accessm吗_标准差_24

除此之外,还有可能出现KMO均值和KMO值均为空的结果,这就说明该数据无法计算出来KMO值,可能和“无法计算KMO值,相关矩阵不可逆”之类的原因有关系,在此不再深究,对于这样的数据,建议查看数据的相关性矩阵,如果某一列或某一行数据存在大量数据小于0.3或大于0.9,可以酌情删除该属性。

笔者在处理数据的时候,一开始有几列数据和其他数据的相关性存在大量负号,即该属性和其他属性的相关性不高,最后只能忍痛删除相关性低的属性0.0。
经验之谈,如果有数据和其他大量负相关,删掉之后就能计算出KMO值,当然也可能是因为属性列数目小于样本列数目,所以计算不出来。

代码

以下是增加了输出相关性矩阵的KMO检验代码。

import numpy as np
import pandas as pd
from factor_analyzer.factor_analyzer import calculate_kmo


def kmo_test(file_path):
    # 读取Excel文件
    df = pd.read_excel(file_path)
    # 选择属性列(假设属性列从第二列开始)
    data = df.iloc[:, 1:]
    # 执行KMO检验
    kmo_results = calculate_kmo(data)

    # 计算相关矩阵
    cor_matrix = np.corrcoef(data, rowvar=False)
    print(cor_matrix)

    # 返回KMO值和KMO均值
    return {'KMO': kmo_results[0], 'KMO_Mean': kmo_results[1]}


# 调用函数进行KMO检验,传入Excel文件路径
kmo_results = kmo_test('04标准化后.xlsx')

print("KMO值:", kmo_results['KMO'])
print("KMO均值:", kmo_results['KMO_Mean'])