Question Matplotlib log scale cocher le numéro de label


Avec matplotlib Lorsqu'une échelle de journal est spécifiée pour un axe, la méthode par défaut d'étiquetage de cet axe est avec des nombres 10 à une puissance, par exemple. 10 ^ 6. Existe-t-il un moyen facile de changer toutes ces étiquettes pour qu’elles soient leur représentation numérique complète? par exemple. 1, 10, 100, etc.

Notez que je ne sais pas quelle gamme de puissances sera et que vous voulez supporter une gamme arbitraire (négatifs inclus).


31
2018-02-20 21:42


origine


Réponses:


Bien sûr, changez simplement le formateur.

Par exemple, si nous avons cette parcelle:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 100000])
ax.loglog()

plt.show()

enter image description here

Vous pouvez définir les libellés à cocher manuellement, mais les emplacements des étiquettes et les étiquettes seront corrigés lorsque vous effectuez un zoom / panoramique / etc. Par conséquent, il est préférable de changer le formateur:

from matplotlib.ticker import ScalarFormatter
for axis in [ax.xaxis, ax.yaxis]:
    axis.set_major_formatter(ScalarFormatter())

enter image description here


42
2018-02-20 22:05



J'ai trouvé qu'en utilisant ScalarFormatter est excellent si toutes les valeurs de ticks sont supérieures ou égales à 1. Cependant, si vous cochez un chiffre <1, la ScalarFormatter imprime l'étiquette de coche comme 0.

enter image description here

J'ai utilisé ceci lambda fonction avec FuncFormatter définir des nombres >= 1 à leur valeur entière et nombres <1 à leur valeur décimale, avec le nombre minimum de décimales requis (c.-à-d. 0.1, 0.01, 0.001, etc). Il suppose que vous ne définissez que des tics sur le base10 valeurs.

import matplotlib.ticker as ticker
import numpy as np

ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,pos: ('{{:.{:1d}f}}'.format(int(np.maximum(-np.log10(y),0)))).format(y)))

enter image description here

Pour plus de clarté, voici la fonction lambda écrite de manière plus détaillée, mais aussi plus compréhensible:

def myLogFormat(y,pos):
    # Find the number of decimal places required
    decimalplaces = int(np.maximum(-np.log10(y),0))     # =0 for numbers >=1
    # Insert that number into a format string
    formatstring = '{{:.{:1d}f}}'.format(decimalplaces)
    # Return the formatted tick label
    return formatstring.format(y)

ax.yaxis.set_major_formatter(ticker.FuncFormatter(myLogFormat))

22
2017-10-19 11:26



en ce qui concerne ces questions

Et si je voulais changer les chiffres en 1, 5, 10, 20?
  - aloha 10 juillet 15 à 13:26

Je voudrais ajouter des tiques entre 50,200, etc., comment puis-je faire   cette? J'ai essayé, set_xticks [50.0,200.0] mais cela ne semble pas fonctionner!   - The Predator 3 août 15 à 12h54

Mais avec ax.axis ([1, 100, 1, 100]), ScalarFormatter donne 1,0, 10,0, ce qui n'est pas ce que je souhaite. Je veux qu'il donne des nombres entiers ...   - CPBL 7 décembre 15 à 20h22

Vous pouvez résoudre ces problèmes avec le formateur MINOR:

ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
ax.set_yticks([0.00000025, 0.00000015, 0.00000035])

Dans mon application, j'utilise ce schéma de format qui, à mon avis, résout la plupart des problèmes liés au formatage logarithmique des logs; la même chose pourrait être faite pour les données> 1.0 ou le formatage des axes x:

plt.ylabel('LOGARITHMIC PRICE SCALE')
plt.yscale('log')
ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
#####################################################
#force 'autoscale'
#####################################################
yd = [] #matrix of y values from all lines on plot
for n in range(len(plt.gca().get_lines())):
        line = plt.gca().get_lines()[n]
        yd.append((line.get_ydata()).tolist())
yd = [item for sublist in yd for item in sublist]
ymin, ymax = np.min(yd), np.max(yd)
ax.set_ylim([0.9*ymin, 1.1*ymax])
#####################################################
z = []
for i in [0.0000001, 0.00000015, 0.00000025, 0.00000035,
          0.000001, 0.0000015, 0.0000025, 0.0000035,
          0.00001,  0.000015, 0.000025, 0.000035,
          0.0001, 0.00015, 0.00025, 0.00035,
          0.001, 0.0015, 0.0025, 0.0035,
          0.01, 0.015, 0.025, 0.035,
          0.1, 0.15, 0.25, 0.35]:

    if ymin<i<ymax:
        z.append(i)
        ax.set_yticks(z)                

pour les commentaires sur "force autoscale" voir:  Python matplotlib logarithmique à l'échelle automatique

qui donne:

enter image description here

puis pour créer une machine à usage général:

# user controls
#####################################################
sub_ticks = [10,11,12,14,16,18,22,25,35,45] # fill these midpoints
sub_range = [-8,8] # from 100000000 to 0.000000001
format = "%.8f" # standard float string formatting

# set scalar and string format floats
#####################################################
ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter(format))
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter(format))

#force 'autoscale'
#####################################################
yd = [] #matrix of y values from all lines on plot
for n in range(len(plt.gca().get_lines())):
        line = plt.gca().get_lines()[n]
        yd.append((line.get_ydata()).tolist())
yd = [item for sublist in yd for item in sublist]
ymin, ymax = np.min(yd), np.max(yd)
ax.set_ylim([0.9*ymin, 1.1*ymax])

# add sub minor ticks
#####################################################
set_sub_formatter=[]
for i in sub_ticks:
    for j in range(sub_range[0],sub_range[1]):
        set_sub_formatter.append(i*10**j)
k = []
for l in set_sub_formatter:
    if ymin<l<ymax:
        k.append(l)
ax.set_yticks(k)
#####################################################

donne:

enter image description here


3
2018-03-12 15:37



j'ai trouvé Joe's et Tom's des réponses très utiles, mais il y a beaucoup de détails utiles dans les commentaires sur ces réponses. Voici un résumé des deux scénarios:

Gammes ci-dessus 1

Voici l'exemple de code comme celui de Joe, mais avec une plage plus élevée:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 1000000])
ax.loglog()

plt.show()

Cela montre une intrigue comme celle-ci, en utilisant la notation scientifique: Default plot with scientific notation

Comme dans la réponse de Joe, j'utilise un ScalarFormatter, mais j'appelle aussi set_scientific(False). C'est nécessaire lorsque la balance monte à 1000000 ou au-dessus.

import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter

fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
    formatter = ScalarFormatter()
    formatter.set_scientific(False)
    axis.set_major_formatter(formatter)

plt.show()

Plot with integer ticks

Gammes ci-dessous 1

Comme dans la réponse de Tom, voici ce qui se passe lorsque la plage est inférieure à 1:

import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter

fig, ax = plt.subplots()
ax.axis([0.01, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
    formatter = ScalarFormatter()
    formatter.set_scientific(False)
    axis.set_major_formatter(formatter)

plt.show()

Cela affiche les deux premiers ticks sur l'axe des x sous forme de zéros.

Plot with ticks labelled as zero

Passer à un FuncFormatter gère cela. Encore une fois, j'ai eu des problèmes avec les nombres 1000000 ou plus, mais l'ajout d'une précision à la chaîne de format l'a résolu.

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

fig, ax = plt.subplots()
ax.axis([0.01, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
    formatter = FuncFormatter(lambda y, _: '{:.16g}'.format(y))
    axis.set_major_formatter(formatter)

plt.show()

enter image description here


1
2018-03-15 18:16