使用Plotly绘制聚类轮廓图时遇单值无法迭代报错问题
解决聚类轮廓图绘制的TypeError问题
问题原因
你用sklearn.metrics.silhouette_score得到的是全局平均轮廓系数,是单个numpy.float64值,而绘制轮廓图需要每个样本的轮廓系数,直接迭代这个单值就会触发TypeError: 'numpy.float64' object is not iterable。
修复方案
改用sklearn.metrics.silhouette_samples函数获取每个样本的轮廓系数,再结合matplotlib绘制标准轮廓图,同时确保concat_omics_df的索引和subtype_labels完全匹配。
完整代码示例
import matplotlib.pyplot as plt import numpy as np from sklearn.metrics import silhouette_samples, silhouette_score # 对齐数据与标签的索引,确保样本和标签一一对应 aligned_df = concat_omics_df.loc[subtype_labels.index] X = aligned_df.values labels = subtype_labels.values # 计算全局平均轮廓系数,以及每个样本的轮廓系数 sil_avg = silhouette_score(X, labels) sil_samples = silhouette_samples(X, labels) # 绘制轮廓图 n_clusters = len(np.unique(labels)) y_lower = 10 # 底部留白 plt.figure(figsize=(8, 6)) for i in range(n_clusters): # 提取当前簇的样本轮廓系数并排序 cluster_sil = sil_samples[labels == i] cluster_sil.sort() cluster_size = cluster_sil.shape[0] y_upper = y_lower + cluster_size # 填充簇的轮廓区域 plt.fill_betweenx(np.arange(y_lower, y_upper), 0, cluster_sil, alpha=0.7) # 标注簇编号 plt.text(-0.05, y_lower + 0.5 * cluster_size, str(i+1)) y_lower = y_upper + 10 # 簇之间留空 # 绘制全局平均轮廓系数的虚线 plt.axvline(x=sil_avg, color="red", linestyle="--") plt.xlabel("轮廓系数值") plt.ylabel("簇编号") plt.title(f"聚类轮廓图 (平均轮廓系数: {sil_avg:.2f})") plt.tick_params(axis='y', which='both', left=False, labelleft=False) # 隐藏y轴刻度 plt.show()
关键说明
- 索引对齐:通过
loc方法确保concat_omics_df的行顺序和subtype_labels完全一致,避免样本与标签不匹配的问题。 silhouette_samples:返回与样本数量一致的数组,每个元素对应单个样本的轮廓系数,这是绘图的核心数据。- 绘图逻辑:按簇排序系数后填充区域,同时标注簇编号和平均系数线,符合标准轮廓图的样式。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

