2017-03-07 26 views
1

我有一個時間序列,我想有2個x軸,1顯示數據索引和一個它是相應的時間戳。一種方法是使用plt.plot_date,然後再對照索引進行繪圖。但是:2 x軸,1的索引和1使用時間戳點,相同的y

  1. 必須有一個更好的方式來做到這一點
  2. 對日期是不是撿了所有的數據(你可以看到下面的「空白」)的情節。

dataplot vs indexplot.

紅色是日期情節,藍色的指數圖。

  • 有沒有我可以在最初設定的「日期」的方式X軸等於 「指數」 x軸,然後更改刻度標記到相應的 日期?

  • 你也知道爲什麼我在使用 plt.plot_date時可能會出現間隙行爲嗎?

時間戳

原始格式爲在strarray(['2017-02-14 05:48:00', '2017-02-14 05:49:00', '2017-02-14 05:50:00', '2017-02-14 05:51:00', '2017-02-14 05:52:00', '2017-02-14 05:53:00',...]

x = [dt.datetime.strptime(d,'%Y-%m-%d %H:%M:%S') for d in dates_test] 
x = [mdates.date2num(i) for i in x] 
fig, ax = plt.subplots(nrows=3, figsize=(8, 6), sharex = True) 

ax[0].plot(xaxis, errors) 
ax4 = ax[0].twiny() 
ax4.plot_date(x, errors, fmt="r-") 
ax4.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m \n%H:%M')) 
+0

你可以嘗試[編輯蜱(http://matplotlib.org/examples/ticks_and_spines/tick-formatters.html)到你想要的值,[這個例子]( http://matplotlib.org/examples/axes_grid/demo_parasite_axes2.html)可能是有用的 – berna1111

+0

此外,對日期的陰謀似乎在收集所有的數據,它只是沒有像對抗指數,但聚集在幾個日期。你確定時間戳是全部等間隔和正確轉換? – berna1111

+0

@ berna1111感謝您的回覆。我不認爲在這種情況下提到的例子有幫助。 ii)這是一個好點。時間戳不是等間隔的,但這只是它們的方式。這就是爲什麼我想用它們作爲刻度標籤,而不是實際的刻度。 – ninjaSurfer

回答

0

產生類似的數據到你的後:

import numpy as np 
import matplotlib.pyplot as plt 
plt.ioff() 
import matplotlib.dates as mdates 
import datetime as dt 
import time 

# --- Build date blocks --- 
now = time.time() # first time 
delta_time = 60 # distance between points in seconds 

n_jumps = 10 # number of pieces with no data 
avg_jump_size = 60*60*24 # 86400 s = 1 day 
jumps = abs(np.random.normal(avg_jump_size/2., 
          avg_jump_size/2, 
          n_jumps+1)) + avg_jump_size/2. 
# `abs` just to make sure the jump is positive, and ` + avg_jump_size/2.` to 
# make sure it's larger than the time step. 

avg_n_poins_per_block = 2*60*60/delta_time # 2 hours of acquisition per block 
blocks_sizes = abs(np.random.normal(avg_n_poins_per_block/2., 
            avg_n_poins_per_block/2., 
            n_jumps+1)) + avg_n_poins_per_block/2. 

times = np.array([]) # array to place all dates 
for i in range(n_jumps): 
    block = np.arange(now, now+delta_time*blocks_sizes[i], delta_time) 
    times = np.concatenate((times, block)) 
    now += jumps[i] 
# last block 
block = np.arange(now, now+delta_time*blocks_sizes[-1], delta_time) 
times = np.concatenate((times, block)) 

def time2mdate_str(number=None): 
    """ 
    Convert a time given by `time.time()` to a `datetime` instance 
    from `matplotlib.mdate`. 
    """ 
    if number is None: 
     number = time.time() 
    # time.time() returns the number of seconds since the Epoch 
    # (1970-01-01 00:00:00). 
    # But mdate represents time in days since 0001-01-01 00:00:00, plus 1 day. 
    # (http://matplotlib.org/api/dates_api.html) 
    # So we convert to days: 
    number /= 60*60*24 
    # and then we add the 1969 years: 
    # http://www.rapidtables.com/calc/time/days-in-year.htm 
    number += 1969*365.2425 
    # and now it should be off by only (!) ~11h (close enough) 
    a = mdates.num2date(number) 
    return a 

# list of time strings: 
dates_test = [time2mdate_str(t).strftime("%Y-%m-%d %H:%M:%S") for t in times] 
# some random data: 
errors = np.random.normal(0.025, 0.01, len(times)) 
xaxis = np.arange(len(errors)) # omiter 

# Original code: 
x = [dt.datetime.strptime(d,'%Y-%m-%d %H:%M:%S') for d in dates_test] 
x = [mdates.date2num(i) for i in x] 
fig, ax = plt.subplots(nrows=3, figsize=(8, 6), sharex = True) 

ax[0].plot(xaxis, errors) 
ax4 = ax[0].twiny() 
ax4.plot_date(x, errors, fmt="r-") 
ax4.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m \n%H:%M')) 

fig.tight_layout() 
fig.show() 

enter image description here

我首先想到的是分隔每個數據塊(你還可以減去初始小時,有第一x值是00:00):

# break into blocks: 
x = np.array(x) 
deltas = x[1:] - x[:-1] 
# assume there's no break right after the first value and 
# find where the difference between consecutive times is larger 
# than 1.1*deltas[0] (margin of 1.1* for float comparison) 
break_indexes = np.where(deltas > deltas[0]*1.1)[0]+1 
# add borders (will be useful for iterating over the list): 
break_indexes = np.concatenate(([0],break_indexes,[-1])) 
n_jumps = len(break_indexes) - 1 
# offset to make sure each line does not overlap with another: 
offset = 1.5*np.max(errors) 

fig2, ax2 = plt.subplots(figsize=(8, 6)) 
for i in range(n_jumps): 
    i_0 = break_indexes[i] 
    slice_ = slice(i_0, break_indexes[i+1]) 
    ax2.plot(x[slice_]-x[i_0]+x[0], errors[slice_]+offset*i, label=dates_test[i_0]) 
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) 
ax2.set_xlim(x[0]) 
ax2.legend() 

fig2.tight_layout() 
fig2.show() 

Pieces separated

然後,我還以爲你會發現它有用每次使用塊的開始爲蜱雖然這可能會導致標籤的疊加:

# use blocks as ticks: 
fig3, ax3 = plt.subplots(nrows=3, figsize=(8, 6), sharex = True) 
ax3[0].plot(xaxis, errors) 
ax3 = ax3[0].twiny() 
ax3.plot_date(x, errors, fmt="r-") 
ax3.set_xticks(x[break_indexes][:-1]) 
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m \n%H:%M')) 

fig3.tight_layout() 
fig3.show() 

Useful ticks

最後我想你可能想REM奧雅納這些差距,但保持標籤在正確的地方:

# use blocks as ticks and eliminate the gaps: 
# (could have used the inverse of this to create those gaps) 
x_without_gaps = x.copy() 
delta = x[1] - x[0] 
for i in range(1,n_jumps): 
    i0 = break_indexes[i] 
    i1 = break_indexes[i+1] 
    if i1 == -1: 
     i1 = None 
    x_without_gaps[i0:i1] -= x_without_gaps[i0] - x_without_gaps[i0-1] - delta 

#x_without_gaps += x[0] 
fig4, ax4 = plt.subplots(nrows=3, figsize=(8, 6), sharex = True) 
ax4[0].plot(xaxis, errors) 
ax4[0].set_xlim(0,len(errors)-1) 
ax5 = ax4[0].twiny() 
ax5.plot_date(x_without_gaps, errors, fmt="r-") 
ax5.set_xticks(x_without_gaps[break_indexes][:-1]) 
ax5.set_xticklabels([date.strftime('%d/%m \n%H:%M') for date in 
       mdates.num2date(x[break_indexes][:-1])]) 
# the following line would clear the values placed! 
#ax5.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m \n%H:%M')) 
fig4.tight_layout() 
fig4.show() 

enter image description here

老結果和錯誤的刻度標記(此數據在每次運行隨機的,因此在新的例如標籤有明顯的不同,但我不想重新上傳每張圖片 - 信任或嘗試自己並驗證= op): Probably what is wanted 請注意,您無法真正看到紅色背後的藍線,因此匹配似乎沒有問題 - 只要您設置xlim以確保。 Detail of previous picture

+0

最終示例中的刻度標籤放置方式存在錯誤,將盡快進行編輯(或者如果有人想要,請成爲我的客人)。 – berna1111

+0

感謝所有這些。如果沿着date2num路線行進,這看起來確實是正確的方式。不過,我只是在想,由於存在差距,將日期視爲字符串更簡單。 – ninjaSurfer

+0

但是,如果您正在嘗試進行任何頻譜分析或時間相關分析,則可能需要使用數字 - 這取決於您是否單獨使用所有數據。最後一個例子似乎是「我可以初始設置」日期「xaxis等於」index「xaxis,然後將tick標籤更改爲相應的日期?」,儘管可能有點複雜。 – berna1111

1

由於時間戳之間的差距,這比最初想象的更困難。使用date2num而不是將時間戳視爲浮動時,可能會更容易將它們視爲str:

dates_test是str格式的時間戳數組。

fig, ax = plt.subplots(nrows=3, figsize=(8, 6), sharex = True) 

ax[0].plot(xaxis, errors) 
ax4 = ax[0].twiny() 
ax4.plot(xaxis, errors, "r-") 
ax4.xaxis.set_major_locator(majorLocator) 
ax4.xaxis.set_minor_locator(minorLocator) 

majorDates = [dates_test[i] for i in range(0,len(dates_test),250)] 
majorDates = [dates_test[0]] + majorDates 
ax4.set_xticklabels(majorDates, rotation = 'vertical') 

enter image description here