如何使用最近邻等方法对相似numpy数组或pandas DataFrame聚类
实现步骤
前置说明
默认你所有500个DataFrame的date列时间点完全对齐,如果存在时间缺失/顺序不一致的情况,需要先统一按date列重索引、填充缺失值后再往下操作。
1. 特征提取
将每个DataFrame转为可计算相似度的一维特征向量,示例代码如下:
import pandas as pd import numpy as np from sklearn.metrics.pairwise import cosine_similarity, euclidean_distances from sklearn.cluster import KMeans # 你需要先把所有500个DataFrame存入一个列表 dfs_list feature_list = [] for df in dfs_list: # 先按date排序保证所有样本顺序一致 sorted_df = df.sort_values("date", ignore_index=True) # 提取val1、val2两列的数值,拉平为一维特征向量 feat = sorted_df[["val1", "val2"]].values.flatten() feature_list.append(feat) # 转为形状为(500, 特征长度)的特征矩阵 feature_mat = np.array(feature_list)
2. 计算500×500相似度矩阵
根据你的业务需求可选不同的相似度计算方式:
- 若更看重序列变化趋势的相似性,选余弦相似度,取值范围[-1,1],越接近1相似度越高:
cos_sim_mat = cosine_similarity(feature_mat)
- 若更看重数值绝对值的接近程度,可以把欧氏距离转为相似度,取值范围(0,1],越接近1相似度越高:
euc_dist_mat = euclidean_distances(feature_mat) euc_sim_mat = 1 / (1 + euc_dist_mat)
如果你的DataFrame时间点不对齐,就用动态时间规整(DTW)计算两两距离再转相似度:
from dtw import dtw n = len(dfs_list) dtw_dist_mat = np.zeros((n, n)) for i in range(n): for j in range(i, n): dist, _, _, _ = dtw( dfs_list[i][["val1", "val2"]].values, dfs_list[j][["val1", "val2"]].values ) dtw_dist_mat[i][j] = dtw_dist_mat[j][i] = dist # 转相似度 dtw_sim_mat = 1/(1 + dtw_dist_mat)
3. 聚类分组
拿到特征矩阵/相似度矩阵后即可做聚类,以最常用的K-Means为例:
# 按需设置聚类数量k,比如设为8 k = 8 kmeans = KMeans(n_clusters=k, random_state=42) # 得到每个DataFrame对应的分组标签 cluster_labels = kmeans.fit_predict(feature_mat) # 可以把标签和对应df绑定输出 result = [{"df_index": idx, "cluster": label} for idx, label in enumerate(cluster_labels)]
如果不想提前指定聚类数量,你可以换成DBSCAN、层次聚类等无监督聚类算法,直接传入特征矩阵即可运行。
内容的提问来源于stack exchange,提问作者Rahul Gupta
相关产品推荐
相关产品推荐

