Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling tick labels alignment in pandas Boxplot within subplots

For a single boxplot, the tick labels alignment can be controlled like so:

import matplotlib.pyplot as plt
import matplotlib as mpl
%matplotlib inline

fig,ax = plt.subplots()
df.boxplot(column='col1',by='col2',rot=45,ax=ax)
plt.xticks(ha='right')

This is necessary because when the tick labels are long, it is impossible to read the plot if the tick labels are centered (the default behavior).

Now on to the case of multiple subplots. (I am sorry I am not posting a complete code example). I build the main figure first:

fig,axarr = plt.subplots(ny,nx,sharex=True,sharey=True,figsize=(12,6),squeeze=False)

then comes a for loop that iterates over all the subplot axes and calls a function that draws a boxplot in each of the axes objects:

    for key,gr in grouped:
        ix = i/ny # Python 2
        iy = i%ny
        add_box_plot(gr,xcol,axarr[iy,ix])

where

def add_box_plot(gs,xcol,ax):
    gs.boxplot(column=xcol,by=keyCol,rot=45,ax=ax)

I have not found a way to get properly aligned tick labels.

If I add plt.xticks(ha='right') after the boxplot command in the function, only the last subplot gets the ticks aligned correctly (why?).

like image 220
germ Avatar asked Oct 21 '25 00:10

germ


1 Answers

If I add plt.xticks(ha='right') after the boxplot command in the function, only the last subplot gets the ticks aligned correctly (why?).

This happens because plt.xticks refers to the last active axes. When you crate subplots, the one created last is active. You then access the axes opbjects directly(although they are called gs or gr in your code, whatever that means). However, this does not change the active axis.

Solution 1:

Use plt.sca() to set the current axis:

def add_box_plot(gs, xcol, ax):
    gs.boxplot(column=xcol, by=keyCol, rot=45, ax=ax)
    plt.sca(ax)
    plt.xticks(ha='right')

Solution 2:

Use Axes.set_xticklabels() instead:

def add_box_plot(gs, xcol, ax):
    gs.boxplot(column=xcol,by=keyCol,rot=45,ax=ax)
    plt.draw()  # This may be required to update the labels
    labels = [l.get_text() for l in ax.get_xticklabels()]
    ax.set_xticklabels(labels, ha='right')

I'm not sure if the call to plt.draw() is always required, but if I leave it out I only get empty labels.

like image 118
MB-F Avatar answered Oct 22 '25 15:10

MB-F