# Time Series Objects and Collections

The recommended way to store time series data is with `timetable`

, which has a broad set of supporting functions for preprocessing, restructuring, and analysis. To get started with timetables, see Create Timetables.

Some existing code uses these objects, described in this topic:

`timeseries`

— Stores numeric data and time values, as well as the metadata information that includes units, events, data quality, and interpolation method.`tscollection`

— Stores a collection of`timeseries`

objects that share a common time vector, convenient for performing operations on synchronized time series with different units.

### Data Samples in `timeseries`

Consider data that consists of three sensor signals: two signals represent the position of an object in meters, and the third represents its velocity in meters/second. `NaN`

represents a missing data value.

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];

The first two columns of `x`

contain quantities with the same units, and you can create a multivariate `timeseries`

object to store these two time series.

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

A *data sample* consists of one or more values associated with a specific time in the `timeseries`

object. The number of data samples in a time series is the same as the length of the time vector, which is `5`

in this example. To find the size of the data sample, use `getdatasamplesize`

.

getdatasamplesize(ts_pos)

`ans = `*1×2*
1 2

You can create a second `timeseries`

object to store the velocity data.

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

If you want to perform operations on `ts_pos`

and `ts_vel`

while keeping them synchronized, group them in a collection. For more information, see Time Series Collections.

**Creating Time Series Objects**

The sample data in `count.dat`

has 24 rows and three columns. Each column represents hourly vehicle counts at each of three town intersections.

Load the data and create three `timeseries`

objects to store the data collected at each intersection.

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");

Alternatively, when all time series have the same data units and you want to keep them synchronized during calculations, create a single object.

count_ts = timeseries(count,1:24,"name","traffic_counts");

### Modifying Units and Interpolation Method

By default, a time series has a time vector with units of seconds and a start time of 0 sec, and the series uses linear interpolation.

Modify the time units to be hours for the three time series.

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

Change the data units for `count1`

to cars.

`count1.DataInfo.Units = "cars";`

Set the interpolation method for `count1`

to zero-order hold. The other time series use the default method, linear interpolation.

`count1.DataInfo.Interpolation = tsdata.interpolation("zoh");`

View the modified data properties.

count1.DataInfo

tsdata.datametadata Namespace: tsdata Common Properties: Units: 'cars' Interpolation: zoh (tsdata.interpolation)

### Defining Events

Events mark the data at specific times. Events also provide a convenient way to synchronize multiple time series.

Add two events to each series that mark the times of the AM commute and PM commute.

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 the first time series. Red circle markers indicate the events.

plot(count1)

### Time Series Collections

A *collection* is a group of synchronized time series. The time vectors of the `timeseries`

objects in a collection must match. Each individual time series in a collection is called a *member*. Typically, you use collections for time series that have different data units. In this simple example, all time series have the same units.

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

#### Resampling a Collection

A resampling operation is used to either select existing data at specific time values, or to interpolate data at finer intervals. If the new time vector contains time values that did not exist in the previous time vector, the new data values are calculated using the interpolation method associated with each time series.

Resample the time series to include data values every two hours instead of every hour and save it as a new `tscollection`

object.

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

In some cases, you might need a finer sampling of information than you currently have and it is reasonable to obtain it by interpolating data values. For instance, interpolate values at each half-hour mark.

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

The new data points in `Intersection1`

are calculated by using the zero-order hold interpolation method, which holds the value of the previous sample constant. Plot the members of `tsc1`

with markers to see the results of interpolating.

`plot(tsc1.Intersection1,"-x")`

The new data points in `Intersection2`

use linear interpolation, the default method.

`plot(tsc1.Intersection2,"-o")`

#### Adding a Data Sample to a Collection

Add a data sample to the first collection member at 3.25 hours.

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

The time series includes values for every half hour, so the new value is the sixth element.

tsc1.Intersection1.Data

`ans = `*48×1*
11
11
7
7
14
5
14
11
11
43
⋮

Because you did not specify the data values for `Intersection2`

and `Intersection3`

in the new sample, the missing values are represented by `NaN`

for these members.

tsc1.Intersection2.Data

`ans = `*48×1*
11
12
13
15
17
NaN
15
13
32
51
⋮

#### Handling Missing Data

The `Intersection2`

and `Intersection3`

members in the `tsc1`

collection currently contain missing values at 3.25 hours, represented by `NaN`

. Before analyzing this data, you can either remove the missing values or use interpolation to replace them.

For instance, find and remove the data samples that contain `NaN`

values. For each missing value in `Intersection2`

, the data at that time is removed from *all* members of the collection.

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

Alternatively, replace the `NaN`

values in `Intersection2`

and `Intersection3`

by resampling using interpolation. The default interpolation method for these time series is linear interpolation.

tsc1 = resample(tsc1,tsc1.Time); tsc1.Intersection2.Data

`ans = `*48×1*
11
12
13
15
17
16
15
13
32
51
⋮

#### Plotting Collection Members

To plot data in a time series collection, plot its members one at a time.

Optionally, to display the time vectors as formatted dates and times, specify the start date. In this case, the time units are hours, so you can specify a display format that shows hours and minutes.

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

When you plot a single member of a collection, its time units display on the *x*-axis and its data units display on the *y*-axis. The plot title is displayed as `Time Series Plot:<member name>`

.

If you specify `hold on`

before plotting multiple members of the collection, no annotations display. The time series `plot`

method does not attempt to show labels and titles on held figures because the descriptors for the series can be different. To preserve date formatting, hold after plotting the first member. Update the title and labels to reflect the entire collection.

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