在Python / matplotlib中使用xaxis_date()手动设置xticks

时间:2012-03-11 00:20:27

标签: python matplotlib

我一直在研究如何在x轴上制作与时间相关的情节,并对其进行了相当多的排序,有一个奇怪的怪癖让我想知道我是否遇到过一个错误或者(更确切地说是)做一些我真不理解的事情。

简单地说,下面是我的程序的简化版本。如果我把它放在一个.py文件中并从解释器(ipython)执行它,我会得到一个x轴只有年份的数字,“2012”,重复了很多次,like this

但是,如果我注释掉手动设置xticks的行(40),即'plt.xticks(tk)',然后在执行脚本后立即在解释器中运行该命令,那么它很有效,我的身材看起来like this

同样,如果我只是将该行移动到脚本中的savefig命令之后也可以工作,也就是说将它放在文件的最末端。当然,在这两种情况下,只有屏幕上绘制的图形才会有所需的轴,而不是保存的文件。为什么我不能提前设置我的x轴?

感谢任何见解,提前谢谢!

import matplotlib.pyplot as plt 
import datetime

# define arrays for x, y and errors
x=[16.7,16.8,17.1,17.4]
y=[15,17,14,16]
e=[0.8,1.2,1.1,0.9]

xtn=[]

# convert x to datetime format
for t in x:
   hours=int(t)
   mins=int((t-int(t))*60)
   secs=int(((t-hours)*60-mins)*60)
   dt=datetime.datetime(2012,01,01,hours,mins,secs)
   xtn.append(date2num(dt))

# set up plot
fig=plt.figure()
ax=fig.add_subplot(1,1,1)

# plot
ax.errorbar(xtn,y,yerr=e,fmt='+',elinewidth=2,capsize=0,color='k',ecolor='k')

# set x axis range
ax.xaxis_date()
t0=date2num(datetime.datetime(2012,01,01,16,35)) # x axis startpoint
t1=date2num(datetime.datetime(2012,01,01,17,35)) # x axis endpoint
plt.xlim(t0,t1) 

# manually set xtick values 
tk=[]
tk.append(date2num(datetime.datetime(2012,01,01,16,40)))
tk.append(date2num(datetime.datetime(2012,01,01,16,50)))
tk.append(date2num(datetime.datetime(2012,01,01,17,00)))
tk.append(date2num(datetime.datetime(2012,01,01,17,10)))
tk.append(date2num(datetime.datetime(2012,01,01,17,20)))
tk.append(date2num(datetime.datetime(2012,01,01,17,30)))
plt.xticks(tk)

plt.show()

# save to file
plt.savefig('savefile.png')

1 个答案:

答案 0 :(得分:5)

我认为您不需要拨打xaxis_date();因为您已经以matplotlib知道如何处理的格式提供x轴数据。我还认为你的secs公式存在一些问题。

我们可以使用matplotlib的内置格式化程序和定位器来:

  1. 将主要xticks设置为常规间隔(分钟,小时,天等)
  2. 使用strftime格式字符串
  3. 自定义显示

    如果未指定格式化程序,则默认显示年份;这就是你所看到的。

    试试这个:

    import datetime as dt
    import matplotlib.pyplot as plt
    from matplotlib.dates import DateFormatter, MinuteLocator
    
    x = [16.7,16.8,17.1,17.4]
    y = [15,17,14,16]
    e = [0.8,1.2,1.1,0.9]
    xtn = []
    for t in x:
      h = int(t)
      m = int((t-int(t))*60)
      xtn.append(dt.datetime.combine(dt.date(2012,1,1), dt.time(h,m)))
    
    def larger_alim( alim ):
      ''' simple utility function to expand axis limits a bit '''
      amin,amax = alim
      arng = amax-amin
      nmin = amin - 0.1 * arng
      nmax = amax + 0.1 * arng
      return nmin,nmax
    
    plt.errorbar(xtn,y,yerr=e,fmt='+',elinewidth=2,capsize=0,color='k',ecolor='k')
    plt.gca().xaxis.set_major_locator( MinuteLocator(byminute=range(0,60,10)) )
    plt.gca().xaxis.set_major_formatter( DateFormatter('%H:%M:%S') )
    plt.gca().set_xlim( larger_alim( plt.gca().get_xlim() ) )
    plt.show()
    

    结果:

    enter image description here

    FWIW实用程序函数larger_alim最初是针对其他问题编写的:Is there a way to tell matplotlib to loosen the zoom on the plotted data?