Seaborn 水平条形图

Seaborn horizontal bar plot

默认的 Seaborn 条形图几乎对我有用,尽管有一些细节。如下图:

请查看每个栏右侧的 'text' 注释。有几件事我想改进:

  1. 由于某种原因,最后一个栏没有显示注释。我不知道如何解决这个问题。

  2. 条形图的边缘与上下 X 轴之间没有 space。我想在那里放一些space。

  3. 是否可以增加条形的宽度?

  4. 我还想增加 'tallest' 条和右 Y 轴之间的距离,因为我计划添加文本,而不仅仅是与其 X 轴值相对应的厚度数字.如果您查看与 HRA 的 Red0 类别对应的条形图,它将类似于 105.65 (42.54%)。这显然会将它 'over' 推到右 Y 轴的边缘。有没有办法在其峰值和最大 X 轴值之间增加一些距离?因此,例如,如果我可以将其设置为条形的最大高度(易于计算)加上一定数量。

如果我能处理好这些细节,那就完美了!

这是与上述问题相关的代码片段:

sns.set_style('whitegrid')
sns.set(font_scale=0.8)
thickness = []
for hra_color in df_hra_colors['hra']:
    thickness.append(grouped.get_group(hra_color).count()['hra'] * mult)
df_hra_colors['thickness'] = thickness
ax = sns.barplot(x='thickness', y='hra', data=df_hra_colors,
                 palette=df_hra_colors['hex'].tolist())
ax.set_xlabel("Thickness")
ax.set_ylabel("HRA")
ax.set_title("What an Awesome Plot!")
for p in ax.patches:
    ax.annotate("%.2f" % p.get_width(), (p.get_x() + p.get_width(), p.get_y() + 1.2),
                xytext=(5, 10), textcoords='offset points')
plt.show()

这是一个最小的、完整的可验证示例:

""" Minimal program for demonstration """
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def main():
    sns.set_style('whitegrid')
    sns.set(font_scale=0.8)
    # plt.rcParams['figure.figsize'] = (10,10)
    df_hra_colors = pd.DataFrame({
        'hra': ['red', 'green', 'blue'],
        'hex': ['#cc0000', '#40ff00', '#0000ff']
    })
    thickness = [1, 2, 3]
    thick_sum = sum(thickness)
    df_hra_colors['thickness'] = thickness
    ax = sns.barplot(x='thickness', y='hra', data=df_hra_colors,
                     palette=df_hra_colors['hex'].tolist())
    plt.xlim(0, max(thickness) + 30)
    ax.set_xlabel("Thickness")
    ax.set_ylabel("HRA")
    ax.set_title("What an Awesome Plot!")
    for i, p in enumerate(ax.patches):
        ax.annotate("%.2f (%.2f)%%" % (p.get_width(), thickness[i] / thick_sum * 100.0),
                    (p.get_x() + p.get_width(), p.get_y() + 1),
                    xytext=(5, 10), textcoords='offset points')
    plt.show()

if __name__ == "__main__":
    main()

这是它的样子:

然后我将向 p.get_y() 添加 1 的行更改为添加 0.5,如下所示:

for i, p in enumerate(ax.patches):
    ax.annotate("%.2f (%.2f)%%" % (p.get_width(), thickness[i] / thick_sum * 100.0),
                (p.get_x() + p.get_width(), p.get_y() + 0.5),
                xytext=(5, 10), textcoords='offset points')

这就是我得到的:

所以注释文本因为偏移而被隐藏了。利用这些知识,我可以调整我的原始脚本以在最后一个栏中显示带注释的文本。但这会导致额外的问题。在事先不知道柱数的情况下如何调整代码保持一致?

你的答案 2 没问题。谢谢。

3 号对我不起作用,因为我使用的是 sns.barplot。 Python 不喜欢调用 barplot 时的宽度参数。

4 号工作正常。谢谢。

感谢您对我的问题的帮助。

  1. 关于第一点,我们需要minimal, complete, verifiable example.

  2. 为了在边缘条和轴之间放置 space,可以调整轴的限制。 ax.set_ylim(-1,N),其中 N 是柱数。

  3. 可以使用 plt.barwidth 参数设置条的宽度。 plt.bar(..., width=1);或者,对于水平条,使用 height 参数。 seaborn条形图不允许设置宽度或高度。

  4. 与 2 相同,只是 ax.set_xlim(0,barmax*1.4),其中 barmax 是柱的最大长度。