Форматировать ось Y в процентах


114

У меня есть существующий сюжет, созданный с помощью таких пандов:

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

Ось y имеет формат с плавающей запятой, и я хочу изменить ось y на проценты. Во всех найденных мною решениях используется синтаксис ax.xyz, и я могу разместить код только под строкой выше, которая создает график (я не могу добавить ax = ax в строку выше).

Как отформатировать ось Y в процентах, не меняя строку выше?

Вот решение, которое я нашел, но требует, чтобы я переопределил сюжет :

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

Ссылка на приведенное выше решение: Pyplot: использование процента по оси x


Не могли бы вы изменить свой принятый ответ на подход, реализованный изначально в matplotlib? stackoverflow.com/a/36319915/1840471
Макс Генис 03

Ответы:


131

Это произошло с опозданием на несколько месяцев, но я создал PR # 6251 с matplotlib, чтобы добавить новый PercentFormatterкласс. С этим классом вам понадобится всего одна строка для переформатирования вашей оси (две, если вы считаете импорт matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

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

PercentFormatter()принимает три аргумента, xmax, decimals, symbol. xmaxпозволяет установить значение, соответствующее 100% на оси. Это хорошо, если у вас есть данные от 0,0 до 1,0 и вы хотите отображать их от 0% до 100%. Просто сделай PercentFormatter(1.0).

Два других параметра позволяют вам установить количество цифр после десятичной точки и символа. По умолчанию они равны Noneи '%'соответственно. decimals=Noneавтоматически установит количество десятичных знаков в зависимости от того, сколько осей вы показываете.

Обновить

PercentFormatter был введен непосредственно в Matplotlib в версии 2.1.0.


@MateenUlhaq Пожалуйста, не вносите существенных изменений кода в свои правки. Вы без надобности воспроизвели код из моего ответа. Это была не лучшая редакция.
Безумный физик,

Мое плохое, по какой-то странной причине я прочитал это from matplotlib.ticker import mtickи предположил, что mtick«модуль» был удален.
Матин Улхак,

125

График pandas dataframe вернет axдля вас, а затем вы можете начать манипулировать осями, как хотите.

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

введите описание изображения здесь


5
Это приведет к нежелательным эффектам, как только вы будете перемещать / масштабировать график в интерактивном режиме
hitzg

3
В миллион раз проще, чем пытаться использовать matplotlib.tickerформатеры функций!
Jarad

Как вы тогда ограничите ось Y, чтобы сказать (0,100%)? Я пробовал ax.set_ylim (0,100), но это, похоже, не работает !!
mpour

@mpour изменяются только ярлыки yticks, поэтому пределы по-прежнему выражены в натуральных единицах. Установка ax.set_ylim (0, 1) сделает свое дело.
Joeran

80

Решение Jianxun сработало за меня, но сломало индикатор значения y в нижнем левом углу окна.

В итоге я использовал FuncFormatterвместо этого (а также удалил ненужные конечные нули, как предлагается здесь ):

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

Вообще я бы рекомендовал использовать FuncFormatterдля форматирования этикеток: он надежный и универсальный.

введите описание изображения здесь


19
Вы можете упростить код еще больше: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA нет необходимости в лямбде, пусть формат сделает всю работу.
Даниэль Химмельштейн

@DanielHimmelstein, можешь немного объяснить это? Особенно внутри {}. Не уверен, как мои 0,06 превращаются в 6%, используя это с форматом python. Также отличное решение. Кажется, работает намного надежнее, чем использование .set_ticklabels
DC,

3
@DChaps '{0:.0%}'.formatсоздает функцию форматирования . 0Перед двоеточием говорит форматировщику заменить фигурные скобки и его содержимое с первым аргументом , переданной функцией. Часть после двоеточия, .0%сообщает программе форматирования, как визуализировать значение. .0Указывает 0 знаков после запятой и %определяет , рендеринга в процентах.
Даниэль Химмельштейн

31

Для тех, кто ищет быстрый однострочник:

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

Или, если вы используете Latex в качестве средства форматирования текста оси, вам нужно добавить одну обратную косую черту '\'

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

Для меня ответ Даниэля Химмельштейна сработал, тогда как этот ответ изменил масштаб
Р. Кокс

2

Предлагаю альтернативный метод с использованием seaborn

Рабочий код:

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)

введите описание изображения здесь


0

Я опаздываю в игру, но просто понимаю: axможно заменить на plt.gca()для тех, кто не использует топоры и только второстепенные сюжеты.

Повторяя ответ @Mad Physicist, используя пакет, PercentFormatterон будет:

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.