首页 > 解决方案 > Seaborn Barplot:异构条形图

问题描述

我正在使用 seaborn 来绘制不同算法的结果。我想区分不同的算法以及它们的分类(“组”)。问题是并非所有算法都在所有组中,所以当我使用 group as 时hue,我会得到很多空白:

import seaborn as sns
group = ['Simple', 'Simple', 'Complex', 'Complex', 'Cool']
alg = ['Alg 1', 'Alg 2', 'Alg 3', 'Alg 4', 'Alg 2']
results = [i+1 for i in range(len(group))]
sns.barplot(group, results, hue=alg)

条形图

如您所见,seaborn 为来自所有算法的条形留出了空间,使其位于所有组中,从而导致大量空白。我怎样才能避免这种情况?我确实想在 x 轴上显示不同的组,并通过颜色/样式区分不同的算法。算法可能出现在多个但不是所有组中。但我只想要“简单”和“复杂”中的 2 个小节的空间,而“酷”中的 1 个小节。matplotlib也欢迎任何带有纯的解决方案;它不需要是海运的。不过,我想保留 seaborn 调色板。

标签: pythonmatplotlibseabornbar-chart

解决方案


似乎没有创建这种类型的分组条形图的标准方法。以下代码为条形及其颜色创建位置列表,并为标签及其位置创建列表。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.patches import Patch

group = ['Simple', 'Simple', 'Complex', 'Complex', 'Cool']
alg = ['Alg 1', 'Alg 2', 'Alg 3', 'Alg 4', 'Alg 2']
colors = plt.cm.tab10.colors
alg_cat = pd.Categorical(alg)
alg_colors = [colors[c] for c in alg_cat.codes]

results = [i + 1 for i in range(len(group))]

dist_groups = 0.4 # distance between successive groups
pos = (np.array([0] + [g1 != g2 for g1, g2 in zip(group[:-1], group[1:])]) * dist_groups + 1).cumsum()
labels = [g1 for g1, g2 in zip(group[:-1], group[1:]) if g1 != g2] + group[-1:]
label_pos = [sum([p for g, p in zip(group, pos) if g == label]) / len([1 for g in group if g == label])
             for label in labels]
plt.bar(pos, results, color=alg_colors)
plt.xticks(label_pos, labels)
handles = [Patch(color=colors[c], label=lab) for c, lab in enumerate(alg_cat.categories)]
plt.legend(handles=handles)
plt.show()

结果图


推荐阅读