2015-07-06 11 views
7

Poniżej Mam następujący skrypt, który tworzy prosty szeregów czasowych działki:Seaborn tsplot nie pokazuje datetimes na X osi studni

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

a wynik ten jest następujący:

enter image description here

Jak widać oś X zawiera dziwne liczby dla dat, które nie są zwykłymi "ładnymi" reprezentacjami, które pochodzą z matplotlib i innych narzędzi do kreślenia. Próbowałem już wielu rzeczy, zmieniając format danych, ale nigdy nie wychodzi na jaw. Ktoś zna drogę?

Odpowiedz

8

Matplotlib reprezentuje daty w liczbach zmiennoprzecinkowych (w dniach), więc jeśli nie (lub pandy lub seaborn), powiedz, że twoje wartości reprezentują daty, to nie będzie formatować tyknięć jako dat. Nie jestem ekspertem od seabornów, ale wygląda na to, że to on (lub pandy) konwertuje obiekty datetime na daty matplotlib, ale potem nie przypisuje do osi odpowiednich lokalizatorów i formaterów. To dlatego otrzymujesz te dziwne numery , które są w rzeczywistości tylko dniami od 0001.01.01. Musisz więc zająć się kleszczami ręcznie (co w większości przypadków jest lepsze, ponieważ daje ci większą kontrolę).

Musisz więc przypisać kod date locator, który decyduje o tym, gdzie umieścić znaczniki, oraz date formatter, który następnie sformatuje ciągi znaków dla etykiet.

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

Wynik:

enter image description here

+2

otrzymuję ten błąd: OverflowError: Python int zbyt duży do konwersji C długich – kurious

+0

działa na moim boku. Czy używasz mojego dokładnego przykładu? Może musisz zaktualizować swoją dystrybucję. – hitzg

+2

@kurious: Otrzymuję coś podobnego: 'OverflowError: liczba całkowita ze znakiem jest większa niż maksymalna' od matplotlib/dates.pyc (linia 214) w _from_ordinalf (x, tz). Po prostu zainstaluj pip na Linuksie z Pythonem 2.7. –

7

Dla mnie @ hitzg za wyniki odpowiedź w "OverflowError: podpisana liczba całkowita jest większa niż maksimum" w głębi dateFormatter.

Patrząc na moją ramkę danych, moje indeksy są datetime64, a nie datetime. Pandy dobrze to jednak konwertują. Następujące prace wielki dla mnie:

import matplotlib as mpl 

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

[ . . . ] 

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

A jak możemy to sformatować? 'ax.xaxis.set_major_formatter (mdates.DateFormatter ('% Y.% m.% D'))' nie będzie działać. – MERose