LSA降维后层次聚类Dendrogram标注文本簇可读标签方法咨询
层次聚类树状图添加自定义文本标签实现方法
你之前绘制的树状图仅显示样本数量,核心原因是调用dendrogram函数时没有传入自定义labels参数,截断模式下会默认显示节点的样本计数。按照以下步骤修改即可实现和mtcars示例一致的自定义标签效果:
基础实现:直接使用样本名称作为标签
直接在调用绘图函数时传入labels参数即可,完整可运行代码如下:
import pandas as pd from matplotlib import pyplot as plt import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.cluster import AgglomerativeClustering from sklearn.decomposition import TruncatedSVD # 加载IMDB数据集 df = pd.read_csv( 'https://raw.githubusercontent.com/peetck/IMDB-Top1000-Movies/master/IMDB-Movie-Data.csv' ) # 文本向量化 + LSA降维 vectorizer = TfidfVectorizer(stop_words='english', max_features=1000) X = vectorizer.fit_transform(df.Description) TSVD = TruncatedSVD(n_components=10) X_reduced = TSVD.fit_transform(X) # 训练层次聚类模型 model = AgglomerativeClustering(distance_threshold=0, n_clusters=None) model = model.fit(X_reduced) def plot_dendrogram(model, **kwargs): # 构建聚类链接矩阵 counts = np.zeros(model.children_.shape[0]) n_samples = len(model.labels_) for i, merge in enumerate(model.children_): current_count = 0 for child_idx in merge: if child_idx < n_samples: current_count += 1 # 叶节点计数 else: current_count += counts[child_idx - n_samples] counts[i] = current_count linkage_matrix = np.column_stack([model.children_, model.distances_, counts]).astype(float) return dendrogram(linkage_matrix, **kwargs) # 核心修改:传入labels参数指定叶节点显示的文本,此处用电影名作为标签 out = plot_dendrogram(model, p=3, truncate_mode='level', leaf_rotation=90, leaf_font_size=7, labels=df.Title.values) # 调整布局避免标签被截断 plt.tight_layout() plt.show()
进阶实现:为聚合节点生成语义标签
如果开启了层级截断,合并的非叶节点可以自定义生成语义标签,比如提取簇内文本的高频关键词作为标签,补充代码如下:
# 提取每个节点对应的样本索引映射 n_samples = len(model.labels_) node_sample_map = {} # 初始化叶节点的样本索引 for i in range(n_samples): node_sample_map[i] = [i] # 递归生成聚合节点的样本索引 for i, merge in enumerate(model.children_): node_id = n_samples + i node_sample_map[node_id] = node_sample_map[merge[0]] + node_sample_map[merge[1]] # 生成簇关键词的工具函数 def get_cluster_keywords(sample_indices, top_k=2): cluster_tfidf = X[sample_indices] mean_tfidf = np.array(cluster_tfidf.mean(axis=0)).flatten() top_word_ids = mean_tfidf.argsort()[-top_k:][::-1] return "/".join(vectorizer.get_feature_names_out()[top_word_ids]) # 重新生成所有显示节点的标签 ax = plt.gca() final_labels = [] for leaf_id in out['leaves']: if leaf_id < n_samples: # 叶节点显示电影名 final_labels.append(df.Title.iloc[leaf_id]) else: # 聚合节点显示高频关键词 final_labels.append(get_cluster_keywords(node_sample_map[leaf_id])) # 替换x轴标签 ax.set_xticklabels(final_labels, rotation=90, fontsize=6) plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者osint_alex
相关产品推荐
相关产品推荐

