I would like to move some ticks' labels horizontally along the x-axis, without moving the corresponding ticks.
More specifically, when rotating labels with plt.setp
, the centers of the labels' text stay aligned with the ticks. I would like to shift those labels to the right, so that the near ends of the labels get aligned instead as suggested on the image below.
I am aware of this post and this one, however the answers are interesting kludges rather than strict answers to the question.
my code:
import matplotlib.pyplot as plt import numpy as np import datetime # my fake data dates = np.array([datetime.datetime(2000,1,1) + datetime.timedelta(days=i) for i in range(365*5)]) data = np.sin(np.arange(365*5)/365.0*2*np.pi - 0.25*np.pi) + np.random.rand(365*5) /3 # creates fig with 2 subplots fig = plt.figure(figsize=(10.0, 6.0)) ax = plt.subplot2grid((2,1), (0, 0)) ax2 = plt.subplot2grid((2,1), (1, 0)) ## plot dates ax2.plot_date( dates, data ) # rotates labels plt.setp( ax2.xaxis.get_majorticklabels(), rotation=-45 ) # try to shift labels to the right ax2.xaxis.get_majorticklabels()[2].set_y(-.1) ax2.xaxis.get_majorticklabels()[2].set_x(10**99) plt.show()
Strangely enough, set_y
behaves as expected, but even if I set x
to a fantasillion, the labels would not move by one iota. (The use of plot_date
may introduce additional confusion, but the same actually happens with plot
.)
With matplotlib version 3.3. 0, the matplotlib functions set_xlabel and set_ylabel have a new parameter “loc” that can help adjust the positions of axis labels. For the x-axis label, it supports the values 'left', 'center', or 'right' to place the label towards left/center/right.
If you know the tick positions, you can do something like for pos, tick in zip(ticks, ax. xaxis. get_majorticklabels()): tick. set_x(pos - 0.1) tick.
However there is no direct way to center the labels between ticks. To fake this behavior, one can place a label on the minor ticks in between the major ticks, and hide the major tick labels and minor ticks.
First of all, let's use a mcve to show the problem.
import numpy as np import datetime import matplotlib.pyplot as plt plt.rcParams["date.autoformatter.month"] = "%b %Y" # my fake data dates = np.array([datetime.datetime(2000,1,1) + datetime.timedelta(days=i) for i in range(365)]) data = np.sin(np.arange(365)/365.0*2*np.pi - 0.25*np.pi) + np.random.rand(365) /3 # creates fig with 2 subplots fig, ax = plt.subplots(figsize=(6,2)) ## plot dates ax.plot_date( dates, data ) # rotates labels plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45 ) plt.tight_layout() plt.show()
Now as other anwers pointed out already, you may use horizontal alignment of the text.
# rotates labels and aligns them horizontally to left plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left" )
You may use the rotation_mode
argument to let the rotation happen about the top left point of the text, giving a slightly nicer result in this case.
# rotates labels and aligns them horizontally to left plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left", rotation_mode="anchor")
In case those options are not fine grained enough, i.e. you want to position the labels more accurately, e.g. shifting it to the side by some points, you may use a transform. The following would offset the label by 5 points in horizontal direction, using a matplotlib.transforms.ScaledTranslation
.
import matplotlib.transforms plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45) # Create offset transform by 5 points in x direction dx = 5/72.; dy = 0/72. offset = matplotlib.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans) # apply offset transform to all x ticklabels. for label in ax.xaxis.get_majorticklabels(): label.set_transform(label.get_transform() + offset)
The advantage of this, compared to e.g. the solution provided by @explorerDude is that the offset is independent on the data in the graph, such that it is generally applicable to any plot and would look the same for a given fontsize.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With