Formatta l'asse y come percentuale


114

Ho una trama esistente che è stata creata con i panda in questo modo:

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

L'asse y è formato come float e voglio cambiare l'asse y in percentuali. Tutte le soluzioni che ho trovato utilizzano la sintassi ax.xyz e posso solo posizionare il codice sotto la riga sopra che crea la trama (non posso aggiungere ax = ax alla riga sopra).

Come posso formattare l'asse y come percentuali senza modificare la linea sopra?

Ecco la soluzione che ho trovato ma richiede di ridefinire la trama :

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

Collegamento alla soluzione precedente: Pyplot: utilizzando la percentuale sull'asse x


Potresti cambiare la tua risposta accettata all'approccio implementato nativamente in matplotlib? stackoverflow.com/a/36319915/1840471
— Max Ghenis

Risposte:


128

Questo è in ritardo di alcuni mesi, ma ho creato PR # 6251 con matplotlib per aggiungere una nuova PercentFormatterclasse. Con questa classe hai solo bisogno di una riga per riformattare il tuo asse (due se conti l'importazione di matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

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

PercentFormatter()accetta tre argomenti, xmax, decimals, symbol. xmaxpermette di impostare il valore che corrisponde al 100% sull'asse. Questo è utile se hai dati da 0.0 a 1.0 e vuoi visualizzarli da 0% a 100%. Fallo e basta PercentFormatter(1.0).

Gli altri due parametri consentono di impostare il numero di cifre dopo il punto decimale e il simbolo. L'impostazione predefinita è Nonee '%', rispettivamente. decimals=Noneimposterà automaticamente il numero di punti decimali in base alla quantità di assi mostrati.

Aggiornare

PercentFormatter è stato introdotto in Matplotlib nella versione 2.1.0.


@MateenUlhaq Per favore, non introdurre modifiche significative al codice nelle tue modifiche. Hai replicato il codice nella mia risposta senza alcun bisogno. Non era una buona modifica.
— Mad Physicist

Colpa mia, per qualche strana ragione, l'ho letto e ho from matplotlib.ticker import mtickpensato che il mtick"modulo" fosse stato rimosso.
— Mateen Ulhaq

125

pandas dataframe plot restituirà il axper te, quindi puoi iniziare a manipolare gli assi come preferisci.

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

inserisci qui la descrizione dell'immagine


5
Ciò avrà effetti indesiderati non appena si
— esegue una

3
Milioni di volte più facile che provare a utilizzare i matplotlib.tickerformattatori di funzioni!
— Jarad

Come si limita quindi l'asse y a dire (0,100%)? Ho provato ax.set_ylim (0,100) ma non sembra funzionare !!
— Verso il

@mpour vengono modificate solo le etichette degli ytick, quindi i limiti sono ancora in unità naturali. L'impostazione di ax.set_ylim (0, 1) farà il trucco.
— Joeran

79

La soluzione di Jianxun ha funzionato per me, ma ha rotto l'indicatore del valore y in basso a sinistra nella finestra.

Ho finito per usare FuncFormatterinvece (e ho anche rimosso gli zeri finali non necessari come suggerito qui ):

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

In generale, ne consiglio l'utilizzo FuncFormatterper la formattazione dell'etichetta: è affidabile e versatile.

inserisci qui la descrizione dell'immagine


19
È possibile semplificare il codice ancora di più: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA non c'è bisogno di lambda, lascia che il formato faccia il lavoro.
— Daniel Himmelstein

@DanielHimmelstein puoi spiegarlo un po '? In particolare all'interno di {}. Non sono sicuro di come il mio 0,06 venga trasformato nel 6% usando quello con il formato python. Ottima anche la soluzione. Sembra funzionare in modo molto più affidabile rispetto all'utilizzo di .set_ticklabels
— DC Forse il

3
@DChaps '{0:.0%}'.formatcrea una funzione di formattazione . La 0prima dei due punti indica al formattatore di sostituire le parentesi graffe e il suo contenuto con il primo argomento passato alla funzione. La parte dopo i due punti,, .0%indica al formattatore come eseguire il rendering del valore. La .0specifica 0 cifre decimali e %specifica di rendering come percentuale.
— Daniel Himmelstein

31

Per coloro che cercano il one-liner veloce:

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

Oppure, se stai usando Latex come formattatore del testo dell'asse, devi aggiungere una barra rovesciata '\'

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

Per me, la risposta di Daniel Himmelstein ha funzionato mentre questa risposta ha cambiato la scala
— R. Cox il

2

Propongo un metodo alternativo utilizzando seaborn

Codice di lavoro:

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)

inserisci qui la descrizione dell'immagine


0

Sono in ritardo per il gioco ma me ne rendo conto: axpuò essere sostituito con plt.gca()per coloro che non utilizzano assi e solo sottotrame.

Facendo eco alla risposta di @Mad Physicist, usando il pacchetto PercentFormattersarebbe:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.