2016-04-29 11 views
1

Ich sollte vorweg sagen, dass dies alles in einem iPython-Kernel getan wird, aber die einzigen Maßnahmen, die ich gemacht habe, sind der folgende Code.Matplotlib (Seaborn) set_xticks arbeitet unerwartet mit datetime und timedelta

I haben die folgende Tabelle, die durch den folgenden Code erzeugt wird:

from queries import TOTAL, DEMO, DB_CREDENTIALS, TOTAL_USA_EX, TOTAL_ESPN_EX 
import pandas as pd 
import pyodbc 
pd.options.mode.chained_assignment = None # default='warn'  
import seaborn as sns 
from matplotlib import pyplot as plt 
from datetime import datetime, timedelta 
mpl.rc('font',family='Arial Rounded MT Bold') 
y_label = {'fontsize':14} 
title = {'fontsize':30} 
s_legend = {'fontsize':14, 'handlelength':7} 

with pyodbc.connect(DB_CREDENTIALS) as cnxn: 
    df = pd.read_sql(sql=TOTAL_USA_EX, con=cnxn) 
    df['date'] = pd.to_datetime(df['date']) 
    df_e = pd.read_sql(sql=TOTAL_ESPN_EX, con=cnxn) 
    df_e['date'] = pd.to_datetime(df_e['date']) 

ex_ = df 
ex_['subject'] = ex_['date'] - ex_['date'].min() 
ex_['subject'] = ex_['subject'].apply(lambda x: x.days) 
ex_['hour'] = ex_['datetime'].apply(lambda x: x.hour) 
ex_['minute'] = ex_['datetime'].apply(lambda x: x.minute) 
ex_['minute'] = ex_['minute'] // 15 
ex_['qh'] = ex_.apply(lambda x: x['minute'] + (x['hour']*4), axis=1) 
ex_['imp'] = ex_['imp'].apply(lambda x: round(x/1000000.0,3)) 
ex_['station'] = 'USA' 

ex_e = df_e 
ex_e['subject'] = ex_e['date'] - ex_e['date'].min() 
ex_e['subject'] = ex_e['subject'].apply(lambda x: x.days) 
ex_e['hour'] = ex_e['datetime'].apply(lambda x: x.hour) 
ex_e['minute'] = ex_e['datetime'].apply(lambda x: x.minute) 
ex_e['minute'] = ex_e['minute'] // 15 
ex_e['qh'] = ex_e.apply(lambda x: x['minute'] + (x['hour']*4), axis=1) 
ex_e['imp'] = ex_e['imp'].apply(lambda x: round(x/1000000.0,3)) 
ex_e['station'] = 'ESPN' 

data = pd.concat([ex_, ex_e])   

fig, ax = plt.subplots() 
fig.set_size_inches(14, 7) 
sns.tsplot(time='qh', value='imp', unit='subject', condition='station', 
      ci=80, data=data, ax=ax, linewidth=2, color=["#21A0A0", "#E53D00"]) 
ax.set_ylabel('IMPRESSIONS (M)', **y_label) 
ax.set_xlabel('TIME', **y_label) 
ax.set_title('STATION IMPRESSIONS: 80% CONFIDENCE INTERVAL') 
ax.set_xticks([x for x in xrange(0,96,8)]) 
ax.set_xticklabels([(datetime(year=2015,month=12,day=28)+timedelta(minutes=15*(x))).strftime('%H:%M') for x in ax.get_xticks()]); 

Die x_ticks werden in Intervallen von 15 Minuten eingestellt, so dass das erwartete Verhalten Ticks eingestellt wäre bei jeder 2 Stunden increment (zB xticklabel[0] = 00:00, xticklabel[1] = 02:00, und so weiter).

jedoch aus irgendeinem Grund wird die folgende erzeugt:

Showing only time.

ich hinzufügen, das Datum und Monat unten, um zu sehen, was genau los ist, immer noch verwirrend.

Wrong graph, showing the dates are acting wonky.

So versuchte ich intuitiv, den Fehler zu erstellen, indem zu sehen, was passiert, wenn ich versuche, das Zecken-Objekt zuzugreifen, nachdem die ax erstellt und zu sehen, ob die Berechnung erfolgt immer, und es zeigt einig super verwirrend Verhalten :

In [19]: 
i = ax.get_xticks() 
[(timedelta(minutes=15*(j)), j) for j in i ] 

Out [19]: 
[(datetime.timedelta(0), 0), 
(datetime.timedelta(-1, 85010, 65408), 8), 
(datetime.timedelta(0, 1515, 98112), 16), 
(datetime.timedelta(0, 125, 163520), 24), 
(datetime.timedelta(-1, 85135, 228928), 32), 
(datetime.timedelta(0, 1640, 261632), 40), 
(datetime.timedelta(0, 250, 327040), 48), 
(datetime.timedelta(-1, 85260, 392448), 56), 
(datetime.timedelta(0, 1765, 425152), 64), 
(datetime.timedelta(0, 375, 490560), 72), 
(datetime.timedelta(-1, 85385, 555968), 80), 
(datetime.timedelta(0, 1890, 588672), 88)] 

Für meinen Verstand, was ist i?

In [20]: 
i 
Out [20]: 
array([ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88]) 

So öffne ich einen separaten Kernel in jupyter und sehen, ob ich die gleichen Fehler in einem Vakuum replizieren kann. Und ich bin nicht in der Lage:

neuen Kernel

In [1]: 
from datetime import datetime, timedelta 
i = [x*15 for x in xrange(0,96,8)] 
[timedelta(minutes=x) for x in i] 

Out [1]: 
[datetime.timedelta(0), 
datetime.timedelta(0, 7200), 
datetime.timedelta(0, 14400), 
datetime.timedelta(0, 21600), 
datetime.timedelta(0, 28800), 
datetime.timedelta(0, 36000), 
datetime.timedelta(0, 43200), 
datetime.timedelta(0, 50400), 
datetime.timedelta(0, 57600), 
datetime.timedelta(0, 64800), 
datetime.timedelta(0, 72000), 
datetime.timedelta(0, 79200)] 

mir jemand hier aus gehen verrückt helfen?

Zwei schnelle Änderungen:

1) Das Datum 2015.12.28 völlig willkürlich ist, ich das Datum nicht brauchen Ich brauche nur die Zeit mit ihr verbunden ist, um meine Achse. Ein beliebiges Datum würde ausreichen, aber hier sollte es keine Rolle spielen angesichts des Verhaltens, das ich erwarte.

2) Nur um sicherzustellen, dass es nicht irgendeine Art von seltsamem Syntaxfehler war, ähnlich wie in dem neuen Kernel das funktioniert gut:

In [2]: 
from datetime import datetime, timedelta 
i = [x for x in xrange(0,96,8)] 
[timedelta(minutes=(x)*15) for x in i] 
Out [2]: 
[datetime.timedelta(0), 
datetime.timedelta(0, 7200), 
datetime.timedelta(0, 14400), 
datetime.timedelta(0, 21600), 
datetime.timedelta(0, 28800), 
datetime.timedelta(0, 36000), 
datetime.timedelta(0, 43200), 
datetime.timedelta(0, 50400), 
datetime.timedelta(0, 57600), 
datetime.timedelta(0, 64800), 
datetime.timedelta(0, 72000), 
datetime.timedelta(0, 79200)] 

Antwort

0

Dank im #learnprogramming Kanal darkf; Dies wird durch den Typ des Artikels verursacht, der von der ax.get_xticks()-Methode zurückgegeben wird, die numpy.int32 ist; Es ist also wahrscheinlich, dass eine Zeigerreferenz und nicht der tatsächliche Int zurückgegeben wird.

Korrigierte Codezeile:

x.set_xticklabels([(datetime(year=2015,month=12,day=28)+timedelta(minutes=15*(int(x)))).strftime('%H:%M') for x in ax.get_xticks()]); 

und Grafik:

enter image description here

Dank!

Verwandte Themen