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

Rat*_*-IM 42 python matplotlib

我长期以来一直使用小子程序来格式化我正在绘制的图表的轴。几个例子:

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()])
Run Code Online (Sandbox Code Playgroud)

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

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

出现这种警告的原因是什么?我无法弄清楚查看 matplotlib 的文档。

小智 90

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

  • 哎呀!很好的收获@als0052。这是下次的字符串: `ax.set_xticks(ax.get_xticks()); ax.set_yticks(ax.get_yticks())` (3认同)
  • 我不断遇到这个警告并回到你的答案!与数据/绘图无关的解决方案是: `ax.set_yticks(ax.get_yticks().tolist()); ax.set_xticks(ax.get_xticks().tolist())`。 (2认同)

Rat*_*-IM 37

解决方法:

避免警告的方法是使用 FixedLocator(它是 matplotlib.ticker 的一部分)。下面我展示了一个绘制三个图表的代码。我以不同的方式格式化他们的轴。请注意,“set_ticks”使警告静音,但它会更改实际的刻度位置/标签(我花了一些时间才发现 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()
Run Code Online (Sandbox Code Playgroud)

输出图表:

示例图表

显然,有几行像上面这样的空闲代码行(我基本上是获取 yticks 或 xticks 并再次设置它们)只会给我的程序增加噪音。我希望警告被删除。但是,查看一些“错误报告”(来自上面/下面评论的链接;问题实际上不是错误:它是一个产生一些问题的更新),管理 matplotlib 的贡献者有他们的理由保持警告。

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

conda install matplotlib=3.2.2
Run Code Online (Sandbox Code Playgroud)

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


Ram*_*ami 29

当我尝试使用定位的日期刻度旋转 X 轴上的刻度标签时,我遇到了同样的问题:

ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
ax.xaxis.set_major_locator(dates.DayLocator())
Run Code Online (Sandbox Code Playgroud)

它使用“tick_params()”方法计算出来:

ax.tick_params(axis='x', labelrotation = 45)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。我对这个答案很满意。 (3认同)

小智 11

根据这个 matplotlib页面

# FixedFormatter should only be used together with FixedLocator. 
# Otherwise, one cannot be sure where the labels will end up.
Run Code Online (Sandbox Code Playgroud)

这意味着一个人应该做

from matplotlib import ticker

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))
Run Code Online (Sandbox Code Playgroud)

ticker.LogLocator但即使标签被传递到 ,问题仍然存在ticker.FixedFormatter。所以这种情况下的解决方案是

  1. 定义格式化函数

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

    ax.xaxis.set_major_locator(ticker.LogLocator(base=10, numticks=5))
    ax.xaxis.set_major_formatter(major_formatter)
    
    Run Code Online (Sandbox Code Playgroud)

详情请参阅上面的链接。

  • 另外:`从 matplotlib 导入股票代码` (2认同)

小智 6

我解决了只是添加这句话:

ax.set_xticks([1,2,3])
ax.set_xtickslabels(['Label1', 'Label2', 'Label3'])
Run Code Online (Sandbox Code Playgroud)