Formatieren Sie die y-Achse in Prozent

113

Ich habe ein vorhandenes Grundstück, das mit Pandas wie diesem erstellt wurde:

df['myvar'].plot(kind='bar')

Die y-Achse ist als float formatiert und ich möchte die y-Achse in Prozent ändern. Alle Lösungen, die ich gefunden habe, verwenden die ax.xyz-Syntax und ich kann nur Code unterhalb der Zeile darüber platzieren, die das Diagramm erstellt (ich kann ax = ax nicht zur obigen Zeile hinzufügen.)

Wie kann ich die y-Achse als Prozentsatz formatieren, ohne die obige Zeile zu ändern?

Hier ist die Lösung, die ich gefunden habe , die ich jedoch neu definieren muss :

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

data = [8,12,15,17,18,18.5]
perc = np.linspace(0,100,len(data))

fig = plt.figure(1, (7,4))
ax = fig.add_subplot(1,1,1)

ax.plot(perc, data)

fmt = '%.0f%%' # Format you want the ticks, e.g. '40%'
xticks = mtick.FormatStrFormatter(fmt)
ax.xaxis.set_major_formatter(xticks)

plt.show()

Link zur obigen Lösung: Pyplot: Verwenden des Prozentsatzes auf der x-Achse

Chris
quelle
Könnten Sie bitte Ihre akzeptierte Antwort auf den in matplotlib nativ implementierten Ansatz ändern? stackoverflow.com/a/36319915/1840471
Max Ghenis

Antworten:

127

Dies ist ein paar Monate zu spät, aber ich habe PR # 6251 mit matplotlib erstellt, um eine neue PercentFormatterKlasse hinzuzufügen . Mit dieser Klasse benötigen Sie nur eine Zeile, um Ihre Achse neu zu formatieren (zwei, wenn Sie den Import von zählen matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

ax = df['myvar'].plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())

PercentFormatter()drei Argumente akzeptiert, xmax, decimals, symbol. xmaxMit dieser Option können Sie den Wert einstellen, der 100% auf der Achse entspricht. Dies ist hilfreich, wenn Sie Daten von 0,0 bis 1,0 haben und diese von 0% bis 100% anzeigen möchten. Tu es einfach PercentFormatter(1.0).

Mit den beiden anderen Parametern können Sie die Anzahl der Stellen nach dem Dezimalpunkt und dem Symbol festlegen. Sie standardmäßig auf Noneund '%'sind. decimals=NoneLegt automatisch die Anzahl der Dezimalstellen fest, basierend auf der Anzahl der angezeigten Achsen.

Aktualisieren

PercentFormatter wurde in Matplotlib in Version 2.1.0 eingeführt.

Verrückter Physiker
quelle
@MateenUlhaq Bitte nehmen Sie bei Ihren Änderungen keine wesentlichen Codeänderungen vor. Sie haben den Code in meiner Antwort ohne Notwendigkeit repliziert. Es war keine gute Bearbeitung.
Mad Physicist
Mein schlechtes, aus irgendeinem seltsamen Grund, las ich das als from matplotlib.ticker import mtickund nahm an, dass das mtick"Modul" entfernt wurde.
Mateen Ulhaq
124

pandas dataframe plot gibt das axfür Sie zurück, und dann können Sie beginnen, die Achsen zu manipulieren, was Sie wollen.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(100,5))

# you get ax from here
ax = df.plot()
type(ax)  # matplotlib.axes._subplots.AxesSubplot

# manipulate
vals = ax.get_yticks()
ax.set_yticklabels(['{:,.2%}'.format(x) for x in vals])

Geben Sie hier die Bildbeschreibung ein

Jianxun Li
quelle
5
Dies wird unerwünschte Effekte haben, sobald Sie die Grafik interaktiv schwenken / zoomen
hitzg
3
Millionenmal einfacher als der Versuch, matplotlib.tickerFunktionsformatierer zu verwenden !
Jarad
Wie begrenzen Sie dann die y-Achse auf 0,100%? Ich habe ax.set_ylim (0,100) ausprobiert, aber das scheint nicht zu funktionieren !!
mpour
@mpour Nur die Beschriftungen der Yticks werden geändert, sodass die Grenzwerte immer noch in natürlichen Einheiten angegeben sind. Das Setzen von ax.set_ylim (0, 1) reicht aus.
Joeran
79

Jianxuns Lösung hat die Arbeit für mich erledigt, aber die y-Wert-Anzeige unten links im Fenster gebrochen.

Ich habe FuncFormatterstattdessen verwendet (und auch die unnötigen nachgestellten Nullen entfernt, wie hier vorgeschlagen ):

import pandas as pd
import numpy as np
from matplotlib.ticker import FuncFormatter

df = pd.DataFrame(np.random.randn(100,5))

ax = df.plot()
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y))) 

Generell würde ich die Verwendung FuncFormatterfür die Etikettenformatierung empfehlen : Sie ist zuverlässig und vielseitig.

Geben Sie hier die Bildbeschreibung ein

erwanp
quelle
18
Sie können den Code noch weiter vereinfachen : ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA keine Notwendigkeit für das Lambda, lassen Sie Format die Arbeit machen.
Daniel Himmelstein
@ DanielHimmelstein kannst du das ein bisschen erklären? Besonders innerhalb der {}. Ich bin mir nicht sicher, wie meine 0.06 mit dem Python-Format zu 6% wird. Auch tolle Lösung. Scheint viel zuverlässiger zu funktionieren als .set_ticklabels
DChaps
3
@DChaps '{0:.0%}'.formaterstellt eine Formatierungsfunktion . Das 0Vorher-Doppelpunkt weist den Formatierer an, die geschweiften Klammern und ihren Inhalt durch das erste an die Funktion übergebene Argument zu ersetzen. Der Teil nach dem Doppelpunkt .0%teilt dem Formatierer mit, wie der Wert gerendert werden soll. Das .0gibt 0 Dezimalstellen und %das Rendern in Prozent an.
Daniel Himmelstein
31

Für diejenigen, die den schnellen Einzeiler suchen:

plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()]) 

Wenn Sie Latex als Achsentextformatierer verwenden, müssen Sie einen Backslash '\' hinzufügen.

plt.gca().set_yticklabels(['{:.0f}\%'.format(x*100) for x in plt.gca().get_yticks()]) 
np8
quelle
Für mich hat Daniel Himmelsteins Antwort funktioniert, während diese Antwort die Skala geändert hat
R. Cox
2

Ich schlage eine alternative Methode vor seaborn

Arbeitscode:

import pandas as pd
import seaborn as sns
data=np.random.rand(10,2)*100
df = pd.DataFrame(data, columns=['A', 'B'])
ax= sns.lineplot(data=df, markers= True)
ax.set(xlabel='xlabel', ylabel='ylabel', title='title')
#changing ylables ticks
y_value=['{:,.2f}'.format(x) + '%' for x in ax.get_yticks()]
ax.set_yticklabels(y_value)

Geben Sie hier die Bildbeschreibung ein

Dr. Arslan
quelle
0

Ich bin zu spät zum Spiel, aber mir ist nur klar, dass dies axdurch plt.gca()diejenigen ersetzt werden kann, die keine Achsen und nur Nebenhandlungen verwenden.

Echo @ Mad Physicist Antwort, mit dem Paket PercentFormatterwäre es:

import matplotlib.ticker as mtick

plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter(1))
#if you already have ticks in the 0 to 1 range. Otherwise see their answer
Katze Mai
quelle