【问题标题】:How to set x tick labels against the actual values of the series如何根据系列的实际值设置 x 刻度标签
【发布时间】:2015-12-10 08:40:04
【问题描述】:

我正在尝试设置 x 刻度标签,但允许 matplotlib 决定放置刻度的位置。不幸的是,当我设置 x 刻度标签时,matplotlib 只会将标签字符串用于已显示的刻度。

例子:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
ax.plot(xs, ys)
ax.set_xticklabels(list('abcdefghijklmnopqrstuvwxyz'))
plt.show()

这给出了:

这对我来说很不直观;我希望标签与它们显示的点相对应。 (不过,我可以理解这种行为在绘制不使用相同 x 值的多个系列时更有用。)

注意:我不希望所有 26 个字母都作为刻度。相反,我只想要 6 个(正如 matplotlib 所建议的那样),但是这 6 个应该适合他们的位置。这样就可以轻松更改无花果大小,而无需手动重新计算新的刻度标签。

我怎样才能达到预期的效果?

【问题讨论】:

  • 这是set_ticklabels 危险的原因之一,它是FixedFormatter 的传递,只能与FixedLocator 一起使用。

标签: python matplotlib


【解决方案1】:

您需要在标签之前指定刻度位置。获得示例所需结果的最简单方法是在设置刻度标签之前添加 ax.set_xticks(xs)

import matplotlib.pyplot as pl
fig = pl.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
_ = ax.plot(xs, ys)
alph = list('abcdefghijklmnopqrstuvwxyz')
ax.set_xticks(xs)
ax.set_xticklabels(alph)
pl.savefig('ticklabels.png', dpi=300)

编辑:我建议以下内容来满足您对更通用解决方案的愿望:

from matplotlib.ticker import MaxNLocator
import matplotlib.pyplot as pl
import numpy as np

alph = list('abcdefghijklmnopqrstuvwxyz')
nticks = 8

fig, ax = pl.subplots()
xs = np.linspace(-10., 10., 100)
ys = np.polyval([1., 2., 3.], xs)

_ = ax.plot(xs, ys)

ax.xaxis.set_major_locator(MaxNLocator(nticks))
ax.set_xticklabels(alph[::int(len(alph)/nticks)])

pl.savefig('ticklabels.png', dpi=300)

您使用MaxNLocator 指定刻度数并通过切片将它们映射到字母表。

不过,我不确定 MaxNLocator 在准确返回所需的刻度数方面有多可靠。如 cmets 中所述,您可以简单地使用 len(ax.get_xticks()) 来获取滴答数。

【讨论】:

  • 谢谢丹尼尔。然而,正如我所提到的,我想保留用于确定应该有多少刻度以及间隔是多少的智能。在这个例子中,我不想要所有 26 个字母,只想要第一张图片中的 6 个,但它们应该是合适的。
  • 您想要一个更通用的解决方案,即将您的 x 范围映射到字母 a-z,还是始终拥有这 26 个 x 值?
  • 我想要一个更通用的解决方案。 x 轴上的值和图表的大小会发生变化。
  • 不使用MaxNLocator,你能不能简单地使用len(ax.get_xticks()),从而将tick数留给matplotlib?
  • 另外,使用FuncFormatter 和查找 x 刻度标签的函数是否有效?
【解决方案2】:

我认为最合适的解决方案是使用FuncFormatter,这将允许您查找所需的刻度标签值,并允许 matplotlib 确定刻度的位置和数量:

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, MaxNLocator
fig = plt.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
labels = list('abcdefghijklmnopqrstuvwxyz')


def format_fn(tick_val, tick_pos):
    if int(tick_val) in xs:
        return labels[int(tick_val)]
    else:
        return ''
ax.xaxis.set_major_formatter(FuncFormatter(format_fn))
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
ax.plot(xs, ys)
plt.show()

这会给你:

(感谢 Daniel Lenz 的指点和其他建议)。

注意:

正如 tcaswell 所述,xaxis.set_major_locator(MaxNLocator(integer=True)) 用于确保刻度仅放置在整数值处。

【讨论】:

  • 我建议还重新设置定位器给我一个MaxNLocator 并传入interger=True(或改变现有的就地)matplotlib.org/api/… 以确保你永远不会得到像这样的滴答声[1.0, 1.25, 1.5, 1.75, 2.0] 将前 4 个标记为“b”。
  • 这已经足够有用了,你愿意在 PR 中添加一个版本到 mpl 库吗?
  • 当然。添加了拉取请求 #5063。
猜你喜欢
  • 1970-01-01
  • 2019-10-29
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
相关资源
最近更新 更多