如何在Matplotlib图例中将两个散点标记合并为单个暂停符号条目?
解决Matplotlib中暂停符号图例重复的问题
你的问题出在两次调用scatter时都设置了相同的label,导致图例生成了重复条目。以下是几种可行的解决方案:
方案一:使用自定义标记路径(最简洁)
直接定义一个包含两条竖线的自定义标记,这样只需一次scatter调用即可完成绘制,自然避免图例重复:
import numpy as np import matplotlib.pyplot as plt from matplotlib.path import Path # 定义双竖线标记的路径 def double_vertical_marker(): shift = 0.1 # 两条线的间距比例 # 标记坐标以中心点(0,0)为基准 vertices = [ (-shift, -0.5), (-shift, 0.5), # 左侧竖线 (shift, -0.5), (shift, 0.5) # 右侧竖线 ] # 路径指令:MOVETO表示移动到起点,LINETO表示画线到下一点 codes = [ Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO ] return Path(vertices, codes) # 绘制汽车行驶路径 x = np.linspace(0, 20, 100) y = np.sin(x) fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(x, y) # 标记停车位置 x_stop = np.array([1, 5, 10]) y_stop = np.sin(x_stop) ax.scatter(x_stop, y_stop, marker=double_vertical_marker(), color='r', s=225, label='停车点') ax.legend(loc='best') plt.show()
方案二:手动创建复合图例条目
保持原有的两次scatter绘制方式,但去掉其中一个的label,然后手动创建包含两条竖线的图例条目:
import numpy as np import matplotlib.pyplot as plt import matplotlib.lines as mlines # 绘制汽车行驶路径 x = np.linspace(0, 20, 100) y = np.sin(x) fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(x, y) # 标记停车位置 x_stop = np.array([1, 5, 10]) y_stop = np.sin(x_stop) shift = 0.1 # 仅在第二次scatter时设置label(或第一次,任选其一) ax.scatter(x_stop - shift, y_stop, marker='|', color='r', s=225) ax.scatter(x_stop + shift, y_stop, marker='|', color='r', s=225) # 创建两个单竖线的标记对象 line_left = mlines.Line2D([], [], color='r', marker='|', markersize=15) line_right = mlines.Line2D([], [], color='r', marker='|', markersize=15) # 将两个标记组合成一个图例条目 ax.legend([(line_left, line_right)], ['停车点'], loc='best') plt.show()
方案三:自定义图例处理器
通过编写自定义的图例处理器,修改单个scatter条目的显示样式,使其展示两条竖线:
import numpy as np import matplotlib.pyplot as plt from matplotlib.legend_handler import HandlerBase import matplotlib.lines as mlines # 自定义图例处理器:绘制两条竖线 class DoubleLineHandler(HandlerBase): def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans): # 在图例框内绘制左右两条竖线 line1 = mlines.Line2D([width/4, width/4], [ydescent, height - ydescent], color='r', linewidth=2) line2 = mlines.Line2D([3*width/4, 3*width/4], [ydescent, height - ydescent], color='r', linewidth=2) return [line1, line2] # 绘制汽车行驶路径 x = np.linspace(0, 20, 100) y = np.sin(x) fig, ax = plt.subplots(figsize=(12, 8)) ax.plot(x, y) # 标记停车位置 x_stop = np.array([1, 5, 10]) y_stop = np.sin(x_stop) shift = 0.1 ax.scatter(x_stop - shift, y_stop, marker='|', color='r', s=225) # 仅给其中一个scatter设置label scatter_right = ax.scatter(x_stop + shift, y_stop, marker='|', color='r', s=225, label='停车点') # 使用自定义处理器生成图例 ax.legend(handles=[scatter_right], handler_map={type(scatter_right): DoubleLineHandler()}, loc='best') plt.show()
内容的提问来源于stack exchange,提问作者kklaw
相关产品推荐
相关产品推荐

