Sformatuj oś Y jako procent

114

Mam istniejącą działkę, która została utworzona z pandami takimi jak ta:

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

Oś y ma format zmiennoprzecinkowy i chcę zmienić oś y na wartości procentowe. Wszystkie rozwiązania, które znalazłem, używają składni ax.xyz i mogę umieścić kod tylko poniżej linii powyżej, która tworzy wykres (nie mogę dodać ax = ax do linii powyżej).

Jak sformatować oś y jako wartości procentowe bez zmiany powyższej linii?

Oto rozwiązanie, które znalazłem, ale wymaga ponownego zdefiniowania działki :

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 do powyższego rozwiązania: Pyplot: używając procentu na osi x

Chris
źródło
Czy mógłbyś zmienić zaakceptowaną odpowiedź na podejście zaimplementowane natywnie w matplotlib? stackoverflow.com/a/36319915/1840471
Max Ghenis

Odpowiedzi:

129

To jest kilka miesięcy później, ale utworzyłem PR # 6251 z matplotlib, aby dodać nową PercentFormatterklasę. W przypadku tej klasy potrzebujesz tylko jednej linii do ponownego sformatowania osi (dwóch, jeśli liczysz import matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

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

PercentFormatter()przyjmuje trzy argumenty, xmax, decimals, symbol. xmaxpozwala ustawić wartość odpowiadającą 100% na osi. Jest to miłe, jeśli masz dane od 0,0 do 1,0 i chcesz wyświetlić je od 0% do 100%. Po prostu zrób PercentFormatter(1.0).

Pozostałe dwa parametry pozwalają ustawić liczbę cyfr po przecinku i symbolu. Są one domyślnie Nonei '%'odpowiednio. decimals=Noneautomatycznie ustawi liczbę miejsc dziesiętnych na podstawie liczby wyświetlanych osi.

Aktualizacja

PercentFormatter został wprowadzony do właściwej wersji Matplotlib w wersji 2.1.0.

Szalony Fizyk
źródło
@MateenUlhaq Prosimy nie wprowadzać znaczących modyfikacji kodu w swoich edycjach. Powtórzyłeś kod w mojej odpowiedzi bez żadnej potrzeby. To nie był dobry montaż.
Mad Physicist
Mój błąd, z jakiegoś dziwnego powodu, przeczytałem to jako from matplotlib.ticker import mticki założyłem, że mtick„moduł” został usunięty.
Mateen Ulhaq
125

pandas dataframe plot zwróci axza ciebie, a potem możesz zacząć manipulować osiami, co chcesz.

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

wprowadź opis obrazu tutaj

Jianxun Li
źródło
5
Będzie to miało niepożądane skutki, gdy tylko
przesuniesz
3
Milion razy łatwiejsze niż próba użycia matplotlib.tickerformatów funkcji!
Jarad
Jak zatem ograniczysz oś y do (0,100%)? Próbowałem ax.set_ylim (0,100), ale to nie działa !!
mpour
@mpour zmieniane są tylko etykiety yticków, więc limity są nadal w naturalnych jednostkach. Ustawienie ax.set_ylim (0, 1) załatwi sprawę.
Joeran
79

Rozwiązanie Jianxun wykonało zadanie za mnie, ale złamało wskaźnik wartości y w lewym dolnym rogu okna.

Skończyło się na tym, że FuncFormatterzamiast tego użyłem (a także usunąłem niepotrzebne zera końcowe, jak sugerowano tutaj ):

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

Ogólnie rzecz biorąc, polecam używanie FuncFormatterdo formatowania etykiet: jest niezawodne i wszechstronne.

wprowadź opis obrazu tutaj

erwanp
źródło
19
Można uprościć kod nawet więcej: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA nie potrzeba lambdy, niech format wykona całą pracę.
Daniel Himmelstein
@DanielHimmelstein Czy możesz to trochę wyjaśnić? Szczególnie wewnątrz {}. Nie jestem pewien, jak moje 0,06 zmienia się w 6%, używając tego w formacie Pythona. Również świetne rozwiązanie. Wydaje się, że działa znacznie bardziej niezawodnie niż używanie .set_ticklabels
DC Być może
3
@DC Być może '{0:.0%}'.formattworzy funkcję formatowania . 0Dwukropek „ przed” mówi programowi formatującemu, aby zamienić nawiasy klamrowe i ich zawartość na pierwszy argument przekazany do funkcji. Część po dwukropku .0%informuje formatera, jak wyrenderować wartość. .0Określa 0 miejsc po przecinku i %określa, renderowania jako procent.
Daniel Himmelstein
31

Dla tych, którzy szukają szybkiej jednej linijki:

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

Lub jeśli używasz Latex jako programu formatującego tekst osi, musisz dodać jeden lewy ukośnik „\”

plt.gca().set_yticklabels(['{:.0f}\%'.format(x*100) for x in plt.gca().get_yticks()]) 
np8
źródło
Dla mnie odpowiedź Daniela Himmelsteina zadziałała, podczas gdy ta odpowiedź zmieniła skalę
R. Cox
2

Proponuję alternatywną metodę wykorzystującą seaborn

Kod roboczy:

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)

wprowadź opis obrazu tutaj

Dr Arslan
źródło
0

Spóźniłem się do gry, ale po prostu zdaję sobie sprawę, że: axmożna go zastąpić plt.gca()dla tych, którzy nie używają osi i tylko poletek.

Powtarzając odpowiedź @Mad Physicist, używając pakietu PercentFormatterbędzie to:

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
Cat Mai
źródło