2015-07-06 8 views
7

Sotto ho il seguente script che crea un semplice grafico temporale:Seaborn tsplot non mostra datetimes su asse x ben

%matplotlib inline 
import datetime 
import pandas as pd 
import seaborn as sns 
import matplotlib.pyplot as plt 

fig, ax = plt.subplots() 

df = [] 
start_date = datetime.datetime(2015, 7, 1) 
for i in range(10): 
    for j in [1,2]: 
     unit = 'Ones' if j == 1 else 'Twos' 
     date = start_date + datetime.timedelta(days=i) 

     df.append({ 
       'Date': date.strftime('%Y%m%d'), 
       'Value': i * j, 
       'Unit': unit 
      }) 

df = pd.DataFrame(df) 

sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax) 
fig.autofmt_xdate() 

E il risultato di questo è la seguente:

enter image description here

Come si può vedere l'asse x ha numeri strani per i datet e non le solite rappresentazioni "belle" fornite con matplotlib e altri programmi di utilità di stampa. Ho provato molte cose, riformattando i dati ma non risulta mai pulito. Qualcuno sa come muoversi?

risposta

8

Matplotlib rappresenta le date come numeri in virgola mobile (in giorni), quindi a meno che tu (o panda o marino) non dica che i tuoi valori rappresentano date, non formatterà i tick come date. Non sono un esperto in mare, ma sembra che (o panda) converta gli oggetti datetime in date matplotlib, ma poi non assegna localizzatori e formattatori appropriati agli assi. Ecco perché ottieni questi numeri strani, che sono in realtà solo i giorni dal 0001.01.01. Quindi dovrai prenderti cura dei tick manualmente (il che, nella maggior parte dei casi, è comunque migliore in quanto ti dà più controllo).

Quindi sarà necessario assegnare uno date locator, che decide dove inserire i segni di graduazione e uno date formatter, che formatterà quindi le stringhe per le etichette di graduazione.

import datetime 
import pandas as pd 
import seaborn as sns 
import matplotlib.pyplot as plt 
import matplotlib.dates as mdates 

# build up the data 
df = [] 
start_date = datetime.datetime(2015, 7, 1) 
for i in range(10): 
    for j in [1,2]: 
     unit = 'Ones' if j == 1 else 'Twos' 
     date = start_date + datetime.timedelta(days=i) 

     # I believe it makes more sense to directly convert the datetime to a 
     # "matplotlib"-date (float), instead of creating strings and then let 
     # pandas parse the string again 
     df.append({ 
       'Date': mdates.date2num(date), 
       'Value': i * j, 
       'Unit': unit 
      }) 
df = pd.DataFrame(df) 

# build the figure 
fig, ax = plt.subplots() 
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax) 

# assign locator and formatter for the xaxis ticks. 
ax.xaxis.set_major_locator(mdates.AutoDateLocator()) 
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y.%m.%d')) 

# put the labels at 45deg since they tend to be too long 
fig.autofmt_xdate() 
plt.show() 

Risultato:

enter image description here

+2

ottengo questo errore: OverflowError: Python int troppo grande per convertire in C lunghe – kurious

+0

Opere dalla mia parte. Usi il mio esempio esatto? Forse hai bisogno di aggiornare la tua distribuzione. – hitzg

+2

@kurious: Sto ottenendo qualcosa di simile: 'OverflowError: intero con segno è maggiore del massimo' da matplotlib/dates.pyc (riga 214) in _from_ordinalf (x, tz). Solo pip installato su Linux con Python 2.7. –

7

Per me, i risultati risposta di @ hitzg in "OverflowError: firmato intero è maggiore di massima" nelle profondità di DateFormatter.

Guardando il mio dataframe, i miei indici sono datetime64, non datetime. Panda li converte benissimo però. I seguenti grandi opere per me:

import matplotlib as mpl 

def myFormatter(x, pos): 
    return pd.to_datetime(x) 

[ . . . ] 

ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter)) 
+0

E poi come possiamo formattarlo? 'ax.xaxis.set_major_formatter (mdates.DateFormatter ('% Y.% m.% D'))' non funzionerà. – MERose

Problemi correlati