简体   繁体   English

如何在水平 Seaborn 条形图上注释文本?

[英]How to annotate text on horizontal Seaborn barplot?

I have the problem that as soon as I want to annotate my horizontal bars there will be some error message:我有一个问题,一旦我想注释我的水平条,就会出现一些错误消息:

posx and posy should be finite values posx 和 posy 应该是有限值

Than I looked into the code and surprisingly I got some nan values which only appear when the hue parameter is used.然后我查看了代码,令人惊讶的是我得到了一些 nan 值,这些值仅在使用hue参数时出现。

Code:代码:

ax = sns.barplot(x="Points", y="Characters", hue="Average Speeds", data=albion_dataset, palette="Set1", dodge=False)
for p in ax.patches:
    width = p.get_width()
    print(width)

Output:输出:
nan
nan
2.57562 2.57562
nan
nan
nan
nan
1.526325 1.526325
nan
... ...

But when I remove the hue option than there is no nan and the annotation works flawless.但是当我删除hue选项时,就没有 nan 并且注释工作完美无缺。 The dataframe itself has no nan values.数据框本身没有 nan 值。 How can this be fixed, so that I can use the hue function.如何解决这个问题,以便我可以使用色调功能。 The dtypes are floats for x and hue and object for y. dtypes 是 x 的floats ,y 的色调和object

UPDATE: Found a way to annotate the bars, but now the last bar has no annotation text.更新:找到了一种注释条的方法,但现在最后一个条没有注释文本。

i = 0
for p in ax.patches:
    ax.annotate("%.4f" % albion_dataset["Average Speeds"][i], (p.get_x() + p.get_width(), p.get_y() + 1.2),
            xytext=(5, 10), textcoords='offset points')
    print(i)
    i += 1

Furthermore, how can I add the text from the hue legend to the bars because the above code is not considering the order of the hue values.此外,我如何将色调图例中的文本添加到条形图中,因为上面的代码没有考虑色调值的顺序。 Thus I get wrong values on the bars.因此,我在条形图上得到了错误的值。

One option is to rely on the width of the patch itself, instead of trying to match the bar to the dataframe:一种选择是依赖补丁本身的宽度,而不是尝试将条形与数据框匹配:

tips = sns.load_dataset("tips")
tips.loc[(tips.day=="Thur")&(tips.sex=='Female')] = np.nan
tips.loc[(tips.day=="Sat")&(tips.sex=='Male')] = np.nan
ax = sns.barplot(y="day", x="total_bill", hue="sex", data=tips, ci=None)

for p in ax.patches:
    ax.annotate("%.4f" % p.get_width(), xy=(p.get_width(), p.get_y()+p.get_height()/2),
            xytext=(5, 0), textcoords='offset points', ha="left", va="center")

在此处输入图片说明

If you need to know the value of the hue (or access the sub-dataframe corresponding to each bar), then I would recommend you explicitly pass an order= and a hue_order= argument, so you know in what order the bars are drawn.如果您需要知道hue的值(或访问与每个条形对应的子数据框),那么我建议您明确传递一个order=和一个hue_order=参数,以便您知道条形的绘制顺序。

import itertools
tips = sns.load_dataset("tips")
tips.loc[(tips.day=="Thur")&(tips.sex=='Female')] = np.nan
tips.loc[(tips.day=="Sat")&(tips.sex=='Male')] = np.nan

group_col = 'day'
hue_col = 'sex'
order=['Sat','Sun','Thur','Fri']
hue_order = ['Female','Male']

ax = sns.barplot(y=group_col, x="total_bill", hue=hue_col, order=order, hue_order=hue_order, data=tips, ci=None)

for p,(cur_hue, cur_y) in zip(ax.patches,itertools.product(hue_order,order)):
    temp_df = tips.loc[(tips[group_col]==cur_y)&(tips[hue_col]==cur_hue)]
    # temp_df is the sub-dataframe that corresponds to the current bar `p`. It can contain 0 or more rows
    pos = p.get_width() if p.get_width()>0 else 0
    ax.annotate(cur_hue, xy=(pos, p.get_y()+p.get_height()/2),
                xytext=(5, 0), textcoords='offset points', ha="left", va="center")

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM