如何为matplotlib散点图创建与绘图颜色匹配的准确图例
问题根源
你的代码存在两个明显错误,直接导致图例匹配失效:
- 无意义的循环:你在
for i in range(clusters)里重复调用了4次scatter,每次传入的都是完整的坐标数组和标签数组,相当于同一批点被叠绘了4次。matplotlib收集图例项时会把坐标轴参考线、所有叠绘的散点层都纳入统计,根本不会按聚类标签做归类。 - 图例传参错误:你直接把全量
my_labels列表传给legend(),matplotlib只会拿列表前N个值,按顺序匹配当前轴上已有的前N个绘图对象,完全不会建立「颜色-聚类标签」的对应关系。
修正方法
推荐两种写法,都能实现颜色和图例一一对应的效果:
方法1:按聚类分组绘制(逻辑直观,易自定义)
去掉无效的叠绘循环,按聚类标签筛选点后单独绘制每个聚类的散点,绘制时直接给每个聚类指定图例标签即可:
import matplotlib.pyplot as plt import numpy as np clusters = 4 two_d_matrix = np.array([[0.00617068, -0.53451777], [-0.01837677, -0.47131886], ...]) my_labels = np.array([0, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]) cmap = plt.get_cmap('viridis', clusters) fig, (plot1, plot2) = plt.subplots(1, 2, sharex=False, sharey=False, figsize=(20, 10)) # 绘制第一个子图 plot1.axhline(0, color='#afafaf') plot1.axvline(0, color='#afafaf') for cluster_id in range(clusters): cluster_mask = my_labels == cluster_id plot1.scatter( two_d_matrix[cluster_mask, 0], two_d_matrix[cluster_mask, 1], s=30, color=cmap(cluster_id), label=f'Cluster {cluster_id}' ) plot1.legend(title="聚类") plot1.set_title("My First Plot") # 绘制第二个子图 plot2.axhline(0, color='#afafaf') plot2.axvline(0, color='#afafaf') for cluster_id in range(clusters): cluster_mask = my_labels == cluster_id plot2.scatter( two_d_matrix[cluster_mask, 0], two_d_matrix[cluster_mask, 1], s=30, color=cmap(cluster_id), label=f'Cluster {cluster_id}' ) plot2.legend(title="聚类") plot2.set_title("My Second Plot") plt.show()
方法2:单次绘制+自动生成图例(代码更简洁)
不需要循环筛选点,只调用一次scatter传入全部点和标签,利用matplotlib自带的legend_elements()方法自动生成和颜色映射匹配的图例项:
# 以第一个子图为例,替换原来的循环scatter部分 plot1.axhline(0, color='#afafaf') plot1.axvline(0, color='#afafaf') scatter1 = plot1.scatter( two_d_matrix[:, 0], two_d_matrix[:, 1], s=30, c=my_labels, cmap='viridis' ) plot1.legend(handles=scatter1.legend_elements()[0], labels=list(range(clusters)), title="聚类")
这种写法不会重复叠绘点,也不会把坐标轴参考线纳入图例,生成的图例条目和散点颜色完全对应。
内容的提问来源于stack exchange,提问作者AdeDoyle
相关产品推荐
相关产品推荐

