2017-03-07 18 views
1

私はtimeseriesを持って、私は2つのx軸、1はデータインデックスを表示し、1つは対応するタイムスタンプを表示したいと思います。これを行う1つの方法は、plt.plot_dateを使用し、次にインデックスに対して再度プロットするようです。しかし:2 x軸、1インデックスと1タイムスタンプポイント、同じyを使用して

  1. に(あなたは下の「ギャップ」を見ることができます)、すべてのデータを拾っていない日数に対してプロットを行うには良い方法がなければなりません。

dataplot vs indexplot.

レッド日付プロット、青のインデックスプロットです。

  • 私は当初、「日付」 「インデックス」x軸に等しいX軸、および、対応する 日付に目盛りラベルを変更設定することができます方法はありますか?

  • plt.plot_dateを使用しているときにギャップ動作が発生している可能性がありますか?タイムスタンプの

オリジナルフォーマットはstrである: array(['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あなたの返事をありがとう。 i)この例では、この例では役に立たないと思う。 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の値は0時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

そして、私はあなたがレムにしたいかもしれないと思いましたこれらのギャップオベが、適切な場所にタグを保つ:

# 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

古い結果を間違った目盛りラベル(新しい例のラベルは明らかに異なっているので、データは各ランでランダム化され、と私あなたが本当に赤い背景の青い線を見ることができないので、一致がうまくいくように注意してください。そのためにxlimを設定してください。 Detail of previous picture

+0

最後の例の目盛りのラベルが配置される方法にエラーがあります。固定された(または誰かが自分のゲストになることを望むならば)すぐに編集します。 – berna1111

+0

ありがとうございました。これは実際にdate2numルートをダウンする場合、これを行う正しい方法のように見えます。しかし、私はちょうどそのギャップのために、文字列として日付を扱うほうが簡単だと考えていました。 – ninjaSurfer

+0

しかし、スペクトル分析や時間依存解析を行う場合は、数値を使用する必要があります。束または個々のピース内のすべてのデータを個別に使用するのはあなた次第です。最後の例は、「「日付」xaxisを「インデックス」xaxisと同じに設定してから、対応する日付に目盛りのラベルを変更する方法です」と思われます。 – 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

関連する問題