2017-08-16 131 views
0

我有一個腳本,它使用matplotlib的plot_date()函數將查詢結果轉換爲時間序列可視化。它曾經運作良好,但在某些時候(不確定爲什麼)日期開始表現出色。Matplotlib plot_date x軸標籤關閉了幾天,部分丟失

這裏的底層數據:

0 = {list} <type 'list'>: [u'2017-07-03', 427] 
1 = {list} <type 'list'>: [u'2017-07-10', 201] 
2 = {list} <type 'list'>: [u'2017-07-17', 594] 
3 = {list} <type 'list'>: [u'2017-07-24', 525] 
4 = {list} <type 'list'>: [u'2017-07-31', 239] 
5 = {list} <type 'list'>: [u'2017-08-07', 437] 

下面的代碼生成圖形:

def generate_timeseries(values, **kwargs): 
    x_values = [] 
    y_values = [] 
    for item in values['rows']: 
     x_values.append(datetime.strptime(item[0], "%Y-%m-%d")) 
     y_values.append(item[1]) 

    # General Figure 
    figure = plt.figure() 
    low = min(y_values) 
    high = max(y_values) 
    plt.ylim([0, math.ceil(high + 0.4 * (high - low))]) 
    figure.set_size_inches(kwargs['chart_size'][0], kwargs['chart_size'][1], forward=True) 
    plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1) 

    # General Axis 
    axis = figure.add_subplot(1, 1, 1) 
    axis.spines["top"].set_visible(False) 
    axis.spines["right"].set_visible(False) 

    # Y-Axis 
    axis.get_yaxis().tick_left() 
    axis.yaxis.label.set_color('gray') 
    axis.yaxis.grid() 
    if kwargs['show_axis_labels']: 
     axis.set_ylabel(kwargs['y_label']) 

    # X-Axis 
    axis.get_xaxis().tick_bottom() 
    axis.xaxis.label.set_color('gray') 
    if kwargs['show_axis_labels']: 
     axis.set_xlabel(kwargs['x_label']) 
    axis.xaxis.set_major_formatter(DateFormatter(kwargs.get('date_format', '%Y-%m-%d'))) 

    plt.plot_date(x_values, 
        y_values, 
        linestyle='-', 
        color=kwargs['palette'][0], 
        marker='o' if kwargs['marker'] else None, 
        linewidth=1.6, 
        clip_on=False) 

    if kwargs['show_datapoint_labels']: 
     for xy_comb in zip(x_values, y_values): 
      axis.annotate('{}'.format(xy_comb[1]), xy_comb, 
          xycoords='data', 
          xytext=(2, 10), 
          textcoords='offset points') 

    if kwargs['show_legend']: 
     plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), fancybox=True, fontsize=6) 

    return plt 

最後但並非最不重要的,這裏的圖是如何變成了: enter image description here

請注意:

  1. 有6個數據點,但只有5日期標籤可見
  2. 似乎是

我已經驗證了plot_date()功能之前輸入的日期5天的轉變;我已經驗證了數據的時區(這不能解釋爲期5天的轉變,但仍然)。我嘗試過基於here建議的格式化和操作日期的不同變化,但似乎沒有任何方法可以解決問題。

有沒有人遇到類似的問題,或者可以在我的代碼中發現問題?我花了幾個小時試圖調試/研究,覺得我迄今沒有得到任何地方。

[Matplotlib V2.0.2; Python 2.7.13]

+0

究竟什麼是* *的問題?你展示的情節似乎是完全正確的,標籤的位置也是正確的。如果你想將你的標籤放在不同的位置,你需要確切地知道你想要的位置。 – ImportanceOfBeingErnest

+0

正如我最初寫的 - 我錯過了1個標籤,其他人沒有與數據點對齊(沒有到位,也沒有日期) –

+0

所以你想在每個數據點的位置有一個標籤,並且沒有在沒有被數據點佔據的位置上的標籤? (我想這很明顯,這個要求並不是默認的,因爲如果繪製了200個點,那麼它會生成200個標籤,而且肯定是不希望的。) – ImportanceOfBeingErnest

回答

1

要將刻度位置固定爲數據點所在的日期,您需要使用Locator和Formatter。

定位符應該是matplotlib.ticker.FixedLocator,它根據輸入數據設置位置。格式化程序可以是任何matplotlib.dates格式化程序。

data = [[u'2017-07-03', 427], 
     [u'2017-07-10', 201], 
     [u'2017-07-17', 594], 
     [u'2017-07-24', 525], 
     [u'2017-07-31', 239], 
     [u'2017-08-07', 437]] 

import matplotlib.pyplot as plt 
import matplotlib.dates 
import matplotlib.ticker 
import datetime 

x,y = zip(*data) 
f = lambda s: datetime.datetime.strptime(s, '%Y-%m-%d') 
x = list(map(f, x)) 

fig, ax = plt.subplots() 
ax.plot(x,y) 

loc = matplotlib.ticker.FixedLocator(matplotlib.dates.date2num(x)) 
fmt = matplotlib.dates.DateFormatter('%Y-%m-%d') 
ax.xaxis.set_major_locator(loc) 
ax.xaxis.set_major_formatter(fmt) 

fig.autofmt_xdate() 
plt.show() 

enter image description here

0

這應該說清楚,沒有與plot_date沒有問題。我認爲問題在於,您預計首發滴答聲將與您的起始數據保持一致,而不是按照包含數據的等間隔排列。 (編輯:我確實看到你的數據每週都有間隔)。您可以使用Locator子類來操縱xtick位置。

import datetime 
import matplotlib as mpl 
from matplotlib import pyplot as plt 

import numpy 

old_data = [ 
    ['2017-07-03', 427], 
    ['2017-07-10', 201], 
    ['2017-07-17', 594], 
    ['2017-07-24', 525], 
    ['2017-07-31', 239], 
    ['2017-08-07', 437], 
] 

data = [] 
for i in old_data: 
    d = datetime.datetime.strptime(i[0], '%Y-%m-%d') 
    data.append([d,i[1]]) 

data = numpy.array(data) 

fig, ax = plt.subplots(figsize=(8,3)) 
locator = mpl.dates.DayLocator() 
ax.xaxis.set_major_locator(locator) 
ax.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y-%m-%d')) 
ax.grid(True) 

_=ax.plot_date(data[:,0], data[:,1],linestyle='-') 
for tick in ax.get_xticklabels(): 
    tick.set_rotation(270) 
# fig.savefig("date_plot.png") 

enter image description here