修改刻度标签文本

时间:2012-06-28 12:20:00

标签: python matplotlib

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

例如,如果我这样做:

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”的刻度。

11 个答案:

答案 0 :(得分:225)

警告:除非ticklabels已经设置为字符串(例如在boxplot中通常就是这种情况),否则这不适用于比1.1.0更新的任何matplotlib版本。如果你是从当前的github主人那里工作的,那就不行了。我不确定问题是什么......这可能是一次意外的改变,或者可能不是......

通常情况下,您可以按照以下方式做点什么:

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()

enter image description here

要理解为什么需要跳过这么多箍,你需要更多地了解matplotlib的结构。

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

因此,您无法设置给定刻度标签的文本。默认情况下,每次绘制绘图时都会由轴的定位器和格式化程序重新设置。

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

这是set_*ticklabelsax.*axis.set_ticklabels的作用。

希望这更清楚地说明为什么更改单个刻度标签有点令人费解。

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

答案 1 :(得分:77)

在较新版本的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()

结果: enter image description here

现在,如果您查看_xticklabels,则它们不再是''的一堆。

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

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

答案 2 :(得分:69)

也可以使用 pylab xticks

来做到这一点
import pylab 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()

http://matplotlib.org/examples/ticks_and_spines/ticklabels_demo_rotation.html

答案 3 :(得分:10)

轴类具有set_yticklabels功能,允许您设置刻度标签,如下所示:

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

ax.set_xticklabels(group_labels)

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

答案 4 :(得分:5)

这有效:

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)

FEDS

答案 5 :(得分:5)

问这个问题已经有一段时间了。截止到今天(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()

Histogram with random values from a normal distribution

注意!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()

Histogram with random values from a normal distribution

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

答案 6 :(得分:3)

这在matplotlib 3中也适用:

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

plt.xticks(x1, squad, rotation=45)

答案 7 :(得分:1)

尝试一下:

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

答案 8 :(得分:0)

如果您不使用figax,并且想要修改所有标签(例如为了规范化),则可以执行以下操作:

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

答案 9 :(得分:0)

我注意到这里发布的所有使用set_xticklabels()的解决方案都没有保留偏移量,这是应用于刻度值以创建外观更好的刻度标签的比例因子。例如,如果价格变动幅度约为0.00001(1e-5),则matplotlib将自动添加offset的缩放因子(或1e-5),因此最终的价格变动标签可能最终以{ {1}},而不是1 2 3 4

下面举一个例子:

1e-5 2e-5 3e-5 4e-5数组是x,而np.array([1, 2, 3, 4])/1e6y。所以两者都是很小的值。

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

中间列:类似于@iipr建议,使用y=x**2

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

图在这里: enter image description here

在此处填写代码:

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并放大图形窗口。您会注意到,只有中间列会响应调整大小,并且随着数字变大,会增加更多的刻度。左列和右列将具有空的刻度标签(请参见下图)。

注意事项2 :我还注意到,如果您的刻度值是浮点型的,则直接调用fig, axes = plt.subplots(1, 3, figsize=(6,6))可能会给您带来难看的字符串,例如set_xticklabels(ticks)而不是{{1 }}。

enter image description here

答案 10 :(得分:-4)

你可以这样做:

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

draw()