2

If one uses hue in seaborn's barplot and one of the categories is missing, it leads to this strange effect of "empty columns" where seaborn plots nothing at the place where it expects the hue to be (see below at the second position, Fri; or in the second picture). How can one centre such cases so that it is at the place of the tick? In the first case, it would be in the middle of the orange bar, in the second it would remove the empty space between the blue and green and place the tick in the middle of the green bar. Thanks.

import seaborn

tips = sns.load_dataset("tips")
tips.loc[(tips["sex"]=="Male")&(tips["day"]=="Fri"), "total_bill"]=np.nan

sns.barplot(x="day", y="total_bill", hue="sex", data=tips)

sns.barplot(x="sex", y="total_bill", hue="day", data=tips)

two categories

enter image description here

Side note, it is unrelated to this post.

My Work
  • 2,143
  • 2
  • 19
  • 47
  • There's a recent question / answer that covers this exactly, but I can't find it. You can look through the seaborn tagged qeustions – Trenton McKinney Sep 12 '21 at 16:43
  • @TrentonMcKinney [how to remove empty space from bars for a specific group, that was plotted as seaborn bar plot on data in pandas dataframe](https://stackoverflow.com/questions/66862337/how-to-remove-empty-space-from-bars-for-a-specific-group-that-was-plotted-as-se) ? [How to remove empty bars from catplot](https://stackoverflow.com/questions/65732126/how-to-remove-empty-bars-from-catplot) ? – JohanC Sep 12 '21 at 16:46
  • @JohanC Yes, the second one is the one I was thinking of, but I don't think it quite fits this question, now that I see it again. – Trenton McKinney Sep 12 '21 at 16:50
  • Maybe something like this [answer](https://stackoverflow.com/a/69023875/7758804), which is a manual implementation. – Trenton McKinney Sep 12 '21 at 16:52
  • 1
    Thanks for the comments. The [first mentioned post](https://stackoverflow.com/questions/66862337/how-to-remove-empty-space-from-bars-for-a-specific-group-that-was-plotted-as-se) is not ideal since it changes the problem -- subplots solve it for sure. The second is not exactly the same, as @TrentonMcKinney mentions. The [last post](https://stackoverflow.com/questions/69021751/avoiding-overlapping-plots-in-seaborn-bar-plot/69023875#69023875) with manual solution does some part of the job but ain't perfect, I'll update the question. But thanks both of you for tips. – My Work Sep 12 '21 at 17:40

1 Answers1

2

As mentioned in the comments by @TrentonMcKinney, the following post has some manual workaround (changed and adapted, notice also that the colours get preserved since it does not touch the graph, just the positions):

import seaborn
tips = sns.load_dataset("tips")
tips.loc[(tips["sex"]=="Male")&(tips["day"]=="Fri"), "total_bill"]=np.nan

plot1 = sns.barplot(x="day", y="total_bill", hue="sex", data=tips)

for i, bar in enumerate(plot1.axes.patches): 

    # move the missing to the centre
    current_width = bar.get_width()
    current_pos = bar.get_x()
    if i == 5:
        bar.set_x(current_pos-(current_width/2))
        # move also the std mark
        plot1.axes.lines[i].set_xdata(current_pos)


plot2 = sns.barplot(x="sex", y="total_bill", hue="day", data=tips)

for i, bar in enumerate(plot2.axes.patches): 

    # move the missing to the centre
    current_width = bar.get_width()
    current_pos = bar.get_x()
    if i == 0:
        bar.set_x(current_pos+(current_width/2))
        # get also the std mark
        plot2.axes.lines[i].set_xdata(current_pos+(current_width))
    
    if i == 4:
        bar.set_x(current_pos-(current_width/2))
        # get also the std mark
        plot2.axes.lines[i].set_xdata(current_pos)
    
    if i == 6:
        bar.set_x(current_pos-(current_width/2))
        # get also the std mark
        plot2.axes.lines[i].set_xdata(current_pos)    

There is more work (eg. taking also care of the std or finding the right index) and the problem remains -- it fills the space so that it looks better but does not remove the space. However, I believe that this is sufficient. Thanks a lot to @JohanC and @TrentonMcKinney.

enter image description here

enter image description here

My Work
  • 2,143
  • 2
  • 19
  • 47