如何在水平 Seaborn 条形图上注释文本? [英] How to annotate text on horizontal Seaborn barplot?

查看:93
本文介绍了如何在水平 Seaborn 条形图上注释文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的问题是,一旦我想注释我的水平条,就会出现一些错误消息:

<块引用>

posx 和 posy 应该是有限值

然后我查看了代码,令人惊讶的是我得到了一些 nan 值,这些值仅在使用 hue 参数时出现.

代码:

ax = sns.barplot(x="Points", y="Characters", Hue="Average Speeds", data=albion_dataset, Palette="Set1", dodge=False)对于 ax.patches 中的 p:宽度 = p.get_width()打印(宽度)

<块引用>

输出:


2.57562




1.526325

...

但是当我删除 hue 选项时,没有 nan 并且注释工作完美无缺.数据框本身没有 nan 值.如何解决这个问题,以便我可以使用色调功能.数据类型是 floats 用于 x 和色调,object 用于 y.

更新:找到了注释条的方法,但现在最后一个条没有注释文本.

i = 0对于 ax.patches 中的 p:ax.annotate("%.4f" % albion_dataset["平均速度"][i], (p.get_x() + p.get_width(), p.get_y() + 1.2),xytext=(5, 10), textcoords='offset points')打印(一)我 += 1

此外,我如何将色调图例中的文本添加到条形图中,因为上面的代码没有考虑色调值的顺序.因此,我在条形上得到了错误的值.

解决方案

一种选择是依靠补丁本身的宽度,而不是尝试将条形与数据框匹配:

tips = sns.load_dataset("tips")tips.loc[(tips.day=="Thur")&(tips.sex=='Female')] = np.nantips.loc[(tips.day=="Sat")&(tips.sex=='Male')] = np.nanax = sns.barplot(y="day", x="total_bill", Hue="sex", data=tips, ci=None)对于 ax.patches 中的 p: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")

如果您需要知道 hue 的值(或访问每个条形对应的子数据框),那么我建议您明确传递一个 order=和一个 hue_order= 参数,所以你知道条形的绘制顺序.

import itertools提示 = sns.load_dataset("提示")tips.loc[(tips.day=="Thur")&(tips.sex=='Female')] = np.nantips.loc[(tips.day=="Sat")&(tips.sex=='Male')] = np.nangroup_col = '天'Hue_col = '性别'order=['Sat','Sun','Thur','Fri']Hue_order = ['女','男']ax = sns.barplot(y=group_col,x=total_bill",hue=hue_col,order=order,hue_order=hue_order,data=tips,ci=None)对于 zip(ax.patches,itertools.product(hue_order,order)) 中的 p,(cur_hue, cur_y):temp_df = tips.loc[(tips[group_col]==cur_y)&(tips[hue_col]==cur_hue)]# temp_df 是对应于当前柱`p`的子数据帧.它可以包含 0 行或更多行pos = p.get_width() 如果 p.get_width()>0 else 0ax.annotate(cur_hue, xy=(pos, p.get_y()+p.get_height()/2),xytext=(5, 0), textcoords='offset points', ha="left", va="center")

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

Than I looked into the code and surprisingly I got some nan values which only appear when the hue parameter is used.

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
nan
nan
nan
nan
1.526325
nan
...

But when I remove the hue option than there is no nan and the annotation works flawless. The dataframe itself has no nan values. 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.

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.

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")

这篇关于如何在水平 Seaborn 条形图上注释文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆