如何在Python Matplotlib中为散点分组设置形状与颜色并解决重叠问题?
问题描述
尝试将表格数据导入Python,绘制两个变量的散点图,用两个变量分组:3选项变量分配颜色,5选项变量分配形状。单独设置形状或颜色均可正常显示,但组合设置时每个数据点显示两个形状(正确形状+标准圆点),移除重复点代码则颜色显示异常。示例代码如下:
import matplotlib.pyplot as plt import numpy as np r = np.array([600, 2000, 980, 1770, 920, 1100, 220]) t = np.array([2.7, 12.67, 10.54, 1.3, 16.1, 0.92, 13.56]) spectra_type = np.array(['A', 'A', 'B', 'A', 'C', 'B', 'A']) spectra_num = np.array([{'A': 0, 'B': 1, 'C': 2}[i] for i in spectra_type]) i = np.array(['Shape1','Shape2','Shape3','Shape4','Shape5','Shape2','Shape4']) shape1 = np.where(i=='Shape1')[0] shape2 = np.where(i=='Shape2')[0] shape3 = np.where(i=='Shape3')[0] shape4 = np.where(i=='Shape4')[0] shape5 = np.where(i=='Shape5')[0] plt.figure('fig 1') plt.xlabel('x') plt.ylabel('y') plt.scatter(t[shape1], r[shape1], c=spectra_num[shape1], marker='D', label='Shape1') plt.scatter(t[shape2], r[shape2], c=spectra_num[shape2], marker='^', label='Shape2') plt.scatter(t[shape3], r[shape3], c=spectra_num[shape3], marker='o', label='Shape3') plt.scatter(t[shape4], r[shape4], c=spectra_num[shape4], marker='s', label='Shape4') plt.scatter(t[shape5], r[shape5], c=spectra_num[shape5], marker='*', label='Shape5') first_legend = plt.legend(loc='upper left') plt.gca().add_artist(first_legend) scatter = plt.scatter(t, r, c=spectra_num) plt.legend(handles=scatter.legend_elements()[0], labels=['A', 'B', 'C'], title='Colour')
运行后图表中形状被标准圆点覆盖,需要解决该问题。
解决建议
- 核心问题:最后一行
plt.scatter(t, r, c=spectra_num)会在所有已绘制的形状点之上再绘制一遍全量的圆点,导致覆盖。必须移除这行代码,同时手动构建颜色图例,避免依赖重复绘制的scatter对象。 - 手动创建颜色图例:通过空的散点标记或颜色块来生成颜色图例的手柄,无需重复绘制数据点。
修改后的代码示例:
import matplotlib.pyplot as plt import numpy as np from matplotlib.patches import Patch r = np.array([600, 2000, 980, 1770, 920, 1100, 220]) t = np.array([2.7, 12.67, 10.54, 1.3, 16.1, 0.92, 13.56]) spectra_type = np.array(['A', 'A', 'B', 'A', 'C', 'B', 'A']) spectra_num = np.array([{'A': 0, 'B': 1, 'C': 2}[i] for i in spectra_type]) i = np.array(['Shape1','Shape2','Shape3','Shape4','Shape5','Shape2','Shape4']) shape_groups = { 'Shape1': np.where(i=='Shape1')[0], 'Shape2': np.where(i=='Shape2')[0], 'Shape3': np.where(i=='Shape3')[0], 'Shape4': np.where(i=='Shape4')[0], 'Shape5': np.where(i=='Shape5')[0] } markers = {'Shape1':'D', 'Shape2':'^', 'Shape3':'o', 'Shape4':'s', 'Shape5':'*'} plt.figure('fig 1') plt.xlabel('x') plt.ylabel('y') # 按形状分组绘制散点 for shape, idx in shape_groups.items(): plt.scatter(t[idx], r[idx], c=spectra_num[idx], marker=markers[shape], label=shape) # 形状图例 first_legend = plt.legend(loc='upper left') plt.gca().add_artist(first_legend) # 手动创建颜色图例手柄 colour_handles = [ Patch(color=plt.cm.tab10(0), label='A'), Patch(color=plt.cm.tab10(1), label='B'), Patch(color=plt.cm.tab10(2), label='C') ] plt.legend(handles=colour_handles, title='Colour', loc='upper right') plt.show()
- 优化说明:
- 用字典整合形状分组和标记,代码更简洁易维护。
- 移除重复的全量散点绘制,避免圆点覆盖。
- 使用
Patch创建颜色块作为图例项,完美匹配数据点的颜色分组。
内容的提问来源于stack exchange,提问作者gem9911
相关产品推荐
相关产品推荐

