|
1 | | -""" |
2 | | -================= |
3 | | -Align tick labels |
4 | | -================= |
| 1 | +r""" |
| 2 | +========================== |
| 3 | +Left-aligned y tick labels |
| 4 | +========================== |
5 | 5 |
|
6 | 6 | By default, tick labels are aligned towards the axis. This means the set of |
7 | | -*y* tick labels appear right-aligned. Because the alignment reference point |
8 | | -is on the axis, left-aligned tick labels would overlap the plotting area. |
9 | | -To achieve a good-looking left-alignment, you have to additionally increase |
10 | | -the padding. |
| 7 | +y tick labels appear right-aligned. |
| 8 | +
|
| 9 | +To obtain left-aligned y tick labels, a solution is to force their |
| 10 | +horizontal-alignment to "left". However, because the alignment reference point |
| 11 | +is on the axis, such labels would overlap the plotting area, so the label |
| 12 | +padding needs to be additionally increased. |
| 13 | +
|
| 14 | +An alternate solution is to use the mathtext commands ``\rlap`` and |
| 15 | +``\phantom`` to manipulate the widths of the tick labels as seen by Matplotlib. |
| 16 | +See https://www.tug.org/TUGboat/tb22-4/tb72perlS.pdf for a detailed description |
| 17 | +of this approach. |
| 18 | +
|
| 19 | +See also :doc:`/gallery/axisartist/demo_ticklabel_alignment`. |
11 | 20 | """ |
| 21 | + |
12 | 22 | import matplotlib.pyplot as plt |
13 | 23 |
|
14 | 24 | population = { |
|
20 | 30 | "Shanghai": 21.9, |
21 | 31 | } |
22 | 32 |
|
23 | | -fig, ax = plt.subplots(layout="constrained") |
| 33 | +fig, axs = plt.subplots(1, 2, layout="constrained") |
| 34 | + |
| 35 | +# First solution: Force the horizontal-alignment of y tick labels to "left", |
| 36 | +# and increase the padding (to a manually chosen value). |
| 37 | + |
| 38 | +ax = axs[0] |
24 | 39 | ax.barh(population.keys(), population.values()) |
25 | 40 | ax.set_xlabel('Population (in millions)') |
26 | | - |
27 | | -# left-align all ticklabels |
28 | 41 | for ticklabel in ax.get_yticklabels(): |
29 | 42 | ticklabel.set_horizontalalignment("left") |
30 | | - |
31 | | -# increase padding |
32 | 43 | ax.tick_params("y", pad=70) |
| 44 | + |
| 45 | + |
| 46 | +# Second solution: Use mathtext to manipulate the width of ylabels as seen |
| 47 | +# by Matplotlib. Here, \rlap means "draw this text, but don't advance the |
| 48 | +# cursor", whereas \phantom means "advance the cursor by the width of the |
| 49 | +# enclosed text, but without actually drawing the text". The end result is |
| 50 | +# that the labels get aligned as if "Mexico City" was written every time, but |
| 51 | +# the real labels are actually drawn. |
| 52 | + |
| 53 | +# Note that the widest label ("Mexico City") is still hard-coded here (it is |
| 54 | +# the widest *rendered* label, which is not necessarily the longest label in |
| 55 | +# characters). |
| 56 | +def left_aligned_label(s): |
| 57 | + return r"$\rlap{\text{%s}}\phantom{\text{Mexico City}}$" % s |
| 58 | + |
| 59 | +ax = axs[1] |
| 60 | +ax.barh([*map(left_aligned_label, population)], population.values()) |
| 61 | +ax.set_xlabel('Population (in millions)') |
| 62 | + |
| 63 | +plt.show() |
0 commit comments