如何创建内部带加号的填充/空心正方形自定义Matplotlib标记?
实现带内部加号的自定义正方形标记折线图
你原代码的问题主要有两点:
- scatter的
marker参数不支持直接传入mpatches.Rectangle这类Patch对象,只能使用内置标记字符、Path对象或自定义标记代码 - 直接将多个Patch/Line2D对象传给legend的handles,会生成多个独立图例项,无法呈现组合标记的效果
以下是两种可行的解决方案:
方案一:用Path自定义复合标记(适合大量数据)
通过matplotlib.path.Path将正方形和加号的路径组合成一个自定义标记,效率高,支持scatter/plot直接调用:
import matplotlib.pyplot as plt from matplotlib.path import Path import numpy as np # 定义正方形+加号的复合路径 def create_custom_marker(): # 正方形顶点(顺时针) square_verts = [ (-0.5, -0.5), (-0.5, 0.5), (0.5, 0.5), (0.5, -0.5), (-0.5, -0.5) ] # 加号顶点 plus_verts = [ (0, -0.4), (0, 0.4), (0, 0), (-0.4, 0), (0.4, 0) ] # 路径命令:MOVETO(1)、LINETO(2)、CLOSEPOLY(7) square_codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY] plus_codes = [Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO, Path.LINETO] # 合并路径 verts = square_verts + plus_verts codes = square_codes + plus_codes return Path(verts, codes) # 示例数据 x = np.linspace(0, 10, 20) y = np.sin(x) fig, ax = plt.subplots() # 创建自定义标记 custom_mark = create_custom_marker() # 绘制折线+自定义标记 ax.plot(x, y, color='gray', linestyle='-', linewidth=1) ax.scatter(x, y, marker=custom_mark, s=200, facecolor='blue', edgecolor='white', linewidth=1.5) # 生成对应图例 from matplotlib.patches import PathPatch legend_patch = PathPatch(custom_mark, facecolor='blue', edgecolor='white', linewidth=1.5, label='Custom Marker') ax.legend(handles=[legend_patch]) plt.show()
方案二:手动绘制每个点的标记(适合小数据量,配色更灵活)
逐个在数据点位置绘制正方形和加号,可单独设置两种元素的颜色,图例需要自定义Handler来组合显示:
import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np x = np.linspace(0, 10, 20) y = np.sin(x) fig, ax = plt.subplots() # 先绘制基础折线 ax.plot(x, y, color='gray', linestyle='-', linewidth=1) # 遍历每个数据点,绘制正方形+加号 for xi, yi in zip(x, y): # 蓝色填充正方形 square = mpatches.Rectangle((xi-0.15, yi-0.15), 0.3, 0.3, facecolor='blue', edgecolor='white', linewidth=1.5, zorder=2) ax.add_patch(square) # 白色加号 ax.plot([xi, xi], [yi-0.12, yi+0.12], color='white', linewidth=2, zorder=3) ax.plot([xi-0.12, xi+0.12], [yi, yi], color='white', linewidth=2, zorder=3) # 自定义图例处理器 from matplotlib.legend_handler import HandlerBase class CustomHandler(HandlerBase): def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans): # 在图例区域绘制组合标记 square = mpatches.Rectangle((xdescent, ydescent), width, height, facecolor='blue', edgecolor='white', linewidth=1.5) plus1 = plt.Line2D([xdescent+width/2, xdescent+width/2], [ydescent+height*0.2, ydescent+height*0.8], color='white', linewidth=2) plus2 = plt.Line2D([xdescent+width*0.2, xdescent+width*0.8], [ydescent+height/2, ydescent+height/2], color='white', linewidth=2) return [square, plus1, plus2] # 添加图例 ax.legend([None], ['Custom Marker'], handler_map={None: CustomHandler()}) plt.show()
说明
- 数据量较大时优先选方案一,性能更优
- 需要单独调整正方形和加号颜色时,方案二更灵活
内容的提问来源于stack exchange,提问作者Vinayak Huggannavar
相关产品推荐
相关产品推荐

