Matplotlib: show labels for minor ticks also

前端 未结 3 922
野趣味
野趣味 2020-12-09 20:21

In matplotlib, when I use a log scale on one axis, it might happen that that axis will have no major ticks, only minor

相关标签:
3条回答
  • 2020-12-09 20:49

    I've tried many ways to get minor ticks working properly in log plots. If you are fine with showing the log of the value of the tick you can use matplotlib.ticker.LogFormatterExponent. I remember trying matplotlib.ticker.LogFormatter but I didn't like it much: if I remember well it puts everything in base^exp (also 0.1, 0, 1). In both cases (as well as all the other matplotlib.ticker.LogFormatter*) you have to set labelOnlyBase=False to get minor ticks.

    I ended up creating a custom function and use matplotlib.ticker.FuncFormatter. My approach assumes that the ticks are at integer values and that you want a base 10 log.

    from matplotlib import ticker
    import numpy as np
    
    def ticks_format(value, index):
        """
        get the value and returns the value as:
           integer: [0,99]
           1 digit float: [0.1, 0.99]
           n*10^m: otherwise
        To have all the number of the same size they are all returned as latex strings
        """
        exp = np.floor(np.log10(value))
        base = value/10**exp
        if exp == 0 or exp == 1:   
            return '${0:d}$'.format(int(value))
        if exp == -1:
            return '${0:.1f}$'.format(value)
        else:
            return '${0:d}\\times10^{{{1:d}}}$'.format(int(base), int(exp))
    
    subs = [1.0, 2.0, 3.0, 6.0]  # ticks to show per decade
    ax.xaxis.set_minor_locator(ticker.LogLocator(subs=subs)) #set the ticks position
    ax.xaxis.set_major_formatter(ticker.NullFormatter())   # remove the major ticks
    ax.xaxis.set_minor_formatter(ticker.FuncFormatter(ticks_format))  #add the custom ticks
    #same for ax.yaxis
    

    If you don't remove the major ticks and use subs = [2.0, 3.0, 6.0] the font size of the major and minor ticks is different (this might be cause by using text.usetex:False in my matplotlibrc)

    0 讨论(0)
  • 2020-12-09 21:05

    I think it is worth mentioning the option "minor_thresholds" introduced in matplotlib version 2.0 (docs link). It's a parameter in the form of a pair (subset, all) of the class LogFormatter that allows you to specify when a (fixed) subset of minor ticklabels should be shown and when all minor ticklabels should be shown (explanation of what this means is at the bottom).

    In the following code I show the effect by using the same parameter values ((2, 0.4) in this case) but changing the limits of the x-axis:

    import matplotlib.pyplot as plt
    from matplotlib.ticker import LogFormatter
    import numpy as np
    
    fig, axes = plt.subplots(4, figsize=(12, 24))
    
    dt = 0.01
    t = np.arange(dt, 20.0, dt)
    
    # first plot doesn't use a formatter
    axes[0].semilogx(t, np.exp(-t / 5.0))
    axes[0].set_xlim([0, 25])
    axes[0].grid()
    
    xlims = [[0, 25], [0.2, 8], [0.6, 0.9]]
    
    for ax, xlim in zip(axes[1:], xlims):
        ax.semilogx(t, np.exp(-t / 5.0))
        formatter = LogFormatter(labelOnlyBase=False, minor_thresholds=(2, 0.4))
        ax.get_xaxis().set_minor_formatter(formatter)
        ax.set_xlim(xlim)
        ax.grid()
    
    plt.show()
    

    This results in the following plot:

    You see that in the second row the ticklabels are the same as in the first row where we didn't use a formatter. This is because the log of the view-range is more than 2 (the first value of the parameter pair) or to put it differently, the view spans a range that is bigger than a range between two major ticklabels. In the third row the view is smaller than 2 but bigger than 0.4 (the second value of the parameter pair), so we see a subset of the minor ticklabels. Finally, in the last row the view spans less than 0.4 of the space between two major ticklabels, so all minor ticklabels are shown.

    0 讨论(0)
  • 2020-12-09 21:08

    You can use set_minor_tickformatter on the corresponding axis:

    from matplotlib import pyplot as plt
    from matplotlib.ticker import FormatStrFormatter
    
    axes = plt.subplot(111)
    axes.loglog([3,4,7], [2,3,4])
    axes.xaxis.set_minor_formatter(FormatStrFormatter("%.2f"))
    plt.xlim(1.8, 9.2)
    plt.show()
    

    enter image description here

    0 讨论(0)
提交回复
热议问题