Main Content

时间序列对象和集合

存储时间序列数据的推荐方法是使用timetable,它有一组广泛的预处理、重构和分析支持函数。要开始使用时间表,请参阅创建时间表

一些现有代码使用这些对象,如本主题中所述:

  • timeseries - 存储数值数据和时间值,以及包含单位、事件、数据质量和插值方法的元数据信息。

  • tscollection - 存储共享公共时间向量的 timeseries 对象的集合,便于对具有不同单位的同步时间序列执行操作。

timeseries 中的数据采样

考虑由三个传感器信号组成的数据:其中两个信号表示对象的位置,以米为单位;第三个信号表示其速度,以米/秒为单位。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 的前两列包含具有相同单位的数量,您可以创建多元 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 对象中与特定时间关联的一个或多个值组成。一个时间序列中的数据样本数量与时间向量的长度(在此示例中为 5)相同。要计算数据样本的大小,请使用 getdatasamplesize

getdatasamplesize(ts_pos)
ans = 1×2

     1     2

您可以创建另一个 timeseries 对象来存储速度数据。

ts_vel = timeseries(x(:,3),1:5,"name","Velocity");

如果您要对 ts_posts_vel 执行操作且同时使它们保持同步,请将它们组合到一个集合中。有关详细信息,请参阅时间序列集合

创建时间序列对象

count.dat 中的示例数据有 24 行和 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 秒,并且该序列使用线性插值。

将三个时间序列的时间单位修改为小时。

count1.TimeInfo.Units = "hours";
count2.TimeInfo.Units = "hours";
count3.TimeInfo.Units = "hours";

count1 的数据单位更改为汽车。

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)

定义事件

事件在特定时间标记数据。事件还是同步多个时间序列的一种便捷方式。

在每个序列中添加两个事件,分别标记早上和下午的通勤时间。

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)

Figure contains an axes object. The axes object with title Time Series Plot:Intersection1, xlabel Time (hours), ylabel Intersection1 (cars) contains 2 objects of type stair, line. One or more of the lines displays its values using only markers

时间序列集合

集合是一组同步的时间序列。集合中 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

对集合进行重采样

重采样操作用于选择在特定时间值的现有数据,或以更精细的时间间隔进行数据插值。如果新时间向量包含在前一时间向量中不存在的时间值,则使用与时间序列关联的插值方法计算新数据值。

对时间序列进行重采样以包含每二小时(而不是每小时)的数据值,并将其保存为新 tscollection 对象。

tsc1 = resample(tsc,1:2:24);

在某些情况下,您可能需要比当前更精细的信息采样,通过对数据值进行插值可实现此目的。例如,在每个半小时标记处进行插值。

tsc1 = resample(tsc,1:0.5:24);

Intersection1 中的新数据点是使用零阶保持插值方法计算的,该方法会保持上一个样本常量的值。对具有标记的 tsc1 成员进行绘图以查看插值结果。

plot(tsc1.Intersection1,"-x")

Figure contains an axes object. The axes object with title Time Series Plot:Intersection1, xlabel Time (hours), ylabel Intersection1 (cars) contains 2 objects of type stair, line. One or more of the lines displays its values using only markers

Intersection2 中的新数据点使用线性插值,这是默认方法。

plot(tsc1.Intersection2,"-o")

Figure contains an axes object. The axes object with title Time Series Plot:Intersection2, xlabel Time (hours), ylabel Intersection2 contains 2 objects of type line. One or more of the lines displays its values using only markers

向集合中添加数据样本

在 3.25 小时处向第一个集合成员添加一个数据样本。

tsc1 = addsampletocollection(tsc1,"time",3.25,"Intersection1",5);

时间序列包括每半小时的值,因此新值是第六个元素。

tsc1.Intersection1.Data
ans = 48×1

    11
    11
     7
     7
    14
     5
    14
    11
    11
    43
      ⋮

由于您未在新样本中指定 Intersection2Intersection3 的数据值,因此对于这些成员,缺失值由 NaN 表示。

tsc1.Intersection2.Data
ans = 48×1

    11
    12
    13
    15
    17
   NaN
    15
    13
    32
    51
      ⋮

处理缺失数据

tsc1 集合中的 Intersection2Intersection3 成员当前在 3.25 小时处包含缺失值,由 NaN 表示。在分析此数据之前,您可以删除缺失值,或使用插值方法替换缺失值。

例如,查找并删除包含 NaN 值的数据样本。对于 Intersection2 中的每个缺失值,将从集合的所有成员中删除在该时间处的数据。

tsc2 = delsamplefromcollection(tsc1,"index",... 
       find(isnan(tsc1.Intersection2.Data)));

或者,通过使用插值进行重采样来替换 Intersection2Intersection3 中的 NaN 值。这些时间序列的默认插值方法是线性插值。

tsc1 = resample(tsc1,tsc1.Time);
tsc1.Intersection2.Data
ans = 48×1

    11
    12
    13
    15
    17
    16
    15
    13
    32
    51
      ⋮

绘制集合成员

要绘制时间序列集合中的数据,请逐个绘制其成员。

(可选)要将时间向量显示为格式化的日期时间,请指定开始日期。在本例中,时间单位是小时,因此您可以指定显示小时和分钟的显示格式。

tsc1.TimeInfo.StartDate = "25-DEC-2022 00:00:00";
tsc1.TimeInfo.Format = "HH:MM";

在绘制集合的一个成员时,其时间单位显示在 x 轴上,其数据单位显示在 y 轴上。绘图标题显示为 Time Series Plot:<member name>

如果在绘制集合的多个成员之前指定 hold on,则不会显示任何注释。时间序列 plot 方法不会尝试在保留的图窗上显示标签和标题,因为序列的描述符可能不同。要保留日期格式,请在绘制第一个成员后保留。更新标题和标签以反映整个集合。

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

Figure contains an axes object. The axes object with title Intersections 1 and 2, xlabel Time (hours), ylabel Number of cars contains 2 objects of type stair, line. These objects represent Intersection 1, Intersection 2.

另请参阅

| |