pythonmatplotlibaxis

changing the y axis in matplotlib


How can you change the y-axis in matplotlib such that you have specified ticks ([0, -1, -8, -44, -244]) but they are evenly spread over the y-axis (the gap between 0 and -1 is just as big as the gap between -44 and -244 if you visualise the figure). So you do not have an linear distribution on the y-axis but it makes you plot look better. The distance between the ticks should be equal and this makes your graph look better.

I tried to use the normal yticks first. I also tried the method where you use ax.set_yticks and ax.set_ytickslabels. However, it did not give me the wanted result.


Solution

  • It would be great to have a minimally working example to see what kind of data/plot are you working with. But generally speaking, it sounds like you need to transform your data/axis, rather than just selecting custom ticks.

    You could do this with a custom scale in matplotlib. Below, I have used interpolation to force the [-244, -44, -8, -1, 0] to have equally spaced values (in this case [0..4]). The advantage of using a scaling function rather than scaling your input data is that the yticks, etc. can be specified in the original scale.

    I've assumed that you really need a particular set of values to be equally spaced but you should also checkout other (simpler) scaling methods like set_yscale('log') if they make your plots look better.

    import matplotlib.pyplot as plt
    import numpy as np
    
    # Sample data
    x = np.linspace(0, 10, 100)
    y = 255*(np.sin(x)/2 - 0.5)
    
    # Define the values that need to be equally spaced
    y_scale = [-244, -44, -8, -1, 0]
    y_scale_vals = np.arange(len(y_scale))
    
    # Interpolate such that -244 -> 0, -44 -> 1, -8 -> 2, -1 -> 3, 0 -> 4
    def forward(y):
        return np.interp(y, y_scale, y_scale_vals)
    def inverse(y):
        return np.interp(y, y_scale_vals, y_scale)
    
    fig, ax = plt.subplots(1,2, layout='constrained')
    ax[0].plot(x, y)
    ax[0].set_title('Linear scale')
    
    ax[1].plot(x, y)
    ax[1].set_yscale('function', functions=(forward, inverse))
    ax[1].yaxis.set_ticks(y_scale)
    ax[1].set_title('Custom scale')
    

    An example sinusoidal dataset plotted with either a linear y axis, or a custom transform on the y axis that spaces the desired values equally