在matplotlib中将x轴刻度标签居中对齐到刻度线之间

29

我希望x轴刻度日期标签居中于刻度线之间,而不是像下面的图片一样居中于刻度线。

我已经阅读了文档,但并没有成功-有人知道如何做到这一点吗?

enter image description here

如果有帮助,以下是我用于x轴刻度格式化的所有内容:

day_fmt = '%d'   
myFmt = mdates.DateFormatter(day_fmt)
ax.xaxis.set_major_formatter(myFmt)    
ax.xaxis.set_major_locator(matplotlib.dates.DayLocator(interval=1))     

for tick in ax.xaxis.get_major_ticks():
    tick.tick1line.set_markersize(0)
    tick.tick2line.set_markersize(0)
    tick.label1.set_horizontalalignment('center')
3个回答

28

一个方法是使用小刻度线。其思路是设置小刻度线位于相邻两个大刻度线的中间位置,并手动指定标签。

例如:

import matplotlib.ticker as ticker

# a is an axes object, e.g. from figure.get_axes()

# Hide major tick labels
a.xaxis.set_major_formatter(ticker.NullFormatter())

# Customize minor tick labels
a.xaxis.set_minor_locator(ticker.FixedLocator([1.5,2.5,3.5,4.5,5.5]))
a.xaxis.set_minor_formatter(ticker.FixedFormatter(['1','2','3','4','5']))
  • 隐藏主刻度上的1、2、3、4...等数字
  • 在主刻度之间设置次刻度(假设您的主刻度是1、2、3...)
  • 手动指定次刻度的标签。这里,“1”将位于图表上的1.0和2.0之间。

这只是一个简单的例子。您可能希望通过使用循环等方法来简化它。

您也可以尝试其他定位器或格式化程序

编辑: 或者,如评论中所建议的:

# Hide major tick labels
a.set_xticklabels('')

# Customize minor tick labels
a.set_xticks([1.5,2.5,3.5,4.5,5.5],      minor=True)
a.set_xticklabels(['1','2','3','4','5'], minor=True)

例子:

Before: Before

After: enter image description here


谢谢,我会尝试这个方法。有没有一种方法可以将已经存在的x轴刻度标签作为列表返回,以便我可以用于此?我已经查看了文档,但运气不太好。 - Osmond Bishop
1
a.xaxis.get_majorticklabels() 返回一个可迭代对象,您可以使用类似 for tl in a.xaxis.get_majorticklabels() 的语句进行循环。但请注意,这个列表的元素并不像您期望的那样是字符串,而是 matplotlib.text.Text 对象。要获取字符串,您需要使用类似 [tl.get_text() for tl in a.xaxis.get_majorticklabels()] 的语句。但重要的一点是,这些值直到绘图实际完成后才确定。因此,它们并不是获取标签的好方法。最好直接从数据中获取值。 - jedwards
我的x轴由半小时数据组成,因此我没有创建位置,而是添加了以下内容:ax.xaxis.set_minor_formatter(myFmt) ax.xaxis.set_minor_locator(matplotlib.dates.HourLocator(interval=12)) 并将我的主要格式化程序更改为您所做的方式,ax.xaxis.set_major_formatter(ticker.NullFormatter()) 但出于某种原因它并没有隐藏主要刻度标签,我可能还漏掉了其他什么吗? - Osmond Bishop
1
你可以通过使用 a.set_xticksa.set_xticklabels 更轻松地完成这个任务。两者都有一个可选的布尔参数叫做 minor,使它们影响到次要刻度线,例如 a.set_xticklabels(''); x.set_xticks([1.5,2.5,3.5,4.5,5.5],minor=True); a.set_xticklabels(['1','2','3','4','5'],minor=True) - Erik

3

这里有一种替代使用定位器和格式化程序的方法。它适用于标签之间的任何空格:

# tick_limit: the last tick position without centering (16 in your example)
# offset: how many steps between each tick (1 in your example)
# myticklabels: string labels, optional (range(1,16) in your example)

# need to set limits so the following works:
ax.xaxis.set_ticks([0, tick_limit]) 
# offset all ticks between limits:
ax.xaxis.set(ticks=np.arange(offset/2., tick_limit, offset), ticklabels=myticklabels)
# turn off grid
ax.grid(False)

由于这会修改主要刻度线,可能需要根据应用程序对网格进行调整。也可以通过使用ax.twinx()来解决此问题。这将导致将标签移动到单独轴的相反侧,但将保留原始网格并提供两个网格,一个用于原始刻度线,一个用于偏移。

编辑:

假设均匀间隔的整数刻度,这可能是最简单的方法:

ax.set_xticks([float(n)+0.5 for n in ax.get_xticks()])

0
一个简单的替代方法是使用水平对齐并通过添加空格来操作标签,如下面的 MWE 所示。
#python v2.7
import numpy as np
import pylab as pl
from calendar import month_abbr

pl.close('all')
fig1 = pl.figure(1)
pl.ion()

x = np.arange(120)
y = np.cos(2*np.pi*x/10)

pl.subplot(211)
pl.plot(x,y,'r-')
pl.grid()

new_m=[]
for m in month_abbr: #'', 'Jan', 'Feb', ...
 new_m.append('  %s'%m) #Add two spaces before the month name
new_m=np.delete(new_m,0) #remove first void element

pl.xticks(np.arange(0,121,10), new_m, horizontalalignment='left')
pl.axis([0,120,-1.1,1.1])

fig1name = './labels.png'
fig1.savefig(fig1name)

生成的图形:

Approximately centered tick labels


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,