Search code examples
python-3.xmatplotlibaxis-labelslogarithm

How to specify minor tick location without labeling using logarithmic scale in matplotlib?


I am trying to make a plot for which the major ticks along the x-axis are taken to be every third x-value (ie, index modulo 3) and the corresponding minor ticks are visible without labels. This isn't a problem in the linear scale, but using a logarithmic scale appears to change this. I am having trouble finding the right solution using logarithmic x-data. My actual use case is overlaying a linear and logarithmic scale on the same plot (ie, bottom and left axes correspond to linear scale, top and right axes correspond to logarithmic scale. However, my specific issue is removing the xticklabels for minor ticks along the x-axis. Below is an example.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter

x = 2**np.linspace(1, 16, 16).astype(int) ## LOGARITHMIC X-DATA
y = np.exp(x) / x**2 ## ARBITRARY Y-DATA

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xscale('log', basex=2)
ax.xaxis.set_major_formatter(ScalarFormatter()) ## REMOVE SCIENTIFIC NOTATION FOR LABELS
ax.set_xticks(x[::3]) ## MAJOR
ax.set_xticks([x[idx] for idx in range(len(x)) if idx % 3 != 0], minor=True) ## MINOR
ax.tick_params(axis='x', colors='gray', labelsize=7) 
ax.xaxis.tick_top()
ax.xaxis.set_label_position('top')
ax.set_xlim(min(x)-1, max(x)+1)
plt.show()
plt.close(fig)

The code above produces this plot.

Example Plot

I am trying to apply the solution to my actual use case, which is the figure below.

Use-Case Plot

How can I leave the major ticks as is while removing the minor tick labels? I want to keep the minor ticks visible without the label.


Solution

  • If I understood correctly, you are looking for something like the following. Couple of things here:

    • You need to define a twiny axis to be able to get the upper x-axis.
    • You then hide the minor tick labels for your twin axis using plt.setp()

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.ticker import ScalarFormatter
    
    x = 2**np.linspace(1, 16, 16).astype(int) ## LOGARITHMIC X-DATA
    y = np.exp(x) / x**2 ## ARBITRARY Y-DATA
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    ax2 = ax.twiny()
    
    ax2.set_xscale('log', basex=2)
    ax2.xaxis.set_major_formatter(ScalarFormatter()) ## REMOVE SCIENTIFIC NOTATION FOR LABELS
    ax2.set_xticks(x[::3]) ## MAJOR
    ax2.set_xticks([x[idx] for idx in range(len(x)) if idx % 3 != 0], minor=True) ## MINOR
    
    ax2.tick_params(axis='x', colors='gray', labelsize=7) 
    plt.setp(ax2.get_xminorticklabels(), visible=False) # Grab the ticks and hide them
    ax2.set_xlim(min(x)-1, max(x)+1)
    

    enter image description here