web-dev-qa-db-fra.com

Puis-je afficher les décimales et la notation scientifique sur l'axe d'un graphique matplotlib en utilisant Python 2.7?

Je trace de grands nombres avec matplotlib dans un programme pyqt en utilisant python 2.7. J'ai un axe y qui va de 1e + 18 à 3e + 18 (généralement). Je voudrais voir chaque coche afficher les valeurs en notation scientifique et avec 2 décimales. Par exemple 2,35e + 18 au lieu de simplement 2e + 18 car les valeurs entre 2e + 18 et 3e + 18 ne lisent toujours que 2e + 18 pour quelques coche. Voici un exemple de ce problème.

import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16
ax.plot(x,y)  
ax.get_xaxis().set_major_formatter(plt.LogFormatter(10,  labelOnlyBase=False))
ax.get_yaxis().set_major_formatter(plt.LogFormatter(10,  labelOnlyBase=False))
plt.show()
17
tempneff

C'est vraiment facile à faire si vous utilisez le matplotlib.ticker.FormatStrFormatter par opposition à LogFormatter. Le code suivant étiquetera tout au format '%.2e':

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

fig = plt.figure()

ax = fig.add_subplot(111)

x = np.linspace(0, 300, 20)

y = np.linspace(0,300, 20)
y = y*1e16

ax.plot(x,y)

ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.2e'))

plt.show()

Example plot

41
Ffisegydd

Afin d'obtenir des étiquettes bien formatées en notation scientifique, on peut utiliser les capacités de formatage d'un ScalarFormatter qui utilise MathText (Latex) et l'appliquer aux étiquettes.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker

fig, ax = plt.subplots()

x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16

ax.plot(x,y)

f = mticker.ScalarFormatter(useOffset=False, useMathText=True)
g = lambda x,pos : "${}$".format(f._formatSciNotation('%1.10e' % x))
plt.gca().yaxis.set_major_formatter(mticker.FuncFormatter(g))

plt.show()

enter image description here

Bien que cela puisse être utile dans de nombreux cas, il ne répond pas réellement aux exigences de la question. Pour avoir des chiffres égaux sur toutes les étiquettes, une version plus personnalisée peut être utilisée.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker

fig, ax = plt.subplots()

x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16

ax.plot(x,y)

class MathTextSciFormatter(mticker.Formatter):
    def __init__(self, fmt="%1.2e"):
        self.fmt = fmt
    def __call__(self, x, pos=None):
        s = self.fmt % x
        decimal_point = '.'
        positive_sign = '+'
        tup = s.split('e')
        significand = tup[0].rstrip(decimal_point)
        sign = tup[1][0].replace(positive_sign, '')
        exponent = tup[1][1:].lstrip('0')
        if exponent:
            exponent = '10^{%s%s}' % (sign, exponent)
        if significand and exponent:
            s =  r'%s{\times}%s' % (significand, exponent)
        else:
            s =  r'%s%s' % (significand, exponent)
        return "${}$".format(s)

# Format with 2 decimal places
plt.gca().yaxis.set_major_formatter(MathTextSciFormatter("%1.2e"))

plt.show()

enter image description here