31

Im trying to plot a scatter matrix. I'm building on the example given in this thread Is there a function to make scatterplot matrices in matplotlib?. Here I have just modified the code slightly to make the axis visible for all the subplots. The modified code is given below

import itertools
import numpy as np
import matplotlib.pyplot as plt

def main():
    np.random.seed(1977)
    numvars, numdata = 4, 10
    data = 10 * np.random.random((numvars, numdata))
    fig = scatterplot_matrix(data, ['mpg', 'disp', 'drat', 'wt'],
            linestyle='none', marker='o', color='black', mfc='none')
    fig.suptitle('Simple Scatterplot Matrix')
    plt.show()

def scatterplot_matrix(data, names, **kwargs):
    """Plots a scatterplot matrix of subplots.  Each row of "data" is plotted
    against other rows, resulting in a nrows by nrows grid of subplots with the
    diagonal subplots labeled with "names".  Additional keyword arguments are
    passed on to matplotlib's "plot" command. Returns the matplotlib figure
    object containg the subplot grid."""
    numvars, numdata = data.shape
    fig, axes = plt.subplots(nrows=numvars, ncols=numvars, figsize=(8,8))
    fig.subplots_adjust(hspace=0.05, wspace=0.05)

    for ax in axes.flat:
        # Hide all ticks and labels
        ax.xaxis.set_visible(True)
        ax.yaxis.set_visible(True)

#        # Set up ticks only on one side for the "edge" subplots...
#        if ax.is_first_col():
#            ax.yaxis.set_ticks_position('left')
#        if ax.is_last_col():
#            ax.yaxis.set_ticks_position('right')
#        if ax.is_first_row():
#            ax.xaxis.set_ticks_position('top')
#        if ax.is_last_row():
#            ax.xaxis.set_ticks_position('bottom')

    # Plot the data.
    for i, j in zip(*np.triu_indices_from(axes, k=1)):
        for x, y in [(i,j), (j,i)]:
            axes[x,y].plot(data[x], data[y], **kwargs)

    # Label the diagonal subplots...
    for i, label in enumerate(names):
        axes[i,i].annotate(label, (0.5, 0.5), xycoords='axes fraction',
                ha='center', va='center')

    # Turn on the proper x or y axes ticks.
    for i, j in zip(range(numvars), itertools.cycle((-1, 0))):
        axes[j,i].xaxis.set_visible(True)
        axes[i,j].yaxis.set_visible(True)
    fig.tight_layout()
    plt.xticks(rotation=45)
    fig.show()
    return fig

main()

I cant seem to be able to rotate the x-axis text of all the subplots. As it can be seen, i have tried the plt.xticks(rotation=45) trick. But this seems to perform the rotation for the last subplot alone.

Community
  • 1
  • 1
Vignesh G
  • 345
  • 1
  • 3
  • 7

3 Answers3

55

Just iterate through the axes tied to the figure, set the active axes to the iterated object, and modify:

for ax in fig.axes:
    matplotlib.pyplot.sca(ax)
    plt.xticks(rotation=90)
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
aikramer2
  • 1,283
  • 12
  • 9
34

plt only acts on the current active axes. You should bring it inside your last loop where you set some of the labels visibility to True:

# Turn on the proper x or y axes ticks.
for i, j in zip(range(numvars), itertools.cycle((-1, 0))):
    axes[j,i].xaxis.set_visible(True)
    axes[i,j].yaxis.set_visible(True)

    for tick in axes[i,j].get_xticklabels():
        tick.set_rotation(45)
    for tick in axes[j,i].get_xticklabels():
        tick.set_rotation(45)
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Rutger Kassies
  • 61,630
  • 17
  • 112
  • 97
  • 14
    +1 On a side note, it's much easier to just iterate over `axes.flat` instead of cycling over all i,j pairs. Also, you could use `plt.setp(ax.get_xticklabels(), rotation=45)` instead of iterating over each tick label. That's just a matter of style, though. – Joe Kington Oct 09 '13 at 14:47
  • Agree, but the i,j iteration was already there, and only uses a subset of all the axes, there is no need to rotate hidden labels. The `setp` is a good addition indeed, i couldnt think of an `ax.` way of doing it at once, this does the trick! – Rutger Kassies Oct 09 '13 at 14:53
21
for ax in fig.axes:
    ax.tick_params(labelrotation=90)

  • 3
    Code only answers can almost always be improved by adding some explanation. Without some explanation answers end up in the review queues. – Jason Aller Apr 11 '20 at 16:48