如何将不同的调色板分配给 Seaborn 条形图中的色调级别?

How to assign different palettes to hue levels in a Seaborn barplot?

我正在使用 Seaborn 在 Python 中创建条形图。 我有一个 2(注意:分散与集中)X 3(解决方案:1,2,3)设计。 对于划分,我希望条形颜色为深红色、深绿色、深蓝色。 为了聚焦,我希望条形颜色为红色、绿色、蓝色。

此代码不起作用,因为调色板仅适用于 hue 参数:

import seaborn as sns
import matplotlib.pyplot as plt

data = sns.load_dataset('attention')

palette = ["darkred", "red", "darkgreen", "green", "darkblue", "blue"]
palette = ["darkred", "darkgreen", "darkblue", "red", "green", "blue"]

sns.set(style='ticks', context='notebook', font_scale=1.2)
fig, ax = plt.subplots(figsize=(7, 5), dpi=96)
my_plot = sns.barplot(x="solutions", y="score", hue="attention",
                      palette=palette, capsize=.1, ax=ax, data=data)

plt.show()

这段代码几乎有效:

import seaborn as sns
import matplotlib.pyplot as plt

data = sns.load_dataset('attention')

sns.set(style='ticks', context='notebook', font_scale=1.5)
fig, ax = plt.subplots(figsize=(7, 5), dpi=96)
sns.barplot(x="solutions", y="score",
            palette=['red', 'green', 'blue'], capsize=.1, ax=ax,
            data=data.query('attention=="focused"'))
sns.barplot(x="solutions", y="score",
            palette=['darkred', 'darkgreen', 'darkblue'], capsize=.1, ax=ax,
            data=data.query('attention=="divided"'))
sns.despine(top=True, right=True)
plt.tight_layout()
plt.show()

但有 2 个问题:

  1. 无图例
  2. 条没有分开。

必须(应该?)有某种方法可以用优雅的方式用 seaborn 创建这个模型。第一种方法是理想的:使用指定图形的参数调用 barplot。第二种方法可以:多次调用 barplot。租赁理想的方法是直接调用 matplotlib bar(),但在这一点上,我会接受任何导致所需数字的方法。

请注意,据我所知,这些名称相似的问题似乎并未解决此问题中寻求的结果:

您可以使用灰色和黑色作为图例的色调来创建条形图。然后,遍历创建的条形并更改它们的颜色。

import seaborn as sns
import matplotlib.pyplot as plt

data = sns.load_dataset('attention')

sns.set(style='ticks', context='notebook', font_scale=1.2)
fig, ax = plt.subplots(figsize=(7, 5), dpi=96)
sns.barplot(x="solutions", y="score", hue="attention", hue_order=['divided', 'focused'],
            palette={'divided': 'grey', 'focused': 'black'}, capsize=.1, ax=ax, data=data)
for bar_group, desaturate_value in zip(ax.containers, [0.5, 1]):
    for bar, color in zip(bar_group, ['red', 'green', 'blue']):
        bar.set_facecolor(sns.desaturate(color, desaturate_value))
plt.show()

要获得图例中的所有变化,可以使用 TupleHandler,例如(使用 colors=['crimson', 'limegreen', 'dodgerblue']):

from matplotlib.legend_handler import HandlerTuple

ax.legend(handles=[tuple(bar_group) for bar_group in ax.containers],
          labels=[bar_group.get_label() for bar_group in ax.containers],
          title=ax.legend_.get_title().get_text(),
          handlelength=4, handler_map={tuple: HandlerTuple(ndivide=None, pad=0.1)})

这是另一个例子:

data = sns.load_dataset('tips')

sns.set(style='ticks', context='notebook', font_scale=1.2)
fig, ax = plt.subplots(figsize=(12, 5))
sns.barplot(x="day", y="tip", hue="smoker",
            capsize=.1, ax=ax, data=data)
for bar_group, desaturate_value in zip(ax.containers, [0.5, 1]):
    for bar, color in zip(bar_group, plt.cm.Set2.colors):
        bar.set_facecolor(sns.desaturate(color, desaturate_value))

ax.legend(handles=[tuple(bar_group) for bar_group in ax.containers],
          labels=[bar_group.get_label() for bar_group in ax.containers],
          title=ax.legend_.get_title().get_text(),
          handlelength=4, handler_map={tuple: HandlerTuple(ndivide=None, pad=0.1)})
sns.despine()
plt.tight_layout()
plt.show()