You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建内部带加号的填充/空心正方形自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:15:01