Skip to content

[Bug]: Axes.bar_label() on log scale does not center the label. #23688

Closed

Description

@stefmolin

Bug summary

When plotting on a log scale, if you pass label_type='center' to Axes.bar_label() the resulting labels are not centered in the bar, since the labels are being centered using the original base 10 scale.

Code for reproduction

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
bar_container = ax.barh(['c', 'b', 'a'], [1_000, 5_000, 7_000])
ax.set_xscale('log')
ax.set_xlim(1, None)
ax.bar_label(bar_container, label_type='center')

Actual outcome

Screen Shot 2022-08-20 at 6 07 03 PM

Expected outcome

I was expecting the labels to be in the center of the bar.

Additional information

The label should be placed using figure coordinates rather than data coordinates. I'm not sure how to get that information from the rectangles though.

Operating system

M1 Mac

Matplotlib Version

main branch

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

git checkout

Activity

  1. tacaswell commented on Aug 21, 2022

    @tacaswell
    Member

    https://matplotlib.org/stable/tutorials/text/annotations.html#using-complex-coordinates-with-annotations I think you want to use option 2 in that section and place the text relative to the bounding box of the rectangle.

    The back-compatibility on this may require some thought.

  2. stefmolin commented on Aug 21, 2022

    @stefmolin
    ContributorAuthor

    @tacaswell - Did you mean something like this?

    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    bar_container = ax.barh(['c', 'b', 'a'], [1_000, 5_000, 7_000])
    ax.set_xscale('log')
    ax.set_xlim(1, None)
    for bar in bar_container:
        ax.annotate(f'{bar.get_width():,d}',
                    xy=(0.5, 0.5), xycoords=bar,
                    xytext=(0, 0), textcoords='offset points',
                    ha='center', va='center')

    This only seems to work if the x in xy is 1, as I can move the text vertically by changing the y and the result is as expected. However, if I change the x value to 0.5 to place it halfway along the bar, nothing shows up, and if I do 0.99 the text is way beyond the beginning of the x-axis:
    Screen Shot 2022-08-21 at 11 27 43 AM

  3. tacaswell commented on Aug 21, 2022

    @tacaswell
    Member

    Oh, that makes sense. The bounding bax it is using is not clipped so the left edge is way off the the left at where ever the very small number we clip 0 up to in log scale is. Same log problem, but from the other side.....

  4. anntzer commented on Aug 21, 2022

    @anntzer
    Contributor

    The following (which was made easy by your debugging above!) seems to work:

    from matplotlib.transforms import Bbox
    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    bar_container = ax.barh(['c', 'b', 'a'], [1_000, 5_000, 7_000])
    ax.set_xscale('log')
    ax.set_xlim(1, None)
    for bar in bar_container:
        ax.annotate(
            f'{bar.get_width():,d}',
            xy=(0.5, 0.5),
            xycoords=lambda r, b=bar: Bbox.intersection(b.get_window_extent(r), b.get_clip_box()),
            xytext=(0, 0), textcoords='offset points',
            ha='center', va='center')
    
    plt.show()
  5. stefmolin commented on Aug 21, 2022

    @stefmolin
    ContributorAuthor

    Thanks @anntzer – I'm glad my debugging helped get to the bottom of this. Can I put in a PR to update Axes.bar_label() to properly handle the label_type='center' going forward? Unless this is something you don't want in the API, it seems more robust than what is already there and I imagine the logic will work for any axis scale.

  6. anntzer commented on Aug 21, 2022

    @anntzer
    Contributor

    Seems good to me (although I admittedly haven't followed the whole discussion).

  7. added a commit that references this issue on Aug 21, 2022
  8. added this to the v3.7.0 milestone on Aug 24, 2022
  9. added a commit that references this issue on Dec 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions