Mettre en forme l'axe y en pourcentage


114

J'ai un complot existant qui a été créé avec des pandas comme celui-ci:

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

L'axe y est au format flottant et je veux changer l'axe y en pourcentages. Toutes les solutions que j'ai trouvées utilisent la syntaxe ax.xyz et je ne peux placer du code que sous la ligne ci-dessus qui crée le tracé (je ne peux pas ajouter ax = ax à la ligne ci-dessus.)

Comment puis-je formater l'axe des y sous forme de pourcentages sans changer la ligne ci-dessus?

Voici la solution que j'ai trouvée mais nécessite que je redéfinisse l'intrigue :

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

Lien vers la solution ci-dessus: Pyplot: utilisation du pourcentage sur l'axe des x


Pourriez-vous s'il vous plaît changer votre réponse acceptée à l'approche implémentée nativement dans matplotlib? stackoverflow.com/a/36319915/1840471
— Max Ghenis

Réponses:


128

C'est quelques mois de retard, mais j'ai créé PR # 6251 avec matplotlib pour ajouter une nouvelle PercentFormatterclasse. Avec cette classe, vous n'avez besoin que d'une ligne pour reformater votre axe (deux si vous comptez l'importation de matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

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

PercentFormatter()accepte trois arguments, xmax, decimals, symbol. xmaxvous permet de définir la valeur qui correspond à 100% sur l'axe. C'est bien si vous avez des données de 0,0 à 1,0 et que vous souhaitez les afficher de 0% à 100%. Fais juste PercentFormatter(1.0).

Les deux autres paramètres vous permettent de définir le nombre de chiffres après la virgule décimale et le symbole. Ils sont respectivement par défaut Noneet '%'. decimals=Nonedéfinit automatiquement le nombre de points décimaux en fonction de la quantité d'axes que vous affichez.

Mettre à jour

PercentFormatter a été introduit dans Matplotlib proprement dit dans la version 2.1.0.


@MateenUlhaq Veuillez ne pas introduire de modifications de code significatives dans vos modifications. Vous avez répliqué le code dans ma réponse sans aucun besoin. Ce n'était pas un bon montage.
— Mad Physicist

Mon mauvais, pour une raison étrange, j'ai lu cela comme from matplotlib.ticker import mticket supposé que le mtick"module" était supprimé.
— Mateen Ulhaq le

125

pandas dataframe plot renverra le axpour vous, et vous pourrez alors commencer à manipuler les axes comme vous le souhaitez.

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

entrez la description de l'image ici


5
Cela aura des effets indésirables dès que vous effectuez un panoramique / zoom sur le graphique de manière interactive
— hitzg

3
Des millions de fois plus facile que d'essayer d'utiliser matplotlib.tickerdes formateurs de fonctions!
— Jarad

Comment limitez-vous alors l'axe des y pour dire (0,100%)? J'ai essayé ax.set_ylim (0,100) mais cela ne semble pas fonctionner !!
— mpour

@mpour seuls les libellés des yticks sont modifiés, les limites sont donc toujours en unités naturelles. Définir ax.set_ylim (0, 1) fera l'affaire.
— Joeran

79

La solution de Jianxun a fait le travail pour moi mais a cassé l'indicateur de valeur y en bas à gauche de la fenêtre.

J'ai fini par utiliser à la FuncFormatterplace (et j'ai également supprimé les zéros de fin non nécessaires comme suggéré ici ):

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

De manière générale, je recommanderais d'utiliser FuncFormatterpour le formatage des étiquettes: c'est fiable et polyvalent.

entrez la description de l'image ici


19
Vous pouvez simplifier le code encore plus: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA pas besoin de lambda, laissez le format faire le travail.
— Daniel Himmelstein

@DanielHimmelstein pouvez-vous expliquer cela un peu? Particulièrement à l'intérieur du {}. Je ne sais pas comment mon 0,06 est transformé en 6% en utilisant cela avec le format python. Aussi une excellente solution. Semble fonctionner de manière beaucoup plus fiable que l'utilisation de .set_ticklabels
— DChaps

3
@DChaps '{0:.0%}'.formatcrée une fonction de formatage . Le 0signe avant les deux points indique au formateur de remplacer les accolades et son contenu par le premier argument passé à la fonction. La partie après les deux points,, .0%indique au formateur comment rendre la valeur. Le .0spécifie 0 décimale et %spécifie le rendu en pourcentage.
— Daniel Himmelstein

31

Pour ceux qui recherchent le one-liner rapide:

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

Ou si vous utilisez Latex comme formateur de texte d'axe, vous devez ajouter une barre oblique inverse '\'

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

Pour moi, la réponse de Daniel Himmelstein a fonctionné alors que cette réponse a changé l'échelle
— R. Cox

2

Je propose une méthode alternative utilisant seaborn

Code de travail:

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)

entrez la description de l'image ici


0

Je suis en retard dans le jeu mais je me rends juste compte de ceci: axpeut être remplacé par plt.gca()pour ceux qui n'utilisent pas d'axes et juste des sous-intrigues.

En écho à la réponse de @Mad Physicist, en utilisant le package, PercentFormatterce serait:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.