【问题标题】:Modify tick label text修改刻度标签文本
【发布时间】:2012-06-29 23:10:29
【问题描述】:

我想对图中的几个选定刻度标签进行一些修改。

例如,如果我这样做:

label = axes.yaxis.get_major_ticks()[2].label
label.set_fontsize(size)
label.set_rotation('vertical')

刻度标签的字体大小和方向已更改。

但是,如果尝试:

label.set_text('Foo')

刻度标签没有被修改。如果我这样做:

print label.get_text()

什么都没有打印出来。

这里还有一些奇怪的地方。当我尝试这个时:

 from pylab import *
 axes = figure().add_subplot(111)
 t = arange(0.0, 2.0, 0.01)
 s = sin(2*pi*t)
 axes.plot(t, s)
 for ticklabel in axes.get_xticklabels():
     print ticklabel.get_text()

仅打印空字符串,但绘图包含标记为“0.0”、“0.5”、“1.0”、“1.5”和“2.0”的刻度。

【问题讨论】:

  • 你能提供你用来获取标签的情节吗?
  • 您得到空白标签,因为您还没有绘制画布。如果您在尝试打印标签之前致电draw(),您将得到您所期望的。不幸的是,设置单个刻度标签有点困难(发生的事情是刻度定位器和格式化程序尚未重置,当您set_text 时它会覆盖事物)。如果有人没有击败我,我会稍后添加一个示例。不过,我现在必须赶公共汽车。
  • @JoeKington:太好了!期待看到您的修复。
  • @repoman - 好吧,看来我说得太早了。我想到的适用于旧版本的 matplotlib,但不适用于最新版本。我需要做更多的挖掘。话虽如此,这不应该那么复杂......

标签: python matplotlib


【解决方案1】:

你也可以用 pylabxticks

做到这一点
import matplotlib
import matplotlib.pyplot as plt
x = [0,1,2]
y = [90,40,65]
labels = ['high', 'low', 37337]
plt.plot(x,y, 'r')
plt.xticks(x, labels, rotation='vertical')
plt.show()

https://matplotlib.org/stable/gallery/ticks_and_spines/ticklabels_rotation.html

【讨论】:

  • 这是一个简单的解决方案,适用于 pyplot 1.5.1。这应该被赞成。
  • 虽然问题没有要求这个,但我很欣赏这个例子让你在修改标签的同时设置刻度的位置。
  • 来自现代matplotlib docs:“pylab 已被弃用,由于命名空间污染,强烈建议不要使用它。请改用 pyplot。”
【解决方案2】:

我注意到这里发布的所有使用set_xticklabels() 的解决方案都没有保留偏移量,这是一个应用于刻度值的比例因子,以创建更好看的刻度标签。例如,如果刻度在 0.00001 (1e-5) 的数量级上,matplotlib 将自动添加 1e-5 的比例因子(或 offset),因此生成的刻度标签可能最终为 1 2 3 4,而不是比1e-5 2e-5 3e-5 4e-5

下面举个例子:

x 数组是 np.array([1, 2, 3, 4])/1e6yy=x**2。所以两者都是非常小的值。

左栏:按照@Joe Kington 的建议手动更改第一个和第三个标签。请注意,偏移量会丢失。

中间列:类似于@iipr 建议的,使用FuncFormatter

右栏:我建议的保留偏移解决方案。

图在这里:

完整代码在这里:

import matplotlib.pyplot as plt
import numpy as np

# create some *small* data to plot
x = np.arange(5)/1e6
y = x**2

fig, axes = plt.subplots(1, 3, figsize=(10,6))

#------------------The set_xticklabels() solution------------------
ax1 = axes[0]
ax1.plot(x, y)
fig.canvas.draw()
labels = [item.get_text() for item in ax1.get_xticklabels()]

# Modify specific labels
labels[1] = 'Testing'
labels[3] = 'Testing2'
ax1.set_xticklabels(labels)
ax1.set_title('set_xticklabels()')

#--------------FuncFormatter solution--------------
import matplotlib.ticker as mticker

def update_ticks(x, pos):
    if pos==1:
        return 'testing'
    elif pos==3:
        return 'testing2'
    else:
        return x

ax2=axes[1]
ax2.plot(x,y)
ax2.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
ax2.set_title('Func Formatter')

#-------------------My solution-------------------
def changeLabels(axis, pos, newlabels):
    '''Change specific x/y tick labels

    Args:
        axis (Axis): .xaxis or .yaxis obj.
        pos (list): indices for labels to change.
        newlabels (list): new labels corresponding to indices in <pos>.
    '''

    if len(pos) != len(newlabels):
        raise Exception("Length of <pos> doesn't equal that of <newlabels>.")

    ticks = axis.get_majorticklocs()
    # get the default tick formatter
    formatter = axis.get_major_formatter()
    # format the ticks into strings
    labels = formatter.format_ticks(ticks)

    # Modify specific labels
    for pii, lii in zip(pos, newlabels):
        labels[pii] = lii

    # Update the ticks and ticklabels. Order is important here.
    # Need to first get the offset (1e-6 in this case):
    offset = formatter.get_offset()
    # Then set the modified labels:
    axis.set_ticklabels(labels)
    # In doing so, matplotlib creates a new FixedFormatter and sets it to the xaxis
    # and the new FixedFormatter has no offset. So we need to query the
    # formatter again and re-assign the offset:
    axis.get_major_formatter().set_offset_string(offset)

    return

ax3 = axes[2]
ax3.plot(x, y)

changeLabels(ax3.xaxis, [1, 3], ['Testing', 'Testing2'])
ax3.set_title('With offset')

fig.show()
plt.savefig('tick_labels.png')

警告:似乎使用 set_xticklabels() 的解决方案(包括我自己的解决方案)依赖于 FixedFormatter,它是静态的并且不响应图形大小调整。要观察效果,​​请将图形更改为较小的尺寸,例如fig, axes = plt.subplots(1, 3, figsize=(6,6)) 并放大图形窗口。您会注意到只有中间列响应调整大小并随着图形变大添加更多刻度。左右列将有空的刻度标签(见下图)。

警告 2:我还注意到,如果您的刻度值是浮点数,则直接调用 set_xticklabels(ticks) 可能会给您带来难看的字符串,例如 1.499999999998 而不是 1.5

【讨论】:

    【解决方案3】:

    试试这个:

      fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
      axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)
    

    【讨论】:

      【解决方案4】:

      如果您不使用 figax 并且想要修改所有标签(例如,用于标准化),您可以这样做:

      labels, locations = plt.yticks()
      plt.yticks(labels, labels/max(labels))
      
      

      【讨论】:

        【解决方案5】:

        这也适用于 matplotlib 3:

        x1 = [0,1,2,3]
        squad = ['Fultz','Embiid','Dario','Simmons']
        
        plt.xticks(x1, squad, rotation=45)
        

        【讨论】:

          【解决方案6】:

          这个问题被问到已经有一段时间了。截至今天(matplotlib 2.2.2),经过一些阅读和试验,我认为最好/正确的方法如下:

          Matplotlib 有一个名为 ticker 的模块,“包含支持完全可配置的刻度定位和格式化的类”。要修改图中的特定刻度,以下对我有用:

          import matplotlib.pyplot as plt
          import matplotlib.ticker as mticker
          import numpy as np 
          
          def update_ticks(x, pos):
              if x == 0:
                  return 'Mean'
              elif pos == 6:
                  return 'pos is 6'
              else:
                  return x
          
          data = np.random.normal(0, 1, 1000)
          fig, ax = plt.subplots()
          ax.hist(data, bins=25, edgecolor='black')
          ax.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
          plt.show()
          

          警告! x 是刻度的值,pos 是它在轴上的相对位置。请注意,pos 采用以 1 开头的值,而不是像往常一样在索引时以 0 开头。


          就我而言,我试图用百分比值格式化直方图的y-axismticker 有另一个名为 PercentFormatter 的类可以轻松完成此操作,而无需像以前那样定义单独的函数:

          import matplotlib.pyplot as plt
          import matplotlib.ticker as mticker
          import numpy as np 
          
          data = np.random.normal(0, 1, 1000)
          fig, ax = plt.subplots()
          weights = np.ones_like(data) / len(data)
          ax.hist(data, bins=25, weights=weights, edgecolor='black')
          ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1.0, decimals=1))
          plt.show()
          

          在这种情况下,xmax 是对应于 100% 的数据值。百分比计算为x / xmax * 100,这就是我们修复xmax=1.0 的原因。另外,decimals 是小数点后的小数位数。

          【讨论】:

            【解决方案7】:

            这行得通:

            import matplotlib.pyplot as plt
            
            fig, ax1 = plt.subplots(1,1)
            
            x1 = [0,1,2,3]
            squad = ['Fultz','Embiid','Dario','Simmons']
            
            ax1.set_xticks(x1)
            ax1.set_xticklabels(squad, minor=False, rotation=45)
            

            【讨论】:

              【解决方案8】:

              在较新版本的matplotlib 中,如果您不使用一堆str 值设置刻度标签,则默认情况下它们是''(绘制绘图时,标签只是刻度值) .知道这一点,要获得您想要的输出将需要这样的东西:

              >>> from pylab import *
              >>> axes = figure().add_subplot(111)
              >>> a=axes.get_xticks().tolist()
              >>> a[1]='change'
              >>> axes.set_xticklabels(a)
              [<matplotlib.text.Text object at 0x539aa50>, <matplotlib.text.Text object at 0x53a0c90>, 
              <matplotlib.text.Text object at 0x53a73d0>, <matplotlib.text.Text object at 0x53a7a50>, 
              <matplotlib.text.Text object at 0x53aa110>, <matplotlib.text.Text object at 0x53aa790>]
              >>> plt.show()
              

              结果:

              现在如果你检查_xticklabels,它们不再是一堆''

              >>> [item.get_text() for item in axes.get_xticklabels()]
              ['0.0', 'change', '1.0', '1.5', '2.0']
              

              它适用于从1.1.1rc1到当前版本2.0的版本。

              【讨论】:

              • 谢谢,这是我一直在寻找的答案。最清洁的解决方案 IMO;只需为 set_xticklabels 提供字符串和刻度对象的混合列表。
              • 请注意,如果刻度标签设置为整数,这会将它们更改为浮点数。很容易解决,但值得注意。
              • 这个有效 (ax.get_xticks().tolist())。投票最多的解决方案没有 (ax.get_xtickslabels())。尽管我按照建议使用了fig.canvas.draw(),但在执行plt.show() 之前它无法提取标签。
              • 仅供参考,来自现代matplotlib docs:“pylab 已被弃用,由于命名空间污染,强烈建议不要使用它。请改用 pyplot。”
              • 用户警告:FixedFormatter 只能与 FixedLocator 一起使用
              【解决方案9】:

              警告:除非刻度标签已经设置为字符串(例如箱线图通常是这种情况),否则这不适用于比1.1.0 更新的任何 matplotlib 版本。如果你在当前的 github master 上工作,这是行不通的。我还不确定问题出在哪里...可能是意外更改,也可能不是...

              通常,您会按照以下方式做一些事情:

              import matplotlib.pyplot as plt
              
              fig, ax = plt.subplots()
              
              # We need to draw the canvas, otherwise the labels won't be positioned and 
              # won't have values yet.
              fig.canvas.draw()
              
              labels = [item.get_text() for item in ax.get_xticklabels()]
              labels[1] = 'Testing'
              
              ax.set_xticklabels(labels)
              
              plt.show()
              

              要了解您需要跳过这么多圈的原因,您需要更多地了解 matplotlib 的结构。

              Matplotlib 故意避免对刻度等进行“静态”定位,除非明确告知。假设您希望与绘图进行交互,因此绘图的边界、刻度、刻度标签等将动态变化。

              因此,您不能只设置给定刻度标签的文本。默认情况下,每次绘制绘图时,它都会由轴的 Locator 和 Formatter 重新设置。

              但是,如果定位器和格式化程序设置为静态(分别为FixedLocatorFixedFormatter),则刻度标签保持不变。

              这就是set_*ticklabelsax.*axis.set_ticklabels 所做的。

              希望这可以更清楚地说明为什么更改单个刻度标签有点复杂。

              通常,您真正想要做的只是注释某个位置。在这种情况下,请改为查看 annotate

              【讨论】:

              • 这似乎不适用于当前版本 (1.20)!
              • 如果刻度标签已经设置为字符串,例如箱线图,这仍然有效。这可能很明显,但是由于答案的第一行是它不适用于较新的 matplotlib 版本,因此用户可能会完全跳过它(我最初是这样做的)。不妨简单提一下。
              • 我认为您可以将其浓缩为 plt.gca().set_xticklabels(labels)
              • 如果我希望“测试”的字体粗细为bold 而其他人使用“轻”的字体粗细。有办法吗?
              • 对于那些在 jupyter notebook 中使用它的人可能会受益于注意到fig.canvas.draw() 是至关重要的
              【解决方案10】:

              你可以这样做:

              for k in ax.get_xmajorticklabels():
                  if some-condition:
                      k.set_color(any_colour_you_like)
              
              draw()
              

              【讨论】:

              • 有人能解释一下为什么这个答案被严重否决吗?
              • @HlynurDavíðHlynsson 我认为这与问题无关。好吧,也许有一些编辑......请编辑它,如果你把它与问题联系起来。 ;)
              【解决方案11】:

              axes 类有一个set_yticklabels 函数,允许您设置刻度标签,如下所示:

              #ax is the axes instance
              group_labels = ['control', 'cold treatment',
                           'hot treatment', 'another treatment',
                           'the last one']
              
              ax.set_xticklabels(group_labels)
              

              我仍在研究为什么上面的示例不起作用。

              【讨论】:

              • 但我只想更改一个标签。上述技巧要求您提取所有刻度标签并将所需的标签设置为新值。但是当 label.get_text() 什么都不返回时,如何提取刻度标签?
              猜你喜欢
              • 1970-01-01
              • 2020-10-09
              • 2022-08-16
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多