2012-03-11 8 views
5

Ho cercato di creare grafici contro il tempo sull'asse x e di averlo più o meno ordinato, con uno strano accenno che mi fa pensare se ho eseguito in un bug o (presumibilmente molto più probabile) sto facendo qualcosa che non capisco davvero.Impostazione manuale di xticks con xaxis_date() in Python/matplotlib

In poche parole, di seguito è una versione semplificata del mio programma. Se lo metto in un file .py e lo eseguo da un interprete (ipython) ottengo una figura con un asse x con solo l'anno, "2012", ripetuto un numero di volte, like this.

Tuttavia, se commento la riga (40) che imposta manualmente i xticks, cioè 'plt.xticks (tk)' e poi eseguo quel comando esatto nell'interprete subito dopo l'esecuzione dello script, funziona alla grande e il mio la figura sembra like this.

Analogamente, funziona anche se ho appena spostato quella riga dopo il comando savefig nello script, cioè per metterla alla fine del file. Ovviamente in entrambi i casi solo la figura disegnata sullo schermo avrà l'asse desiderato e non il file salvato. Perché non posso impostare il mio asse x prima?

Grato per eventuali approfondimenti, grazie in anticipo!

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

risposta

5

Non penso che sia necessario quella chiamata a xaxis_date(); dato che stai già fornendo i dati sull'asse x in un formato che matplotlib sa come gestire. Penso anche che ci sia qualcosa di leggermente sbagliato nella tua formula secs.

Possiamo fare uso di formattatori e localizzatori built-in di matplotlib a:

  1. impostare i principali xticks ad intervalli regolari (minuti, ore, giorni, ecc)
  2. personalizzare la visualizzazione utilizzando un strftime di formattazione

sembra che se un formattatore non è specificato, il valore predefinito è per visualizzare l'anno; che è quello che stavi vedendo.

Prova questo fuori:

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

Risultato:

enter image description here

FWIW la funzione di utilità larger_alim stato originariamente scritto per quest'altra domanda: Is there a way to tell matplotlib to loosen the zoom on the plotted data?

Problemi correlati