今天一个学姐拿了一篇论文,问我怎么去实现论文里的那个方法。简要的看了看,还是比较简单的。大体上就是将全国不同省份的经济数据做一个平行坐标轴可视化,流程就是先将数据标准化,然后PCA降维,然后再聚类,然后再用平行坐标可视化。我叭叭叭的讲了半天她还是不明白。让她用SPSS她不会,让她用Python,结果连代码和注释都搞不明白。。。各种问,问的头都大了两三个。。。实在是受不了就自己亲自写了一个。。。
PCA和聚类的基本原理《多元统计分析》这本书里讲的很明白,这里就不再赘述。话不多说,先上马,no code no bb。
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import k_means
def standard_pca_kmeans(file_path, sheetname, n_component, k, save=True):
# 读取目标文件中相应的表
df = pd.read_excel(file_path, sheet_name=sheetname)
# 获取需要进行处理的数据,保留第一列,并转化为numpy数组
data_useful = np.array(df.iloc[:, 1:])
# 对数据进行标准化处理以进行PCA(相关阵法)
scaler = StandardScaler().fit(data_useful)
data_scaled = scaler.transform(data_useful)
# 对数据进行PCA降维处理
pca = PCA(n_components=n_component).fit(data_scaled)
data_pca = np.dot(pca.components_, data_scaled.T).T
print('当选取%s个主成分时,累计方差贡献率为%s' % (n_component, sum(pca.explained_variance_ratio_)))
# 对降维后的数据进行聚类
kmeans = k_means(data_pca, k)
labels = kmeans[1]
# 整合成一个表
print(data_pca.shape)
result = pd.DataFrame(data_pca, columns=['第%s主成分' % (i+1) for i in range(n_component)])
result['类别'] = labels
result.insert(0, 'index', df.iloc[:, 0])
#print('前5行数据为:', result.head(5))
if save:
result.to_excel('结果.xlsx')
return result, data_pca, data_scaled
if __name__ == '__main__':
path = '园区数据.xlsx'
sheet_name = 'Sheet1'
result, data_pca, data_scaled = standard_pca_kmeans(path, sheet_name, 6, 6)
# 求各主成分与原始特征的相关系数,即因子负荷,可以用来解释各变量对各主成分的重要性
corrcoef = []
for i in range(len(data_pca.T)):
each_corr = []
for j in range(len(data_scaled.T)):
each_corr.append(np.corrcoef(data_pca.T[i], data_scaled.T[j])[0][1])
corrcoef.append(each_corr)
print(np.array(corrcoef))
一、数据和任务
数据:数据来源为某示范区某年某月不同园区的财务指标:共17个园区,16个不同指标,如下所示(保险起见随便打个码吧哈哈):
问题和任务:用平行坐标图对十七个园区进行可视化展示,并对园区进行聚类表示。问题时指标过多而难以用这种方法去可视化,于是想到用先对16个指标进行PCA降维,然后利用K-means进行聚类。
二、流程
1、首先导入要用的python库:
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import k_means
2、读取数据
# 读取目标文件中相应的表
df = pd.read_excel(file_path, sheet_name=sheetname)
# 获取需要进行处理的数据,保留第一列,并转化为numpy数组
data_useful = np.array(df.iloc[:, 1:])
这里我们把数据部分摘出来,便于进行运算,最后再把第一列的园区类别插入,便于我们去观察处理
file_path为excel表格存放的位置;sheetname为对应的表名字
3、数据标准化
# 对数据进行标准化处理便于进行PCA
scaler = StandardScaler().fit(data_useful)
data_scaled = scaler.transform(data_useful)
因为不同特征之间的差别较大,所以进行标准化,用相关阵法
4、PCA降维
# 对数据进行PCA降维处理
pca = PCA(n_components=n_component).fit(data_scaled)
data_pca = np.dot(pca.components_, data_scaled.T).T
print('当选取%s个主成分时,累计方差贡献率为%s' % (n_component, sum(pca.explained_variance_ratio_)))
这里解释下PCA方法的参数。其中n_components为要保留的主成分个数,可以是int 1,2,3......等,也可以设置为‘mle’,系统会自动选择主成分个数。个人建议在维度和数据量不大的情况下手动设置,通过观察累积误差贡献率的大小来设置主成分个数。
注意用PCA训练数据后并不是直接返回结果,而是在模型的属性里获得我们想要的结果。这里pca.components_为分解出来的正交特征向量,并不是最总的结果,最终的变换Y=UX,U即为pca.components_。PCA的结果即为data_pca。方差贡献率pca.explained_variance_ratio_是一个1-D矩阵,里边是每个主成分的方差贡献率,我们要的是设置的主成分的贡献率之和,即累计方差贡献率,该值大于0.85即可。
如果我们想找出各原始变量对各主成分的重要性,则可以计算出每个主成分与每个变量(即特征)的相关系数,即因子负荷量,因子负荷量的绝对值越大,说明该变量对该主成分越重要。且不可将变换系数的大小来衡量变量对主成分的重要性:
# 求各主成分与原始特征的相关系数,即因子负荷量,可以用来解释各变量对各主成分的重要性
corrcoef = []
for i in range(len(data_pca.T)):
each_corr = []
for j in range(len(data_scaled.T)):
each_corr.append(np.corrcoef(data_pca.T[i], data_scaled.T[j])[0][1])
corrcoef.append(each_corr)
print(np.array(corrcoef))
5、 聚类
# 对降维后的数据进行聚类
kmeans = k_means(data_pca, k)
labels = kmeans[1]
这里k是我们要聚的类别数。注意,k_means方法返回的是一个元组,第二项数据才是我们要的聚类后的类别标签。
6、将想要的结果整合成一个excel表
result = pd.DataFrame(data_pca, columns=['第%s主成分' % (i+1) for i in range(n_component)])
result['类别'] = labels # 插入类别标签
result.insert(0, 'index', df.iloc[:, 0]) # 插入园区名称
#print('前5行数据为:', result.head(5))
if save:
result.to_excel('结果.xlsx') # 存入当前目录
7、实战
if __name__ == '__main__':
path = '园区数据.xlsx'
sheet_name = 'Sheet1'
result, data_pca, data_scaled = standard_pca_kmeans(path, sheet_name, 6, 6)
这里我们设主成分个数为6,聚类类别数为6,最终输出大概就是这个样子:
8、可视化
算了,懒得搞,交给她自己做吧,我已经仁至义尽了。。。