pythonmatplotlibsubplotsignificant-digits

Number of decimals in a subplot in scientific notation pyplot


I am making a figure with subplots with different y-axes. The y-axis of the last plot needs to be represented in scientific notation, and I would like the numbers on the axis to only display 2 decimals, i.e., 2.15 instead 2.1565. I have been trying to do format the numbers for hours without any success. Any suggestion on how to do it?

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mtick
from matplotlib.ticker import FormatStrFormatter


fig, axs = plt.subplots(2, 3)
y_pos = [0.2,0.4,0.6,0.8]


plt.setp(axs, xticks=[0.2,0.4,0.6,0.8], xticklabels=['A','B','C','D'],xlim=[0.1,0.9],facecolor='#F4F4F4')


#P-2

Pval = [3.3705E+00,3.4262E+00,3.5093E+00,3.4882E+00]

axs[0,0].set_ylim(3.3,3.55)
axs[0,0].set_yticks(np.arange(3.3,3.56, 0.05))
axs[0,0].grid(zorder=0)
axs[0,0].bar(y_pos,Pval,width=0.1,color='#ADDDCE')
axs[0,0].set_title(r'$Initial$') 
axs[0,0].grid(True,linestyle='--',color='#D6D8CD')





#P-1


Pval = [1.6667E+00,1.6079E+00,1.6087E+00,1.6132E+00]

axs[0,1].set_ylim(1.5,1.7)
axs[0,1].set_yticks(np.arange(1.5,1.71, 0.05))
axs[0,1].grid(zorder=0)
axs[0,1].bar(y_pos,Pval,width=0.1,color='#FFC347')

axs[0,1].set_title(r'$Test 1$') 
axs[0,1].grid(True,linestyle='--',color='#D6D8CD')







#P1

Pval = [9.9458E-01,9.4241E-01,9.4569E-01,9.4014E-01]
axs[0,2].set_ylim(0.8,1)
axs[0,2].set_yticks(np.arange(0.8,1.01, 0.05))

#
axs[0,2].grid(zorder=0)
axs[0,2].bar(y_pos,Pval,width=0.1,color='#FC746C')
# 
axs[0,2].set_title(r'$Test 2$') 
axs[0,2].grid(True,linestyle='--',color='#D6D8CD')





#P2


Pval = [2.4196E+00,2.3292E+00,2.3499E+00,2.3213E+00]
axs[1,0].set_ylim(1.8,2.5)
axs[1,0].set_yticks(np.arange(1.8,2.7, 0.2))
#
axs[1,0].grid(zorder=0)
axs[1,0].bar(y_pos,Pval,width=0.1,color='#70AE98')
# 
axs[1,0].set_title(r'$  \omega  $') 
axs[1,0].grid(True,linestyle='--',color='#D6D8CD')



#P3



Pval = [1.5646E+01,1.5346E+01,1.5538E+01,1.5298E+01]
axs[1,1].set_ylim(15,15.7)
axs[1,1].set_yticks(np.arange(15.,15.9, 0.2))

#X
axs[1,1].grid(zorder=0)
axs[1,1].bar(y_pos,Pval,width=0.1,color='#F0A35E')
#
axs[1,1].set_title(r'$  \Pi  $') 
axs[1,1].grid(True,linestyle='--',color='#D6D8CD')


#P4

Pval = [2.1391E+02,2.1148E+02,2.1434E+02,2.1085E+02]
axs[1,2].set_ylim(2.09E+02,2.15E+02)
axs[1,2].set_yticks(np.arange(2.09E+02,2.16E+02,0.95))
#axs[1,2].ticklabel_format(style='sci',scilimits=(200,300),axis='y')
#
#axs[1,2].yaxis.set_major_formatter(MathTextSciFormatter('%.2e'))

#m = grabMaxExponent(2)
#axs[1,2].yaxis.set_major_formatter(OOMFormatter(2, "%1.1f"))
#axs[1,2].yaxis.set_major_formatter(mtick.FormatStrFormatter('%.2f'))


axs[1,2].ticklabel_format(axis='y', style='sci', scilimits=(2,2))
axs[1,2].yaxis.major.formatter._useMathText = True
#axs[1,2].yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
#axs[1,2].yaxis.set_major_formatter(MathTextSciFormatter('%.2e'))
#axs[1,2].ticklabel_format(useOffset=False)
#X
axs[1,2].grid(zorder=0)
axs[1,2].bar(y_pos,Pval,width=0.1,color='#CA7E8D')
# 
axs[1,2].set_title(r'$\gamma$') 
axs[1,2].grid(True,linestyle='--',color='#D6D8CD')


fig.tight_layout()
plt.show()

This is the output of my code


Solution

  • ScalarFormatter doesn't support custom formatting. What you can try is overriding the method responsible for the formatting:

    (NOTE: This works for Matplotlib 3.0.x - Python 3.x, NOT Matplotlib 2.0.x.)

    from matplotlib.ticker import ScalarFormatter
    ...
    # P4
    
    # Extend ScalarFormatter
    class MyScalarFormatter(ScalarFormatter):
        # Override '_set_format' with your own
        def _set_format(self):
            self.format = '%.2f'  # Show 2 decimals
    
    # Your data as before
    Pval = [2.1391E+02,2.1148E+02,2.1434E+02,2.1085E+02]
    axs[1,2].set_ylim(2.09E+02,2.15E+02)
    axs[1,2].set_yticks(np.arange(2.09E+02,2.16E+02,0.95))
    
    # New code
    custom_formatter = MyScalarFormatter(useMathText=True)
    axs[1,2].yaxis.set_major_formatter(custom_formatter)
    axs[1,2].yaxis.major.formatter.set_powerlimits((2,2))
    #axs[1,2].yaxis.major.formatter.set_scientific(True)  # Redundant: True is default
    
    # Rest code as before
    axs[1,2].grid(zorder=0)
    axs[1,2].bar(y_pos,Pval,width=0.1,color='#CA7E8D')
    axs[1,2].set_title(r'$\gamma$') 
    axs[1,2].grid(True,linestyle='--',color='#D6D8CD')
    
    fig.tight_layout()
    plt.show()
    

    Output

    1

    It rounds your y-axis values, though. But you could work it out a bit this way to achieve the result you want. Take a look at ScalarFormatter source.