Customize x-axis in matplotlib

后端 未结 1 2021
梦如初夏
梦如初夏 2021-02-02 17:21

In the figure below, each unit in the x-axis represents a 10mins interval. I would like to customize the labels of x-axis, so that it shows hours, i.e. it displays a ticker ever

相关标签:
1条回答
  • 2021-02-02 17:23

    There's more than one way to do this.

    Let's start out with an example plot:

    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import numpy as np
    
    # Generate some data...
    x, y = np.mgrid[:141, :101]
    z = np.cos(np.hypot(x, y))
    
    # Plot the figure...
    plt.pcolormesh(x, y, z, cmap=mpl.cm.Reds)
    
    plt.show()
    

    enter image description here

    The simple way to do what you want would be something like this:

    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import numpy as np
    
    # Generate some data...
    x, y = np.mgrid[:141, :101]
    z = np.cos(np.hypot(x, y))
    
    # Plot the figure...
    plt.pcolormesh(x, y, z, cmap=mpl.cm.Reds)
    
    # Set the ticks and labels...
    ticks = np.arange(x.min(), x.max(), 6)
    labels = range(ticks.size)
    plt.xticks(ticks, labels)
    plt.xlabel('Hours')
    
    plt.show()
    

    enter image description here

    The other way involves subclassing matplotlib's locators and tickers.

    For your purposes, the example above is fine.

    The advantage of making new locators and tickers is that the axis will automatically be scaled into reasonable intervals of the "dx" units you specify. If you're using it as a part of a larger application, it can be worthwhile. For a single plot, it's more trouble than it's worth.

    If you really wanted to go that route, though, you'd do something like this:

    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import numpy as np
    
    def main():
        # Generate some data...
        x, y = np.mgrid[:141, :101]
        z = np.cos(np.hypot(x, y))
    
        # Plot the figure...
        fig, ax = plt.subplots()
        ax.pcolormesh(x, y, z, cmap=mpl.cm.Reds)
        ax.set_xlabel('Hours')
    
        ax.xaxis.set_major_locator(ScaledLocator(dx=6))
        ax.xaxis.set_major_formatter(ScaledFormatter(dx=6))
    
        plt.show()
    
    class ScaledLocator(mpl.ticker.MaxNLocator):
        """
        Locates regular intervals along an axis scaled by *dx* and shifted by
        *x0*. For example, this would locate minutes on an axis plotted in seconds
        if dx=60.  This differs from MultipleLocator in that an approriate interval
        of dx units will be chosen similar to the default MaxNLocator.
        """
        def __init__(self, dx=1.0, x0=0.0):
            self.dx = dx
            self.x0 = x0
            mpl.ticker.MaxNLocator.__init__(self, nbins=9, steps=[1, 2, 5, 10])
    
        def rescale(self, x):
            return x / self.dx + self.x0
        def inv_rescale(self, x):
            return  (x - self.x0) * self.dx
    
        def __call__(self): 
            vmin, vmax = self.axis.get_view_interval()
            vmin, vmax = self.rescale(vmin), self.rescale(vmax)
            vmin, vmax = mpl.transforms.nonsingular(vmin, vmax, expander = 0.05)
            locs = self.bin_boundaries(vmin, vmax)
            locs = self.inv_rescale(locs)
            prune = self._prune
            if prune=='lower':
                locs = locs[1:]
            elif prune=='upper':
                locs = locs[:-1]
            elif prune=='both':
                locs = locs[1:-1]
            return self.raise_if_exceeds(locs)
    
    class ScaledFormatter(mpl.ticker.OldScalarFormatter):
        """Formats tick labels scaled by *dx* and shifted by *x0*."""
        def __init__(self, dx=1.0, x0=0.0, **kwargs):
            self.dx, self.x0 = dx, x0
    
        def rescale(self, x):
            return x / self.dx + self.x0
    
        def __call__(self, x, pos=None):
            xmin, xmax = self.axis.get_view_interval()
            xmin, xmax = self.rescale(xmin), self.rescale(xmax)
            d = abs(xmax - xmin)
            x = self.rescale(x)
            s = self.pprint_val(x, d)
            return s
    
    if __name__ == '__main__':
        main()
    

    enter image description here

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