matplotlib 中以空格作为千​​位分隔符的科学刻度数

Dán*_*gyi 5 python matplotlib

我想在 y 轴上设置刻度,格式如下:

  • 应写出 < 1M 的数字,并用空格作为千​​位分隔符(例如20 000)
  • 数字 > 1M 应该采用科学计数法,就像标量格式化程序一样(2.0在x10^6轴上方)。

现在,我可以分别实现这两个功能。

matplotlib.ticker.FuncFormatter(lambda x, p: format(x, ',').replace(',', ' '))
Run Code Online (Sandbox Code Playgroud)

用空格替换千位分隔符。

formatter = matplotlib.ticker.ScalarFormatter()
formatter.set_powerlimits((-4, 6))
Run Code Online (Sandbox Code Playgroud)

给出 1M+ 的科学记数法。

我想我必须设置一个 ScalarFormatter 并稍微改变它的一个函数,或者我必须用 FuncFormatter 在 y 轴上方写入。但是,我找不到如何做到这一点。

编辑

我稍微接近了我的目标。通过使用format(x, ',.6g').replace(',', ' ')我至少拥有所需的数字格式。尽管如此,我更喜欢在
轴上 方使用指数符号,并且对于我的所有刻度,如果最大的刻度变得太大......

Ste*_*tef 1

原则上,您可以仅set_useLocale(True)使用标量格式化程序并使用修改后的区域设置。但是,ScalarFormatter 不使用分组(请参阅源代码),因此我们必须派生自己的 ScalarFormatter 并设置grouping=True)。

import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
import locale

fig, (ax1, ax2) = plt.subplots(ncols=2)

ax1.set_ylim(1, 10_000)
ax2.set_ylim(1, 10_000_000)


class MyScalarFormatter(ScalarFormatter):
    def __call__(self, x, pos=None):
        if len(self.locs) == 0:
            return ''
        else:
            xp = (x - self.offset) / (10. ** self.orderOfMagnitude)
            if abs(xp) < 1e-8:
                xp = 0
            if self._useLocale:
                s = locale.format_string(self.format, (xp,), grouping=True)
            else:
                s = self.format % xp
            return self.fix_minus(s)

sf = MyScalarFormatter(useLocale=True)
locale._override_localeconv = {'thousands_sep': ' ', 'grouping': [3,0]}

ax1.yaxis.set_major_formatter(sf)
ax2.yaxis.set_major_formatter(sf)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述