時系列オブジェクトとコレクション
時系列データを格納するには、timetable
を使用する方法が推奨されます。この方法では、前処理、再構成、および解析のための幅広いサポート関数が用意されています。timetable の使用を開始するには、timetable の作成を参照してください。
一部の既存のコードでは、このトピックで説明している以下のオブジェクトが使用されます。
timeseries
— 数値データおよび時間値と共に、単位、イベント、データ品質、内挿法などのメタデータ情報を保存します。tscollection
— 共通の時間ベクトルを共有するtimeseries
オブジェクトのコレクションを保存します。異なる単位をもつ同期した時系列を操作するのに便利です。
timeseries
のデータ サンプル
3 つのセンサー信号で構成されるデータを考えます。2 つの信号は、オブジェクトの位置をメートル単位で表します。3 つ目の信号は、その速度をメートル/秒単位で表します。NaN
は欠損データ値を表します。
x = [-0.2 -0.3 13; -0.1 -0.4 15; NaN 2.8 17; 0.5 0.3 NaN; -0.3 -0.1 15];
x
の最初の 2 列は同じ単位をもつ量を含むので、これらの 2 つの時系列を保存する多変量の timeseries
オブジェクトを作成できます。
ts_pos = timeseries(x(:,1:2),1:5,"name","Position")
timeseries Common Properties: Name: 'Position' Time: [5x1 double] TimeInfo: tsdata.timemetadata Data: [5x2 double] DataInfo: tsdata.datametadata
"データ サンプル" は、timeseries
オブジェクトの特定の時間に関連する 1 つ以上の値から成ります。時系列のデータ サンプルの数は、時間ベクトルの長さと同じです。これは、この例では 5
です。データ サンプルのサイズを求めるには、getdatasamplesize
を使用します。
getdatasamplesize(ts_pos)
ans = 1×2
1 2
2 つ目の timeseries
オブジェクトを作成して、速度のデータを保存できます。
ts_vel = timeseries(x(:,3),1:5,"name","Velocity");
ts_pos
と ts_vel
を同期した状態で操作できるようにするには、それらをコレクションにまとめます。詳細については、時系列コレクションを参照してください。
時系列オブジェクトの作成
count.dat
のサンプル データには 24 行 3 列が含まれています。各列は、3 つの交差点それぞれにおける 1 時間ごとの車両数を表します。
データを読み込み、3 つの timeseries
オブジェクトを作成して、それぞれの交差点で収集されたデータを格納します。
load count.dat count1 = timeseries(count(:,1),1:24,"name","Intersection1"); count2 = timeseries(count(:,2),1:24,"name","Intersection2"); count3 = timeseries(count(:,3),1:24,"name","Intersection3");
あるいは、すべての時系列が同じデータ単位をもっていて、計算中に時系列の同期を取る場合は、単一のオブジェクトを作成します。
count_ts = timeseries(count,1:24,"name","traffic_counts");
単位と内挿法の変更
既定では、時系列には、秒単位の時間ベクトルと開始時刻 0 秒が格納されており、系列では線形内挿が使用されます。
3 つの時系列の時間単位を hours (時間) に変更します。
count1.TimeInfo.Units = "hours"; count2.TimeInfo.Units = "hours"; count3.TimeInfo.Units = "hours";
count1
のデータ単位を cars (台) に変更します。
count1.DataInfo.Units = "cars";
count1
の内挿法をゼロ次ホールドに設定します。他の時系列では、既定の手法である線形内挿が使用されます。
count1.DataInfo.Interpolation = tsdata.interpolation("zoh");
変更されたデータのプロパティを表示します。
count1.DataInfo
tsdata.datametadata Namespace: tsdata Common Properties: Units: 'cars' Interpolation: zoh (tsdata.interpolation)
イベントの定義
イベントは、特定の時間のデータをマークします。また、イベントは、複数の時系列を同期するのにも便利です。
午前と午後の通勤時間をマークする 2 つのイベントを各系列に追加します。
e1 = tsdata.event("AMCommute",8); e1.Units = "hours"; count1 = addevent(count1,e1); count2 = addevent(count2,e1); count3 = addevent(count3,e1); e2 = tsdata.event("PMCommute",18); e2.Units = "hours"; count1 = addevent(count1,e2); count2 = addevent(count2,e2); count3 = addevent(count3,e2);
最初の時系列をプロットします。赤い円形マーカーはイベントを示しています。
plot(count1)
時系列コレクション
"コレクション" とは、同期された時系列のグループです。コレクション内の timeseries
オブジェクトの時間ベクトルは一致しなければなりません。コレクションにある各時系列のことを、"メンバー" といいます。通常、異なるデータ単位をもつ時系列のコレクションを使用します。この簡単な例では、すべての時系列が同じ単位です。
tsc = tscollection({count1,count2,count3},"name","count_coll")
Time Series Collection Object: count_coll Time vector characteristics Start time 1 hours End time 24 hours Member Time Series Objects: Intersection1 Intersection2 Intersection3
コレクションのリサンプリング
リサンプリング操作は、特定の時間値における既存のデータを選択するか、より細かい区間でデータを内挿するために行います。新しい時間ベクトルが前の時間ベクトルに存在しなかった時間値を含む場合は、新しいデータ値は各時系列に関連付けられている内挿法を用いて計算されます。
データ値を 1 時間ごとではなく 2 時間ごとに含めるように時系列をリサンプリングし、新しい tscollection
オブジェクトとして保存します。
tsc1 = resample(tsc,1:2:24);
現在よりも情報を細かくサンプリングしなければならないこともあります。このような場合は、データ値を内挿して取得すれば合理的です。たとえば、30 分おきに値を内挿します。
tsc1 = resample(tsc,1:0.5:24);
Intersection1
の新しいデータ点は、前のサンプルの値を一定に保持する、ゼロ次ホールド内挿法を用いて計算されます。tsc1
のメンバーをマーカーを使用してプロットし、内挿結果を確認します。
plot(tsc1.Intersection1,"-x")
Intersection2
の新しいデータ点は、既定の手法である線形内挿を使用します。
plot(tsc1.Intersection2,"-o")
コレクションへのデータ サンプルの追加
3.25 時間の時点でデータ サンプルを最初のコレクション メンバーに追加します。
tsc1 = addsampletocollection(tsc1,"time",3.25,"Intersection1",5);
時系列には 30 分ごとの値が含まれるため、新しい値は 6 番目の要素になります。
tsc1.Intersection1.Data
ans = 48×1
11
11
7
7
14
5
14
11
11
43
⋮
新しいサンプルでは Intersection2
と Intersection3
のデータ値を指定しなかったので、それらのメンバーに対して欠損値が NaN
で表されます。
tsc1.Intersection2.Data
ans = 48×1
11
12
13
15
17
NaN
15
13
32
51
⋮
欠損データの処理
現在、tsc1
コレクションのメンバー Intersection2
および Intersection3
には、3.25 時間の時点で欠損値が含まれており、これは NaN
で表されています。このデータを解析する前に、欠損値を削除するか、内挿を使用して欠損値を置き換えることができます。
たとえば、NaN
値を含むデータ サンプルを見つけて削除します。Intersection2
の欠損値ごとに、その時点のデータがコレクションの "すべて" のメンバーから削除されます。
tsc2 = delsamplefromcollection(tsc1,"index",... find(isnan(tsc1.Intersection2.Data)));
あるいは、内挿を使用してリサンプリングすることで、Intersection2
および Intersection3
の NaN
値を置き換えます。これらの時系列の既定の内挿法は線形内挿です。
tsc1 = resample(tsc1,tsc1.Time); tsc1.Intersection2.Data
ans = 48×1
11
12
13
15
17
16
15
13
32
51
⋮
コレクション メンバーのプロット
時系列コレクションのデータをプロットするには、そのメンバーを一度に 1 つずつプロットします。
オプションとして、時間ベクトルを書式設定された日付と時刻として表示するには、開始日を指定します。この場合、時間単位は時間となるため、時と分を示す表示形式を指定できます。
tsc1.TimeInfo.StartDate = "25-DEC-2022 00:00:00"; tsc1.TimeInfo.Format = "HH:MM";
コレクションの単一のメンバーをプロットすると、時間単位が "x" 軸に、データ単位が "y" 軸に表示されます。プロットのタイトルは Time Series Plot:<member name>
と表示されます。
コレクションの複数のメンバーをプロットする前に hold on
を指定すると、注釈は表示されません。時系列の plot
メソッドは、系列の記述子が異なる可能性があるため、保持された Figure にラベルとタイトルを表示しようとしません。日付の書式を保持するには、最初のメンバーをプロットした後に保持します。コレクション全体を反映するようにタイトルとラベルを更新します。
plot(tsc1.Intersection1,"Displayname","Intersection 1") hold on plot(tsc1.Intersection2,"Displayname","Intersection 2") legend("Location","NorthWest") title("Intersections 1 and 2") xlabel("Time (hours)") ylabel("Number of cars") hold off