pythonmatplotlibyticks

Bug with y axis minor ticks


Minor ticks on the y-axis are not placed as they should be. I set the minor locator to 2 so there should be 1 minor tick between each major tick but ticks on the bottom of the y-axis and none at the middle and on the top of axis.

Here is the code:

import numpy as np

import matplotlib.pyplot as plt

import pandas as pd

from matplotlib.ticker import (AutoMinorLocator)

from matplotlib.pyplot import figure

minor_locator = AutoMinorLocator(n=2)

#a je 2-->1

a_1_2 = np.array([0,12.3787177960363,0,12.3787177960363,0,0,0,13.4102776123727,0,0,0,13.4102776123727,0,10.3155981633636,0,10.3155981633636,0,14.441837428709,0,14.441837428709,0,15.4733972450454,0,15.4733972450454,0,13.4102776123727,0,20.6311963267272,0,20.6311963267272,0,0,0,18.5680766940545,0,18.5680766940545])

a_1_2[a_1_2==0] = np.nan

#b je 1-->2

b_1_2 = np.array([12.3787177960363,0,12.3787177960363,0,13.4102776123727,0,0,0,13.4102776123727,0,0,0,10.3155981633636,0,10.3155981633636,0,14.441837428709,0,14.441837428709,0,15.4733972450454,0,15.4733972450454,0,13.4102776123727,0,20.6311963267272,0,20.6311963267272,0,18.5680766940545,0,0,0,18.5680766940545,0])

b_1_2[b_1_2==0] = np.nan

#c je 2-->3

c = np.array([0,0,0,0,0,13.4102776123727,0,0,0,13.4102776123727,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.5680766940545,0,0,0,0])

c[c==0] = np.nan

#d je 3-->2

d = np.array([0,0,0,0,0,0,13.4102776123727,0,0,0,13.4102776123727,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.5680766940545,0,0,0])

d[d==0] = np.nan

vykon_1_2 = np.array([70,37,68,33,62,131,125,21,58,118,114,19,64,21,60,21,90,78,80,71,74,71,70,70,82,54,75,44,68,61,70,129,123,56,71,53])

a_1_04 = np.array([0,16.480541444427,0,16.480541444427,0,13.7337845370225,0,13.7337845370225,0,10.987027629618,0,10.987027629618,0,0,8.24027072221352,16.480541444427,0,0,15.1071629907248,0,15.1071629907248,0,19.2272983518315,0,12.3604060833203,0,9.61364917591577])

a_1_04[a_1_04==0] = np.nan

b_1_04 = np.array([16.480541444427,0,16.480541444427,0,16.480541444427,0,13.7337845370225,0,13.7337845370225,0,10.987027629618,0,10.987027629618,8.24027072221352,0,0,16.480541444427,15.1071629907248,0,15.1071629907248,0,19.2272983518315,0,12.3604060833203,0,9.61364917591577,0])

b_1_04[b_1_04==0] = np.nan

vykon_1_04 = np.array([80,44,65,44,67,36,78,36,79,60,79,61,80,99,90,54,70,85,39,85,39,72,67,102,48,128,127])

a_0_8 = np.array([0,27.8521150410817,0,27.8521150410817,0,32.4941342145953,0,32.4941342145953])

a_0_8[a_0_8==0] = np.nan

b_0_8 = np.array([27.8521150410817,0,27.8521150410817,0,32.4941342145953,0,32.4941342145953,0])

b_0_8[b_0_8==0] = np.nan

vykon_0_8 = np.array([105,100,101,97,97,95,98,94])

R_a_1_2 = 1.78*a_1_2*1.2e-3/(5.04e-5)

R_b_1_2 = 1.78*b_1_2*1.2e-3/(5.04e-5)

R_a_1_04 = 1.78*a_1_04*1.04e-3/(5.04e-5)

R_b_1_04 = 1.78*b_1_04*1.04e-3/(5.04e-5)

R_a_0_8 = 1.78*a_0_8*0.8e-3/(5.04e-5)

R_b_0_8 = 1.78*b_0_8*0.8e-3/(5.04e-5)

a_1_2 = pd.DataFrame(a_1_2)

b_1_2 = pd.DataFrame(b_1_2)

c = pd.DataFrame(c)

d = pd.DataFrame(d)

R_a_1_2 = pd.DataFrame(R_a_1_2)

R_b_1_2 = pd.DataFrame(R_b_1_2)

vykon_1_2 = pd.DataFrame(vykon_1_2)

a_1_04 = pd.DataFrame(a_1_04)

b_1_04 = pd.DataFrame(b_1_04)

R_a_1_04 = pd.DataFrame(R_a_1_04)

R_b_1_04 = pd.DataFrame(R_b_1_04)

vykon_1_04 = pd.DataFrame(vykon_1_04)

a_0_8 = pd.DataFrame(a_0_8)

b_0_8 = pd.DataFrame(b_0_8)

R_a_0_8 = pd.DataFrame(R_a_0_8)

R_b_0_8 = pd.DataFrame(R_b_0_8)

vykon_0_8 = pd.DataFrame(vykon_0_8)

data_1_2 = pd.concat([vykon_1_2, a_1_2,b_1_2,c,d], axis = 1)

data_1_04 = pd.concat([vykon_1_04, a_1_04,b_1_04], axis = 1)

data_0_8 = pd.concat([vykon_0_8, a_0_8,b_0_8], axis = 1)

data_R_1_2 = pd.concat([vykon_1_2, R_a_1_2,R_b_1_2,], axis = 1)

data_R_1_04 = pd.concat([vykon_1_04, R_a_1_04,R_b_1_04], axis = 1)

data_R_0_8 = pd.concat([vykon_0_8, R_a_0_8,R_b_0_8], axis = 1)

fig, ax = plt.subplots(figsize=(8,5), dpi = 100)

#figure(figsize=(8,5), dpi = 100)

#plt.plot(data.iloc[:,0],data.iloc[:,1],"v", color="#000000")

plt.ylabel('Výkon [W]')

plt.xlabel('Rychlost plynu [m/s]')

ax.plot(data_1_2.iloc[:,2],data_1_2.iloc[:,0],"v", color="#000000", label = "1,2 mm průměr")

ax.plot(data_1_04.iloc[:,2],data_1_04.iloc[:,0],"s", color="#ff0000", label = "1,04 mm průměr")

ax.plot(data_0_8.iloc[:,2],data_0_8.iloc[:,0],"o", color="#0000ff", label = "0,8 mm průměr")

ax.legend()

#plt.plot(data_1_2.iloc[:,2],data_1_2.iloc[:,0])

#plt.plot(data_1_2.iloc[:,3],data_1_2.iloc[:,0])

#plt.xlim(10, 140)

plt.yticks(np.arange(10,130+1, step=20))

ax.yaxis.set_minor_locator(minor_locator)

plt.xticks(np.arange(5, 35+1, step=2.5))

ax.xaxis.set_minor_locator(minor_locator)

plt.savefig("prechod_z_1_na_2.pdf")

#ax.xaxis.set_major_locator(MultipleLocator(20))

#ax.xaxis.set_minor_locator(MultipleLocator(5))

and there is the result I get:

enter image description here


Solution

  • TL;DR Always use ax.*axis.set_minor_locator(AutoMinorLocator(n))


    When you use the same instance of AutoMinorLocator twice, something bad is going to happen.

    I *guess that

    1. when an AutoMinorLocator is associated with an axis, an internal data structure is written with a list of ticks' positions
    2. when you associate the same instance, for you minor_locator, to two axis, the internal data is correct for the last axis only, because the internal data is overwritten
    3. when you use plt.show() only one axis is associated with the correct data structure (the last one that was associated), while the first axis ticks are placed according to list of positions found for the second one.

    Here follows an example.

    First subplot, same instance, first used on x and then on y, y ticks are OK, on x the ticks are on 16.67 and 23.33, i.e., the same two positions on y!
    Second subplot, same instance, first y then x, x ticks are OK, the y ticks are in the same positions as the x ticks, the last minor y tick is at 35, more or less...
    Third subplot, using two different, fresh instances, then both axes' ticks are OK.

    enter image description here

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.ticker import AutoMinorLocator
    
    #Number of Minor Ticks
    nmt = 3
    
    b_1_2 = np.array([12.3787177960363,0,12.3787177960363,0,13.4102776123727,0,0,0,13.4102776123727,0,0,0,10.3155981633636,0,10.3155981633636,0,14.441837428709,0,14.441837428709,0,15.4733972450454,0,15.4733972450454,0,13.4102776123727,0,20.6311963267272,0,20.6311963267272,0,18.5680766940545,0,0,0,18.5680766940545,0])
    b_1_04 = np.array([16.480541444427,0,16.480541444427,0,16.480541444427,0,13.7337845370225,0,13.7337845370225,0,10.987027629618,0,10.987027629618,8.24027072221352,0,0,16.480541444427,15.1071629907248,0,15.1071629907248,0,19.2272983518315,0,12.3604060833203,0,9.61364917591577,0])
    b_0_8 = np.array([27.8521150410817,0,27.8521150410817,0,32.4941342145953,0,32.4941342145953,0])
    
    vykon_1_2 = np.array([70,37,68,33,62,131,125,21,58,118,114,19,64,21,60,21,90,78,80,71,74,71,70,70,82,54,75,44,68,61,70,129,123,56,71,53])
    vykon_1_04 = np.array([80,44,65,44,67,36,78,36,79,60,79,61,80,99,90,54,70,85,39,85,39,72,67,102,48,128,127])
    vykon_0_8 = np.array([105,100,101,97,97,95,98,94])
    
    for v in (b_1_2, b_1_04, b_0_8): v[v==0] = np.nan
    
    fig, axes = plt.subplots(3, 1, figsize=(7, 10), layout='constrained')
    for n, ax in enumerate(axes.flat):
    
      ax.plot( b_1_2,  vykon_1_2, "v", color="#000000", label = "1,20 mm průměr")
      ax.plot(b_1_04, vykon_1_04, "s", color="#ff0000", label = "1,04 mm průměr")
      ax.plot (b_0_8,  vykon_0_8, "o", color="#0000ff", label = "0,80 mm průměr")
    
      ax.set_xticks(np.arange(5, 35+1, step=2.5))
      ax.set_yticks(np.arange(10,130+1, step=20))
      minor_locator = AutoMinorLocator(nmt)
      if n==0:
        ax.xaxis.set_minor_locator(minor_locator)  
        ax.yaxis.set_minor_locator(minor_locator)
      elif n==1:
        ax.yaxis.set_minor_locator(minor_locator)
        ax.xaxis.set_minor_locator(minor_locator)
      else:
        ax.xaxis.set_minor_locator(AutoMinorLocator(nmt))
        ax.yaxis.set_minor_locator(AutoMinorLocator(nmt))
          
      ax.set_xlabel('Rychlost plynu [m/s]')
      ax.set_ylabel('Výkon [W]')
      ax.legend()
    
    plt.show()