Search code examples
pythonmatplotlibx-axis

Hierarchical axis labeling


Suppose I'm looking at an n x n grid and on each axis I have labels of say, animals. But I'm also interested at looking at the relationship between groups, subgroups, etc. of the animals. So for example, I may have vertebrates and invertebrates, within vertebrates I may have mammals and reptiles and so forth. (If it matters, I'm particularly interested in a correlation matrix and am actually using a heatmap via seaborn...)

I'd like to plot this in matplotlib but have hierarchical labeling along the axes. So using my above example, I would have labels like dog, cat, horse, lizard, crocodile, etc. and then the first group of dog through horse would have a label of mammal and the second group of lizard, crocodile, etc. would have reptiles, and those two together would have a further label of vertebrates...

How would I do this?


Solution

  • Unfortunately I can't figure out how to disable minor ticks:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.ticker as ticker
    from mpl_toolkits.axes_grid.parasite_axes import SubplotHost
    
    fig1 = plt.figure()
    ax1 = SubplotHost(fig1, 111)
    fig1.add_subplot(ax1)
    
    # Some data
    x = np.arange(1,6)
    y = np.random.random(len(x))
    
    # First X-axis
    ax1.plot(x, y)
    ax1.set_xticks(x)
    ax1.set_xticklabels(['dog', 'cat', 'horse', 'lizard', 'crocodile'])
    #ax1.xaxis.set_label_text('First X-axis') # Uncomment to label axis
    ax1.yaxis.set_label_text("Sample data")
    
    # Second X-axis
    ax2 = ax1.twiny()
    offset = 0, -25 # Position of the second axis
    new_axisline = ax2.get_grid_helper().new_fixed_axis
    ax2.axis["bottom"] = new_axisline(loc="bottom", axes=ax2, offset=offset)
    ax2.axis["top"].set_visible(False)
    
    ax2.set_xticks([0.0, 0.6, 1.0])
    ax2.xaxis.set_major_formatter(ticker.NullFormatter())
    ax2.xaxis.set_minor_locator(ticker.FixedLocator([0.3, 0.8]))
    ax2.xaxis.set_minor_formatter(ticker.FixedFormatter(['mammal', 'reptiles']))
    
    # Third X-axis
    ax3 = ax1.twiny()
    offset = 0, -50
    new_axisline = ax3.get_grid_helper().new_fixed_axis
    ax3.axis["bottom"] = new_axisline(loc="bottom", axes=ax3, offset=offset)
    ax3.axis["top"].set_visible(False)
    
    ax3.set_xticks([0.0, 1.0])
    ax3.xaxis.set_major_formatter(ticker.NullFormatter())
    ax3.xaxis.set_minor_locator(ticker.FixedLocator([0.5]))
    ax3.xaxis.set_minor_formatter(ticker.FixedFormatter(['vertebrates']))
    
    ax1.grid(1)
    plt.show()
    

    enter image description here


    EDIT:

    1. Disabling minor ticks could be done by setting ticksize to 0 (thanks to @arnsholt): ax2.axis["bottom"].minor_ticks.set_ticksize(0).

    2. In latest matplotlib version (3.0.0 or higher) SubplotHost has to be imported as:

      from mpl_toolkits.axisartist.parasite_axes import SubplotHost