什么是因子分析
因子分析是通过研究变量间的相关系数矩阵,把这些变量间错综复杂的关系归结成少数几个综合因子,并据此对变量进行分类的一种统计分析方法。由于归结出的因子个数少于原始变量的个数,但是它们又包含原始变量的信息,所以,这一分析过程也称为降维。
因子分析与主成分分析的关系
主成分分析直接对因子进行降维,无法很好进行后续的解释,因而对其进行扩展:不仅注意变量之间是否相关,而且考虑相关关系的强弱,使得提取出来的公因子不仅起到降维的作用,而且能够被很好的解释,该方法就是因子分析。因子分析是在主成分分析法的基础上进行因子旋转,使得因子载荷重新分布,从而使得新因子能够很好的解释之前的因子。
为什么使用因子分析
因子分析主要包含以下三个原因:
- 探索结构:在变量之间存在高度相关性的时候我们希望用较少的因子来概括其信息;
- 简化数据:把原始变量转化为因子得分后,使用因子得分进行其他分析,比如聚类分析、回归分析等;
- 综合评价:通过每个因子得分计算出综合得分,对分析对象进行综合评价。
因子分析就是将原始变量转变为新的因子,这些因子之间的相关性较低,而因子内部的变量相关程度较高。
因子分析的步骤
因子分析的一般步骤:
- 判断数据是否适合因子分析;
- 构造因子变量;
- 利用因子旋转方法使得因子更具有实际意义;
- 计算每个因子得分;
- 确定因子个数
因子分析的变量要求是连续变量,分类变量不适合直接进行因子分析;建议个案个数是变量个数的5倍以上,这只是一个参考依据,并不是绝对的标准;KMO检验统计量在0.5以下,不适合因子分析,在0.7以上时,数据较适合因子分析,在0.8以上时,说明数据极其适合因子分析。
提取因子个数的标准
- 初始特征值大于1的因子个数;
- 累积方差贡献率达到一定水平(60%)的因子个数;
- 碎石图中处于较陡峭曲线上所对应的因子个数;
- 依据对研究事物的理解而指定因子个数;
python实例
- 导入相关包和数据
# 导入相关包和数据
import numpy as np
import pandas as pd
from factor_analyzer import FactorAnalyzer
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
import matplotlib.pyplot as plt
import matplotlib
import warnings
warnings.filterwarnings("ignore")
%matplotlib inline
plt.rcParams['font.sans-serif']=['Arial Unicode MS']
# 解决中文乱码
matplotlib.rcParams['font.sans-serif'] = ['Heiti TC']
matplotlib.rcParams['font.serif'] = ['Heiti TC']
matplotlib.rcParams['axes.unicode_minus'] = False
- 初始化数据集
# 初始化数据集
df = pd.DataFrame(cancer.data,columns=cancer.feature_names)
df['label'] = cancer.target
df.head()
3. 充分性检验,对因子进行KMO或者Bartlett球形检验
# 充分性检验,对因子进行KMO或者Bartlett球形检验
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity, calculate_kmo
# chi_square_value为卡方值,p_value为Bartlett球形检验值,
chi_square_value, p_value = calculate_bartlett_sphericity(df)
chi_square_value, p_value
统计量p-value的值为0,表明变量的相关矩阵不是单位矩阵,即各个变量之间是存在一定的相关性,我们就可以进行因子分析
kmo_all, kmo_model = calculate_kmo(df)
kmo_model
检查变量间的相关性和偏相关性,取值在0-1之间;KOM统计量越接近1,变量间的相关性越强,偏相关性越弱,因子分析的效果越好。 kmo值大于0.6则表明变量之间有一定的相关性,可以进行因子分析。
如果没有安装factor_analyzer模块,使用以下代码进行安装:
pip install factor_analyzer
- 选择因子个数
# 选择合适的因子个数,绘制碎石图从而选出保留的因子个数
fa = FactorAnalyzer(25, rotation=None)
fa.fit(df)
# ev为特征值,v为特征向量
ev, v = fa.get_eigenvalues()
# 绘制碎石图
plt.plot(range(1,df.shape[1]+1), ev)
plt.scatter(range(1, df.shape[1]+1), ev)
plt.title('Scree plot碎石图')
plt.xlabel('factors')
plt.ylabel('eigenvalue')
plt.grid()
plt.show()
我们提取碎石图中处于较陡峭曲线上所对应的因子个数,以上碎石图的曲线对应是5的位置。
# 查看公共因子方差
fa.get_communalities()
# 查看方差贡献率
pd.DataFrame(fa.get_factor_variance())
其中第0行表示每个因子的总方差贡献率; 第1行表示方差贡献率; 第2行表示累计方差贡献率。 一般我们选取累计方差贡献率达到60%以上的因子个数。
5. 根据因子个数得到因子成分矩阵,方便进行因子解释
#找到5个隐藏的因子,进行因子分析
# 指定矩阵旋转方式为:方差最大化varimax
fa = FactorAnalyzer(5, rotation='varimax')
fa.fit(df)
# 31*5 变量个数*因子个数
fa.loadings_.shape
# 对因子分析后的成分矩阵进行可视化分析,方便进行因子解释
import seaborn as sns
df_fa = pd.DataFrame(np.abs(fa.loadings_), index=df.columns)
plt.subplots(figsize=(16,14))
ax = sns.heatmap(df_fa, annot=True, cmap='BuPu')
ax.tick_params(axis='x',labelsize=15)
ax.set_title("Factor Analysis",fontsize=12)
ax.set_ylabel("Sepal Width")
使用以上热力图进行因子解释。
6. 将原始数据转化为对应的因子分析数据
#将原始数据转化为因子分析后的数据,即将31个因子转化为5个因子
pd.DataFrame(fa.transform(df))