将Y轴格式设置为百分比。

226

我有一个已经用Pandas创建的图:

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 中本地实现的方法?https://dev59.com/ll0Z5IYBdhLWcg3whApv#36319915 - Max Ghenis
10个回答

342
这是几个月前的事情了,但我已经使用matplotlib创建了PR#6251,以添加一个新的PercentFormatter类。使用此类,您只需要一行代码重新格式化您的轴(如果计算上matplotlib.ticker的导入,则需要两行代码):
import ...
import matplotlib.ticker as mtick

ax = df['myvar'].plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
PercentFormatter() 接受三个参数,xmaxdecimalssymbolxmax 允许您设置与轴上的 100% 相对应的值。如果您有从 0.0 到 1.0 的数据,并且想将其显示为从 0% 到 100%,只需执行 PercentFormatter(1.0)

另外两个参数允许您设置小数点后的位数和符号。它们分别默认为 None'%'decimals=None 将根据您正在显示的轴的大小自动设置小数点的位数。

更新

PercentFormatter 在 Matplotlib 2.1.0 版本中正式引入。


1
哦,我认为这是因为默认值为decimal=None,它会根据范围自动生成小数位数。所以如果范围小于50%,它会生成10.0%。超过50%,它生成10%。因此很抱歉-您的答案是正确的,具体取决于其他参数。 - Dr Xorile
2
很好的答案!在我的情况下,我使用了 plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter()) 来避免先保存一个 ax 图。 - igorkf
@sancho.sReinstateMonicaCellio。哪个版本没有乘以100?PercentFormatter(1.0) - Mad Physicist
2
@MadPhysicist - 因为1.0等于100%,它们是相同的数字!好像使用x1e6更改为科学计数法会将1000000更改为1000000x1e6……它更改了数字。我从未想过,这肯定是erwanp的答案可行且无需进一步输入参数(如PercentFormatter)的原因。可能有进一步的xmax灵活性,但默认设置显然是错误的,它不是“无转换”。我一定是漏掉了什么...... - sancho.s ReinstateMonicaCellio
@MadPhysicist 你好,谢谢回复,但是那个方法没有起作用... - zyy
显示剩余13条评论

167

pandas dataframe plot会为你返回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])

输入图片描述


6
一旦您在图表上进行平移/缩放操作,这将产生不良影响。 - hitzg
4
比尝试使用 matplotlib.ticker 函数格式化工具简单百万倍! - Jarad
那么如何限制y轴的范围为(0,100%)呢? 我尝试使用ax.set_ylim(0,100),但似乎没有作用! - mpour
2
@mpour 只有 yticks 的标签被更改了,因此限制仍然是自然单位。设置 ax.set_ylim(0, 1) 就可以解决问题了。 - Joeran
不确定为什么,但这个答案错误地标记了刻度,而erwanp的则正确地标记了整个轴。 - Gene Burinsky

96

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进行标签格式化:它可靠且多功能。

enter image description here


22
代码可以更加简化: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format))。也就是说,不需要使用lambda函数,让format函数来完成工作即可。 - Daniel Himmelstein
@DanielHimmelstein,你能稍微解释一下吗?特别是在 { } 内部。不确定如何使用 Python 格式将我的 0.06 转换为 6%。此外,这是一个很好的解决方案。似乎比使用 .set_ticklabels 更可靠。 - DChaps
4
'{0:.0%}'.format 创建了一个格式化函数。冒号前的0告诉格式化程序使用传递给该函数的第一个参数来替换花括号及其内容。 冒号后面的“.0%”告诉格式化程序如何呈现值。 “.0”指定为零位小数,“%”指定以百分比形式呈现。 - Daniel Himmelstein

60
对于那些寻找简洁表达的人来说:
plt.gca().set_yticklabels([f'{x:.0%}' for x in plt.gca().get_yticks()]) 

或者,如果你已经将你的matplotlib.axes.Axes对象保存到变量ax中:
ax.set_yticklabels([f'{x:.0f}%' for x in ax.get_yticks()]) 

这假设:
  • 导入: from matplotlib import pyplot as plt
  • Python >=3.6 用于 f-String 格式化。对于旧版本,请用 '{:.0%}'.format(x) 替换 f'{x:.0%}'

1
对我来说,Daniel Himmelstein的答案有效,而这个答案改变了比例尺。 - R. Cox
如果设置刻度标签会改变比例尺,那么您应该在此之后发出比例尺选择命令。 - sancho.s ReinstateMonicaCellio

20

我来迟了,但我刚意识到这一点: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

6
我提出一种使用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)

enter image description here


5

您可以在一行代码中完成此操作,无需导入任何内容: plt.gca().yaxis.set_major_formatter(plt.FuncFormatter('{}%'.format))

如果您想要整数百分比,可以这样操作: plt.gca().yaxis.set_major_formatter(plt.FuncFormatter('{:.0f}%'.format))

您可以使用 ax.yaxisplt.gca().yaxisFuncFormatter 仍然是 matplotlib.ticker 的一部分,但您也可以使用 plt.FuncFormatter 作为快捷方式。


3

如果yticks在0和1之间,另一种一行代码的解决方案:

plt.yticks(plt.yticks()[0], ['{:,.0%}'.format(x) for x in plt.yticks()[0]])

3

根据@erwanp的回答,你可以使用Python 3的格式化字符串字面量

x = '2'
percentage = f'{x}%' # 2%

通过结合FuncFormatter()方法和一个lambda表达式,可以实现以下功能。

全部包装在一起:

ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: f'{y}%'))

0

添加一行代码

ax.yaxis.set_major_formatter(ticker.PercentFormatter())


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接