【问题标题】:Seaborn and matplotlib control legend in subplotsSeaborn 和 matplotlib 控制子图中的图例
【发布时间】:2020-05-11 23:56:18
【问题描述】:

我一直在玩 plt.legend() 和 ax.legend() 以及 seaborn 本身的传奇,我想我错过了一些东西。

我的第一个问题是,有人可以向我解释一下它们是如何结合在一起的,它们是如何工作的,如果我有子情节,什么比什么更好?意思是我可以设置一个一般定义(例如,在这个位置的所有子图中都有这个图例),然后为特定的子图覆盖这个定义(例如通过 ax.legend())?

我的第二个问题是实用的,并显示了我的问题。让我们以 seaborn Smokers 数据集为例进行说明:

import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")

# define sizes for labels, ticks, text, ...
# as defined here https://stackoverflow.com/questions/3899980/how-to-change-the-font-size-on-a-matplotlib-plot
SMALL_SIZE = 10
MEDIUM_SIZE = 14
BIGGER_SIZE = 18

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE)     # fontsize of the axes title
plt.rc('axes', labelsize=BIGGER_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=MEDIUM_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=MEDIUM_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE)    # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE)  # fontsize of the figure title


# create figure
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(16,12))
ylim = (0,1)

sns.boxplot(x= 'day', y= 'tip', hue="sex",
                  data=tips, palette="Set2", ax=ax1)
sns.swarmplot(x= 'day', y= 'tip', hue="sex",
                  data=tips, palette="Set2", ax=ax2)
ax2.legend(loc='upper right')

sns.boxplot(x= 'day', y= 'total_bill', hue="sex",
                  data=tips, palette="Set2", ax=ax3)
sns.swarmplot(x= 'day', y= 'total_bill', hue="sex",
                  data=tips, palette="Set2", ax=ax4)


plt.suptitle('Smokers')
plt.legend(loc='upper right')

plt.savefig('test.png', dpi = 150)

如果我简单地使用 seaborn,我会得到子图 1 和 3 中的图例——它具有“色调”标签并遵循定义的字体大小。但是,我无法控制它的位置(它有一些默认值,请参阅 1 和 3 之间的区别)。如果我在子图 2 中使用 ax.legend(),那么我可以修改特定的子图,但我失去了 seaborn 的“色调”功能(注意“性别”消失了)并且它不遵循我的字体定义。如果我使用 plt.legend(),它只会影响它之前的子图(在这种情况下为子图 4)。 我怎样才能团结这一切?例如。对所有子图有一个定义或如何控制 seaborn 默认值?为了明确目标,如何在子图 1 中创建一个图例,其中标签自动来自数据(但我可以更改它们),并且所有子图的位置、字体大小……都设置相同(例如。右上角,字体大小为 10,...)?

感谢您的帮助和解释。

【问题讨论】:

  • 我不明白第二个子图中的图例有什么问题。它有正确的标签、正确的位置和定义的字体大小,不是吗?
  • 不,它没有。首先,我必须将它添加到所有子图中,它不是全局的。其次,字体应该看起来像第一个或第三个(更大)和第三个,缺少色调标签,组标签('sex') - seaborn 自动将它放在那里。

标签: python matplotlib seaborn legend subplot


【解决方案1】:

Seaborn 传说总是用关键字loc=best 来调用。这是在源代码中硬编码的。您可以更改源代码,例如in this line 并替换为 ax.legend()。然后在代码中设置 rc 参数,如

plt.rc('legend', loc="upper right")

会给出想要的输出。

唯一的其他选择是手动创建图例,就像您在第二种情况下所做的那样,

ax2.legend(loc="upper right", title="sex", title_fontsize="x-large")

【讨论】:

  • 感谢您的链接。那么为什么 plt.legend() 不覆盖 seaborn 的默认值呢?或者它在哪里?
  • 我不明白这个问题,对不起。
  • 我的意思是 ax.legend() 覆盖默认值,即 seaborn 的源代码。为什么 plt.legend() 没有?还有一个问题。为什么plt.rc('legend', fontsize=SMALL_SIZE)定义的字体大小会影响图例(改一下看看字体大小的变化)而plt.rc('legend', loc="upper right")不影响?
  • ax.legendplt.legend都覆盖了seaborn创建的图例,没有区别。 plt.rc('legend', loc="upper right") 不会更改 seaborn 图例的位置,因为 seaborn 明确调用 plt.legend(loc="best"),如本答案中的链接所示。
猜你喜欢
  • 2018-07-05
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2016-10-15
  • 2019-10-17
  • 1970-01-01
相关资源
最近更新 更多