Frage Matplotlib-Protokollskalierung Tick-Label-Nummer Formatierung


Mit matplotlib Wenn für eine Achse ein logarithmischer Maßstab angegeben wird, lautet die Standardmethode für die Beschriftung dieser Achse Zahlen mit einer Stärke von z. B. 10. 10 ^ 6. Gibt es eine einfache Möglichkeit, alle diese Beschriftungen in ihre vollständige numerische Darstellung zu ändern? z.B. 1, 10, 100 usw.

Beachten Sie, dass ich nicht weiß, wie der Bereich der Befugnisse sein wird und einen willkürlichen Bereich (einschließlich Negative) unterstützen möchte.


31
2018-02-20 21:42


Ursprung


Antworten:


Sicher, ändern Sie einfach den Formatierer.

Zum Beispiel, wenn wir dieses Diagramm haben:

import matplotlib.pyplot as plt

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

plt.show()

enter image description here

Sie könnten die Hilfsstrichsbeschriftungen manuell festlegen, aber dann werden die Positionen und Beschriftungen der Hilfsstriche beim Zoomen / Verschieben / etc festgelegt. Daher ist es am besten, den Formatierer zu ändern:

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



Das habe ich gefunden ScalarFormatter ist toll, wenn alle Tick-Werte größer oder gleich 1 sind. Allerdings, wenn Sie eine Zahl ankreuzen <1, das ScalarFormatter druckt das Tick-Label als 0.

enter image description here

Ich habe das benutzt lambda Funktion mit FuncFormatter um Zahlen zu setzen >= 1 zu ihrem ganzzahligen Wert und Zahlen <1 auf ihren Dezimalwert mit der erforderlichen Mindestanzahl von Dezimalstellen (d. h. 0.1, 0.01, 0.001, etc). Es wird davon ausgegangen, dass Sie nur Ticks auf dem base10 Werte.

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

Zur Verdeutlichung, hier ist diese Lambda-Funktion auf eine ausführlichere, aber auch verständlichere Weise geschrieben:

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



in Bezug auf diese Fragen

Was wäre, wenn ich die Zahlen in 1, 5, 10, 20 ändern möchte?
  - Aloha 10. Juli 15 um 13:26 Uhr

Ich würde gern Zecken dazwischen hinzufügen, wie 50.200, etc .., Wie kann ich tun   Das? Ich habe versucht, set_xticks [50.0.200.0], aber das scheint nicht zu funktionieren!   - ThePredator 3. August 15 at 12:54

Aber mit ax.axis ([1, 100, 1, 100]) gibt ScalarFormatter 1.0, 10.0, ... was ich nicht möchte. Ich will, dass es ganze Zahlen gibt ...   - CPBL 7. Dezember 15 um 20:22 Uhr

Sie können diese Probleme mit MINOR Formatierer lösen:

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])

In meiner Anwendung verwende ich dieses Formatschema, das meiner Meinung nach die meisten Probleme im Zusammenhang mit der skalaren Formatierung von Logs löst. Das Gleiche könnte für Daten> 1.0 oder X-Achsenformatierung getan werden:

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)                

Kommentare zu "force autoscale" finden Sie unter:  Python matplotlib logarithmische Autoscale

was ergibt:

enter image description here

dann um eine allgemeine Maschine zu erstellen:

# 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)
#####################################################

Erträge:

enter image description here


3
2018-03-12 15:37



ich fand Joe's und Tom ist Antworten sehr hilfreich, aber es gibt viele nützliche Details in den Kommentaren zu diesen Antworten. Hier eine Zusammenfassung der beiden Szenarien:

Bereiche über 1

Hier ist der Beispielcode wie Joe, aber mit einem höheren Bereich:

import matplotlib.pyplot as plt

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

plt.show()

Das zeigt eine solche Darstellung mit wissenschaftlicher Notation: Default plot with scientific notation

Wie in Joes Antwort benutze ich eine ScalarFormatteraber ich rufe auch an set_scientific(False). Das ist notwendig, wenn der Maßstab 1000000 oder mehr erreicht.

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

Bereich unter 1

Wie in Toms Antwort geschieht hier Folgendes, wenn der Bereich unter 1 fällt:

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()

Dies zeigt die ersten beiden Ticks auf der x-Achse als Nullen an.

Plot with ticks labelled as zero

Wechseln zu a FuncFormatter behandelt das. Auch hier hatte ich Probleme mit den Zahlen 1000000 oder höher, aber das Hinzufügen einer Genauigkeit zum Formatzeichenkette löste es.

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