jkoal
jkoal

Reputation: 121

Adjusting the position of an xticklabel in matplotlib has no effect in x-direction

Using matplotlib 2.2.2 with gridspec in Python 3.6.5, I created a huge plot for a research paper with several subplots. The axes objects are stored in a dictionary called axes. This dictionary is passed to the function adjust_xticklabels(), which is supposed to align the first xticklabel slightly to the right and the last xticklabel slightly to the left in each subplot, such that the xticklabels of neighbouring plots dont get in the way of each other. The function is defined as:

def adjust_xticklabels(axes, rate = 0.1):

    for ax in axes.values():
        left, right = ax.get_xlim()                  # get boundaries
        dist = right-left                            # get distance
        xtl = ax.get_xticklabels()
        if len(xtl) > 1:
            xtl[0].set_position((left + rate*dist, 0.))   # (x, y), shift right
            xtl[-1].set_position((right - rate*dist, 0.)) # shift left

Calling it has no effect. Of course I also tried it with ridiculously high values. However, is has an effect in y-direction, for instance in case of setting xtl[0].set_position((0.3, 0.3)).

A simple reproduction:

ax = plt.subplot(111)
ax.plot(np.arange(10))
xtl = ax.get_xticklabels()
xtl[4].set_position((0.3, 0.3)) # wlog, 4 corresponds to 6

No effect in x-direction, despite specifying position as xy = (0.3, 0.3)

I spent quite a while on trying to figure out if this is a feature or a bug. Did I miss something or is this a bug? Is there any other way to do the same thing?

Upvotes: 2

Views: 243

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339102

This is a feature, no bug. The ticklabels are positionned at drawtime to sit at the correct locations according to the ticker in use. This ensures that the label always sits where the corresponding tick is located. If you change the limits, move or zoom the plot, the label always follows those changes.

You are usually not meant to change this location, but you may, by adding a custom transform to it. This is described in Moving matplotlib xticklabels by pixel value. The general idea is to set a translating transformation on the label. E.g. to translate the second label by 20 pixels to the right,

import matplotlib.transforms as mtrans
# ...
trans = mtrans.Affine2D().translate(20, 0)
label = ax.get_xticklabels()[1]
label.set_transform(label.get_transform()+trans)

Upvotes: 4

Related Questions