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

如何修改seaborn stripplot图例中的marker标记形状

Seaborn stripplot自定义marker后图例标记不匹配问题解决

问题描述

使用seaborn绘制stripplot时,分别为两组数据设置了三角形(^)和菱形(D)作为marker,但生成的图例仅显示彩色圆形,未匹配设置的标记形状。

可复现问题代码

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

letters = list('abcdefghijklmnopqrstuvwxyz')
place = ['North', 'South', 'East', 'West']

letter_set1 = set("abcdefghijklmn")
letter_set2 = set("opqrstuvwxyz")

data_size = 100

df_dict = {'letter': np.random.choice(letters, data_size), 
           'place': np.random.choice(place, data_size),
           "height": np.random.randint(low=40, high=100, size=data_size),
          "weight": np.random.randint(low=150, high=210, size=data_size),}

df = pd.DataFrame(df_dict)
print(df)

fig, ax = plt.subplots(1, 1, figsize=(10, 7))

# 此处violinplot可以忽略
sns.violinplot(x='place', y="weight", data=df, scale="width", inner="quartile", bw=0.2, linewidth=1,
)
for violin in ax.collections:
    violin.set_alpha(0.1)

set1_df = df[df['letter'].isin(letter_set1)]
set2_df = df[df['letter'].isin(letter_set2)]

sns.stripplot(data=set1_df, x='place', y="weight", hue="letter", palette="Set1", size=10, linewidth=0.05, marker='^', ax=ax
)
sns.stripplot(data=set2_df, x='place', y="weight", hue="letter", palette="Set2", size=10, linewidth=0.05, marker='D', ax=ax
)

# 调整图例顺序
handles, labels = ax.get_legend_handles_labels()
zipped_list = zip(handles, labels)
sorted_zipped_list = sorted(zipped_list, key=lambda x: x[1])
ordered_handles, ordered_labels = [x[0] for x in sorted_zipped_list], [x[1] for x in sorted_zipped_list]

ax.legend(
    handles=ordered_handles,
    labels=ordered_labels,
    title="Letter",
    bbox_to_anchor=(1.02, 1),
    loc="upper left",
    )
plt.tight_layout()

plt.show()
plt.close()

问题现象

输出效果如下图所示,图例中所有标记均为默认圆形,没有对应上自定义的三角形和菱形:
output

解决方法

可以直接修改PathCollection类型图例句柄的marker属性,不需要重新构造图例。在获取ordered_handles之后、调用ax.legend之前,加入标记样式修改代码即可,完整的图例设置部分如下:

# 更新图例顺序
handles, labels = ax.get_legend_handles_labels()
zipped_list = zip(handles, labels)
sorted_zipped_list = sorted(zipped_list, key=lambda x: x[1])
ordered_handles, ordered_labels = [x[0] for x in sorted_zipped_list], [x[1] for x in sorted_zipped_list]

# 新增:按分组修改每个句柄的marker样式
for handle, label in zip(ordered_handles, ordered_labels):
    handle.set_marker('^' if label in letter_set1 else 'D')

ax.legend(
    handles=ordered_handles,
    labels=ordered_labels,
    title="Letter",
    bbox_to_anchor=(1.02, 1),
    loc="upper left",
    )

该方法直接调用matplotlib PathCollection原生的set_marker方法修改实例属性,无需额外引入依赖,修改后图例标记会和stripplot设置的自定义标记完全对应。


内容的提问来源于stack exchange,提问作者LanternD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:06:04