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

时间:2019-12-06 12:47:49

标签: python pandas seaborn

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

  

posx和posy应该是有限值

比我看了一下代码,出乎意料的是,我得到了一些仅在使用{ 'filters[orderId]': null, 'filters[status]': [ 'rejected', 'accepted' ], 'filters[orderStatus]': 'A', 'filters[a.c]': 'deepFilter', 'filters[a.d]': 'lightFilters', 'filters[a.e.f]': [ 'Hi', 'There' ], 'filters[a.e.g]': 100, 'page[limit]': 15, 'page[offset]': 0 } 参数时才出现的nan值。

代码:

hue
  

输出:
  楠
  楠
  2.57562
  楠
  楠
  楠
  楠
  1.526325
  楠
  ...

但是,当我删除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) 选项时,就没有nan了,注释也可以完美地工作了。数据框本身没有nan值。如何解决此问题,以便可以使用色相功能。 对于x和hue,dtype是hue,对于y,dtypes是floats

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

object

此外,由于上述代码未考虑色相值的顺序,因此如何将色相图例中的文本添加到条形图。因此,我在条上得到了错误的值。

1 个答案:

答案 0 :(得分:0)

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

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

enter image description here

如果您需要了解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")

enter image description here