Wie stelle ich die Tick-Skala als Potenz von 2 in matplotlib ein? [Duplikat]

Dec 16 2020

Ich möchte eine Figur zeichnen, deren xtick-Werte mit der Potenz 2 wachsen.

Zum Beispiel,

import pandas as pd
data = pd.DataFrame({
    'x': [2, 4, 8, 16, 32, 64],
    'y': [1, 2, 3, 4, 5, 6]
})

Was ich erwarte, ist eine Figur wie diese,

Für ordentliche Daten wie das obige Beispiel kann ich einfach eine Hilfsspalte x2von 1 ~ 6 in diesem Datenrahmen erstellen und dann die xticklabels der Abbildung auf 2 ^ 1 ~ 2 ^ 6 setzen. Diese Problemumgehung gilt jedoch nicht für Situationen mit anderen Werten wie 3, 7 oder 30.

Es scheint, dass matplotlib nur eine Protokollskala unterstützt. Wie kann ich einen Tick mit einer Leistungsskala von 2 erreichen?

Antworten

max Dec 16 2020 at 17:20

Dies ist eine besonders trickreiche Frage (die ich nicht erwartet hatte ^^).

OK, beginnen wir mit ein paar Hinweisen zum Lesen: Sie möchten die x / y-Skala festlegen : .matplotlib.axes.Axes.set_yscale () . Es gibt zwar einige Standardskalen (die Standardeinstellung ist natürlich 'liner', man kann eine benutzerdefinierte Skala festlegen. Hier sind einige schöne Beispiele.

Grundsätzlich definieren Sie zwei Funktionen mit der Vorwärtsumwandlung und mit der Umkehrung davon. Danach müssen Sie die Häkchen richtig einstellen (da Sie die Transformation nach dem Plotten anwenden , bleiben die Häkchen gleich (aber aufgrund der Transformation nicht an derselben Position). Hierfür gibt es zwei Möglichkeiten:

  • manuelles Setzen der Häkchen matplotlib.axes.Axes.set_xticks()oder
  • durch Einstellen des Positionierers der Achse : matplotlib.axes.Axes.xaxis.set_major_locator(). Dies wird empfohlen, wenn Sie Gitter verwenden. Da mein Wissen jedoch begrenzt ist, freue ich mich über eine ausführlichere Erklärung (da ich jetzt auch neugierig auf diese Funktion bin ^^)

Und jetzt kommt der schwierige Teil: Formatieren der Tick-Labels, um a darzustellen '2^x'. Ich habe keine bessere Idee gefunden, als sie explizit als Zeichenfolgen festzulegen. Es scheint, dass man das allgemeine Format nur innerhalb begrenzter Grenzen ändern kann, siehe matplotlib.pyplot.ticklabel_format(), wo man wählen kann, ob und wann eine wissenschaftliche Notation verwendet werden soll (dh a '10^x'unten rechts anzeigen ). Lassen Sie mich wissen, ob es dafür eine allgemeinere Lösung gibt.

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import FixedLocator

# create dummy data
df = pd.DataFrame({
    'x': [2**x for x in range(1,10)],
    'y': list(range(1,10))
})

def forward(x):
    return np.log2(x)


def inverse(x):
    return 2**x

# open figure
fig, ax = plt.subplots(2,2)
axs = ax.flatten()
for i in range(0,4):
    # plot data
    axs[i].plot(df['x'],df['y'])
    if i > 0:
        # set scale function
        axs[i].set_xscale('function', functions=(forward,inverse))
    if i > 1:
        # set ticks
        # - OPTION 1
        axs[i].set_xticks(df['x'])
        # - OPTION 2
      axs[i].xaxis.set_major_locator(FixedLocator(2**np.arange(1,10)))
    if i > 2:
        # est tick labels
        axs[i].set_xticklabels( [f"2^{j:.0f}" for j in np.log2(df['x'])] )

plt.show()