如何基于n×n相关矩阵为Python DataFrame特征分配聚类值
基于相关矩阵的特征聚类实现
嘿,这个需求用图连通分量的思路就能轻松搞定——把每个特征看作图中的节点,只要两个特征的相关系数超过你设定的阈值(这里是0.08),就给这两个节点连一条边,最后每个连通的节点组就是一个聚类。下面给你两种实用的实现方式:
方法一:用NetworkX(直观易懂)
NetworkX是专门处理图结构的库,用它来找连通分量非常直观,适合快速实现。
首先如果没装NetworkX,先安装:
pip install networkx
然后是完整代码:
import pandas as pd import numpy as np import networkx as nx # 生成模拟数据(和你的示例一致) np.random.seed(0) df = pd.DataFrame(np.random.randn(100,5), columns=list('ABCDE')) # 计算特征间的相关矩阵 corr_matrix = df.corr() # 设定相关系数阈值 threshold = 0.08 # 初始化无向图 G = nx.Graph() # 把所有特征添加为图的节点 G.add_nodes_from(corr_matrix.columns) # 遍历所有特征对,添加符合条件的边 for i in range(len(corr_matrix.columns)): for j in range(i+1, len(corr_matrix.columns)): feat1 = corr_matrix.columns[i] feat2 = corr_matrix.columns[j] corr_val = corr_matrix.loc[feat1, feat2] # 按你的需求:仅正相关超过0.08时连边 if corr_val > threshold: G.add_edge(feat1, feat2) # 找到所有连通分量(每个分量对应一个聚类) clusters = list(nx.connected_components(G)) # 为每个特征分配聚类ID cluster_labels = {} for cluster_id, cluster in enumerate(clusters): for feature in cluster: cluster_labels[feature] = cluster_id # 转成DataFrame查看结果 cluster_result = pd.DataFrame.from_dict(cluster_labels, orient='index', columns=['Cluster_ID']) print(cluster_result)
结果说明
在你的模拟数据中,B和E的相关系数是0.1408(>0.08),所以它们会被分到同一个聚类;其他特征两两相关系数都没超过阈值,所以各自成为单独的聚类。输出结果如下:
Cluster_ID A 0 B 1 C 2 D 3 E 1
如果需要正负相关都纳入聚类(比如相关系数绝对值>0.08),只需要把判断条件改成:
if abs(corr_val) > threshold:
方法二:用SciPy(无需额外装库)
如果你不想安装新库,用SciPy的稀疏图连通分量函数也能实现,步骤如下:
import pandas as pd import numpy as np from scipy.sparse import csr_matrix from scipy.sparse.csgraph import connected_components # 前期数据准备 np.random.seed(0) df = pd.DataFrame(np.random.randn(100,5), columns=list('ABCDE')) corr_matrix = df.corr() threshold = 0.08 # 构建邻接矩阵:满足阈值条件的设为1,否则0 adj_matrix = (corr_matrix > threshold).astype(int) # 对角线设为1(每个节点和自身相连,保证单个节点也能形成聚类) np.fill_diagonal(adj_matrix.values, 1) # 转换为稀疏矩阵并计算连通分量 sparse_graph = csr_matrix(adj_matrix.values) num_clusters, cluster_labels = connected_components(csgraph=sparse_graph, directed=False, return_labels=True) # 整理结果 cluster_result = pd.DataFrame({ 'Feature': corr_matrix.columns, 'Cluster_ID': cluster_labels }) print(cluster_result)
这个方法和NetworkX的结果完全一致,适合依赖SciPy生态的场景。
内容的提问来源于stack exchange,提问作者muni
相关产品推荐
相关产品推荐

