用户警告:FixedFormatter只能与FixedLocator一起使用

2024-09-27 09:34:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经使用了很长一段时间的小子程序来格式化我正在绘制的图表的轴。举几个例子:

def format_y_label_thousands(): # format y-axis tick labels formats
    ax = plt.gca()
    label_format = '{:,.0f}'
    ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

def format_y_label_percent(): # format y-axis tick labels formats
    ax = plt.gca()
    label_format = '{:.1%}'
    ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

但是,在昨天更新matplotlib后,调用这两个函数中的任何一个时,我会收到以下警告:

UserWarning: FixedFormatter should only be used together with FixedLocator
  ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

为什么要发出这样的警告?通过查看matplotlib的文档,我无法理解这一点


Tags: informatforgetlabelsdefaxlabel
3条回答

根据这个matplotlib page

# FixedFormatter should only be used together with FixedLocator. 
# Otherwise, one cannot be sure where the labels will end up.

这意味着我们应该这样做

positions = [0, 1, 2, 3, 4, 5]
labels = ['A', 'B', 'C', 'D', 'E', 'F']
ax.xaxis.set_major_locator(ticker.FixedLocator(positions))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(labels))

但是问题仍然存在于ticker.LogLocator,即使标签被传递给了ticker.FixedFormatter。 所以这个案例的解决方案是

  1. 定义格式化程序函数

    # FuncFormatter can be used as a decorator
    @ticker.FuncFormatter
    def major_formatter(x, pos):
        return f'{x:.2f}'
    
  2. 并将格式化程序函数传递给FixedFormatter

    ax.xaxis.set_major_locator(ticker.LogLocator(base=10, numticks=5))
    ax.xaxis.set_major_formatter(major_formatter)
    

有关详细信息,请参见上面的链接

解决方法:

避免警告的方法是使用FixedLocator(它是matplotlib.ticker的一部分)。下面我展示了绘制三个图表的代码。我以不同的方式格式化它们的轴。请注意,“设置刻度”会使警告静音,但会更改实际刻度位置/标签(我花了一些时间才发现FixedLocator使用相同的信息,但保持刻度位置不变)。您可以使用x/y来查看每个解决方案如何影响输出

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker

mpl.rcParams['font.size'] = 6.5

x = np.array(range(1000, 5000, 500))
y = 37*x

fig, [ax1, ax2, ax3] = plt.subplots(1,3)

ax1.plot(x,y, linewidth=5, color='green')
ax2.plot(x,y, linewidth=5, color='red')
ax3.plot(x,y, linewidth=5, color='blue')

label_format = '{:,.0f}'

# nothing done to ax1 as it is a "control chart."

# fixing yticks with "set_yticks"
ticks_loc = ax2.get_yticks().tolist()
ax2.set_yticks(ax1.get_yticks().tolist())
ax2.set_yticklabels([label_format.format(x) for x in ticks_loc])

# fixing yticks with matplotlib.ticker "FixedLocator"
ticks_loc = ax3.get_yticks().tolist()
ax3.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax3.set_yticklabels([label_format.format(x) for x in ticks_loc])

# fixing xticks with FixedLocator but also using MaxNLocator to avoid cramped x-labels
ax3.xaxis.set_major_locator(mticker.MaxNLocator(3))
ticks_loc = ax3.get_xticks().tolist()
ax3.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax3.set_xticklabels([label_format.format(x) for x in ticks_loc])

fig.tight_layout()
plt.show()

输出图表:

Sample charts

显然,有两行像上面那样的空闲代码(我基本上是获取ytick或xtick并再次设置它们)只会给我的程序增加噪音。我宁愿删除警告。但是,请查看一些“错误报告”(来自上面/下面评论的链接;该问题实际上不是一个错误:它是一个正在生成一些问题的更新),管理matplotlib的贡献者有理由保留该警告

旧版本的MATPLOTLIB: 如果您使用控制台来控制代码的关键输出(如我所做的),则警告消息可能会有问题。因此,延迟处理该问题的一种方法是将matplotlib降级为3.2.2版。我使用Anaconda管理Python包,下面是用于降级matplotlib的命令:

conda install matplotlib=3.2.2

并非所有列出的版本都可用。例如,无法安装matplotlib 3.3.0,尽管它列在matplotlib的发行版页面:https://github.com/matplotlib/matplotlib/releases

如果有人使用函数axes.xaxis.set_ticklabels()(或等效的yaxis)来到这里,您不需要使用FixedLocator,您可以在axes.xaxis.set_ticks(values_list)之前使用axes.xaxis.set_ticklabels(labels_list)避免此警告

相关问题 更多 >

    热门问题