我想对图中的一些选定刻度标签进行一些修改。
例如,如果我这样做:
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
时它会覆盖内容)。如果有人没有击败我,我会稍后添加一个示例。不过,我现在必须赶公共汽车。
警告:除非刻度标签已设置为字符串(如箱线图中通常的情况),否则这不适用于比 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()
https://i.stack.imgur.com/5m900.png
要了解您需要跳过这么多圈的原因,您需要更多地了解 matplotlib 的结构。
Matplotlib 故意避免对刻度等进行“静态”定位,除非明确告知。假设您希望与绘图进行交互,因此绘图、刻度、刻度标签等的边界将动态变化。
因此,您不能只设置给定刻度标签的文本。默认情况下,每次绘制绘图时,它都会由轴的定位器和格式化程序重新设置。
但是,如果定位器和格式化程序设置为静态(分别为 FixedLocator
和 FixedFormatter
),则刻度标签保持不变。
这就是 set_*ticklabels
或 ax.*axis.set_ticklabels
的作用。
希望这可以更清楚地说明为什么更改单个刻度标签有点复杂。
通常,您真正想要做的只是注释某个位置。在这种情况下,请改为查看 annotate
。
也可以使用 pylab 和 xticks 来做到这一点
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
在较新版本的 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()
https://i.stack.imgur.com/YiGb5.png
现在,如果您检查 _xticklabels
,它们不再是一堆 ''
。
>>> [item.get_text() for item in axes.get_xticklabels()]
['0.0', 'change', '1.0', '1.5', '2.0']
它适用于从 1.1.1rc1
到当前版本 2.0
的版本。
set_xticklabels
提供字符串和刻度对象的混合列表。
ax.get_xticks().tolist()
)。投票最多的解决方案没有 (ax.get_xtickslabels()
)。尽管我按照建议使用了 fig.canvas.draw()
,但它在执行 plt.show()
之前不知何故无法提取标签。
自从问这个问题以来已经有一段时间了。截至今天(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()
https://i.stack.imgur.com/AuRQR.png
警告! x
是刻度的值,pos
是它在轴上的相对位置。请注意,在索引时 pos
采用从 1
开始的值,而不是像往常一样在 0
中。
就我而言,我试图用百分比值格式化直方图的 y-axis
。 mticker
有另一个名为 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()
https://i.stack.imgur.com/PKy37.png
在这种情况下,xmax
是对应于 100% 的数据值。百分比计算为 x / xmax * 100
,这就是我们修复 xmax=1.0
的原因。此外,decimals
是小数点后的小数位数。
这有效:
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)
https://i.stack.imgur.com/qQx6q.png
坐标轴类有一个 set_yticklabels 函数,可让您设置刻度标签,如下所示:
#ax is the axes instance
group_labels = ['control', 'cold treatment',
'hot treatment', 'another treatment',
'the last one']
ax.set_xticklabels(group_labels)
我仍在研究为什么上面的示例不起作用。
这也适用于 matplotlib 3:
x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']
plt.xticks(x1, squad, rotation=45)
如果您不使用 fig
和 ax
并且想要修改所有标签(例如,为了标准化),您可以这样做:
labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))
尝试这个 :
fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)
我注意到这里发布的所有使用 set_xticklabels()
的解决方案都没有保留 offset,这是一个应用于刻度值的缩放因子,以创建更好看的刻度标签。例如,如果刻度在 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])/1e6
,y
是 y=x**2
。所以两者都是非常小的值。
左栏:按照@Joe Kington 的建议手动更改第一个和第三个标签。请注意,偏移量会丢失。
中间列:与@iipr 建议的类似,使用 FuncFormatter
。
右栏:我建议的保留偏移解决方案。
https://i.stack.imgur.com/ZZAOV.png
完整代码在这里:
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
。
https://i.stack.imgur.com/chgXN.png
你可以做:
for k in ax.get_xmajorticklabels():
if some-condition:
k.set_color(any_colour_you_like)
draw()
bold
而其他人使用“轻”的字体粗细怎么办。有没有办法做到这一点?fig.canvas.draw()
至关重要