1

Consider the following plot, where we plot the same data into panel A with vertical labels and into panel B with horizontal labels using text wrapping.

import matplotlib.pyplot as plt

x = "Very long label"
y = "Even much longer label"
z = "Now this is what I call a really long label"

l = [x, y, z]
d = [3, 1, 4]

fig, (axA, axB) = plt.subplots(1, 2, figsize=(10, 5))

axA.bar(l, d)
font_dictA={"va": "center", "ha": "right", "rotation": 90, "wrap": True}
axA.set_xticklabels(l, fontdict= font_dictA)
axA.set_title("Case A: vertical labels")

axB.bar(l, d)
font_dictB={"va": "top", "ha": "center", "rotation": 0, "wrap": True}
axB.set_xticklabels(l, fontdict= font_dictB)
axB.set_title("Case B: horizontal labels")

plt.subplots_adjust(bottom=0.2)
plt.show()

giving the following output:

enter image description here

I assume that text wrapping does not work for horizontal labels is caused by differences in the bounding box calculation which is determined by taking the axis and border into consideration (vertical labels), but not adjacent label text boxes (horizontal labels). Can we easily set the text box dimensions of the labels for the horizontal labels (think: define their max-width)?
Please note that I only want to wrap the text of labels/legends/text with matplotlib functionality; I do not ask for external libraries like textwrap nor for other solutions like rotating labels.

Mr. T
  • 11,960
  • 10
  • 32
  • 54

2 Answers2

1

Text wrapping doesn't wrap text to not overlap, it wraps text when it tries to go outside the figure.

For vertical labels it seems as matplotlib wraps the text to have nice labels but it just prevents the text to go outside the figure. You can verify this when you set a tight layout - no wrapping occurs, just the axes is being shrinked to accommodate for the labels so that there's no need to wrap them (provided it's possible).

If you make the horizontal label so long that they would go outside the figure they will be wrapped, but only those that would go outside the figure. enter image description here

See also this source code comment in Text#_get_wrapped_text()

Return a copy of the text with new lines added, so that the text is wrapped relative to the parent figure.

Stef
  • 28,728
  • 2
  • 24
  • 52
  • I see. So, there is no way to enforce text wrapping by setting a bounding box as implemented in graphic design software? That would be a really good new feature, then. – Mr. T Jan 09 '21 at 18:14
  • As far as I know there isn't. Yes, it would indeed be a good feature. – Stef Jan 09 '21 at 18:21
  • Thank you for correcting my misconception. Retrospectively, the matplotlib behavior did not fit my idea about its behavior. And indeed, in a (1, 2) layout, text wrapping does not occur when conflicting with the lower subplot. – Mr. T Jan 09 '21 at 18:28
-1

You can use this code to rotate your text label.

import matplotlib.pyplot as plt
fig = plt.figure()
axis = fig.add_axes([0,0,1,1])
y = [10,20,30]
x = ["This is a large text","Bigger text label","Data can be big"]
axis.bar(x,y)
axis.tick_params(axis='x', rotation=90) # this line is responsible for text label orientation
plt.show()

Sample code output

Istiyak
  • 693
  • 6
  • 15