如何使用 seaborn 将图例添加到箱线图中

How to add legends to boxplots with seaborn

我有一组数据需要制作箱线图。我在添加图例时遇到麻烦,每个盒子的颜色都合适。这是我的代码:

model_names=["a","b","c","d","e","f","g","h"]
fig = plt.figure()
legend=model_names
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
sns.boxplot(data=df_A, ax=ax1, labels=model_names) # Adding model_names here gives errors.
ax1.set_xticklabels([])
ax1.tick_params(axis = "x", which = "both", bottom = False, top = False)

ax1.set_xlabel("A", fontsize=16)
ax1.set_ylabel("Score", fontsize=16)

sns.boxplot(data=df_B, ax=ax2)
ax2.set_xticklabels([])
ax2.tick_params(axis = "x", which = "both", bottom = False, top = False)
ax2.set_xlabel("B", fontsize=16)

这是我的数据框,df_A:

enter image description here

这是情节,没有传说:

enter image description here

Seaborn 更喜欢 "long form" 中的一种组合数据框。使用这样的数据框,可以使用 xhue 的旧列名创建 catplot(kind='box', ...)。色调名称将出现在图例中。

下面是一些示例代码,展示了如何创建“长格式”和组合数据帧。

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

model_names = ["a", "b", "c", "d", "e", "f", "g", "h"]

df_A = pd.DataFrame(np.random.rand(15, 8), columns=model_names)
df_B = pd.DataFrame(np.random.rand(20, 8), columns=model_names)
df_A_long = df_A.melt()
df_A_long['source'] = 'A'
df_B_long = df_B.melt()
df_B_long['source'] = 'B'
df_combined = df_A_long.append(df_B_long)

g = sns.catplot(kind='box', data=df_combined, col='source', x='variable', y='value', hue='variable',
                dodge=False, palette=sns.color_palette("Set2"), legend_out=True)
g.add_legend()
plt.setp(g.axes, xticks=[], xlabel='') # remove x ticks and xlabel
g.fig.subplots_adjust(left=0.06) # more space for the y-label
plt.show()

dfA_long 是通过 pd.melt() 创建的,它将列名放在一个名为“变量”的新列和一个名为“值”的列中,并具有相应的值。添加“来源”列后,它看起来像:

    variable     value source
0          a  0.581008      A
1          a  0.037324      A
2          a  0.833181      A
....

请注意,通常让 x 值显示每个框的名称比使用颜色和引用图例更清晰。更多的间接性使观众更难快速理解情节。但是如果例如名称太长而无法很好地适合 x 轴,或者当有许多类似的子图时,图例可能是一个很好的解决方案。