Multivariate Time Series
When you have multiple signals that share the same timestamps — like wind, solar, and hydro power — use TimeSeriesTable (also aliased as MultivariateTimeSeries). It stores per-column metadata and a 2D numpy array of values.
[1]:
from datetime import datetime, timedelta, timezone
import numpy as np
import timedatamodel as tdm
base = datetime(2024, 1, 15, tzinfo=timezone.utc)
timestamps = [base + timedelta(hours=i) for i in range(24)]
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[1], line 5
1 from datetime import datetime, timedelta, timezone
3 import numpy as np
----> 5 import timedatamodel as tdm
7 base = datetime(2024, 1, 15, tzinfo=timezone.utc)
8 timestamps = [base + timedelta(hours=i) for i in range(24)]
ModuleNotFoundError: No module named 'timedatamodel'
Creating a TimeSeriesTable
Pass a 2D array (rows = timestamps, columns = variables) along with per-column metadata.
[2]:
rng = np.random.default_rng(42)
wind = 80 + 40 * np.sin(np.linspace(0, 2 * np.pi, 24)) + rng.normal(0, 5, 24)
solar = np.clip(60 * np.sin(np.linspace(-0.5, np.pi + 0.5, 24)), 0, None) + rng.normal(0, 2, 24)
solar = np.clip(solar, 0, None)
hydro = 50 + rng.normal(0, 3, 24)
values = np.column_stack([wind, solar, hydro])
table = tdm.TimeSeriesTable(
tdm.Frequency.PT1H,
timezone="UTC",
timestamps=timestamps,
values=values,
names=["wind", "solar", "hydro"],
units=["MW", "MW", "MW"],
data_types=[tdm.DataType.MEASUREMENT, tdm.DataType.MEASUREMENT, tdm.DataType.MEASUREMENT],
)
table
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[2], line 10
6 hydro = 50 + rng.normal(0, 3, 24)
8 values = np.column_stack([wind, solar, hydro])
---> 10 table = tdm.TimeSeriesTable(
11 tdm.Frequency.PT1H,
12 timezone="UTC",
13 timestamps=timestamps,
14 values=values,
15 names=["wind", "solar", "hydro"],
16 units=["MW", "MW", "MW"],
17 data_types=[tdm.DataType.MEASUREMENT, tdm.DataType.MEASUREMENT, tdm.DataType.MEASUREMENT],
18 )
19 table
NameError: name 'tdm' is not defined
Inspecting table properties
[3]:
print(f"Columns: {table.column_names}")
print(f"Shape: ({len(table)}, {table.n_columns})")
print(f"Begin: {table.begin}")
print(f"End: {table.end}")
print(f"Has missing: {table.has_missing}")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 1
----> 1 print(f"Columns: {table.column_names}")
2 print(f"Shape: ({len(table)}, {table.n_columns})")
3 print(f"Begin: {table.begin}")
NameError: name 'table' is not defined
Selecting a single column
select_column() extracts one column as a univariate TimeSeries, carrying over its metadata.
[4]:
ts_wind = table.select_column("wind")
ts_wind
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[4], line 1
----> 1 ts_wind = table.select_column("wind")
2 ts_wind
NameError: name 'table' is not defined
[5]:
ts_solar = table.select_column("solar")
print(f"Name: {ts_solar.name}, Unit: {ts_solar.unit}, Data type: {ts_solar.data_type}")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[5], line 1
----> 1 ts_solar = table.select_column("solar")
2 print(f"Name: {ts_solar.name}, Unit: {ts_solar.unit}, Data type: {ts_solar.data_type}")
NameError: name 'table' is not defined
Merging univariate series into a table
TimeSeries.merge() is the reverse operation — combine several univariate series that share the same timestamps.
[6]:
ts_a = tdm.TimeSeries(
tdm.Frequency.PT1H,
timestamps=timestamps,
values=wind.tolist(),
name="wind",
unit="MW",
)
ts_b = tdm.TimeSeries(
tdm.Frequency.PT1H,
timestamps=timestamps,
values=solar.tolist(),
name="solar",
unit="MW",
)
ts_c = tdm.TimeSeries(
tdm.Frequency.PT1H,
timestamps=timestamps,
values=hydro.tolist(),
name="hydro",
unit="MW",
)
merged = tdm.TimeSeries.merge([ts_a, ts_b, ts_c])
merged
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 ts_a = tdm.TimeSeries(
2 tdm.Frequency.PT1H,
3 timestamps=timestamps,
4 values=wind.tolist(),
5 name="wind",
6 unit="MW",
7 )
8 ts_b = tdm.TimeSeries(
9 tdm.Frequency.PT1H,
10 timestamps=timestamps,
(...) 13 unit="MW",
14 )
15 ts_c = tdm.TimeSeries(
16 tdm.Frequency.PT1H,
17 timestamps=timestamps,
(...) 20 unit="MW",
21 )
NameError: name 'tdm' is not defined
Decomposing a table back to univariate series
[7]:
univariate_list = merged.to_univariate_list()
for ts in univariate_list:
print(f"{ts.name}: {len(ts)} points, unit={ts.unit}")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[7], line 1
----> 1 univariate_list = merged.to_univariate_list()
2 for ts in univariate_list:
3 print(f"{ts.name}: {len(ts)} points, unit={ts.unit}")
NameError: name 'merged' is not defined
Table arithmetic
Scalar arithmetic works on all columns simultaneously.
[8]:
table_gw = table * 0.001
table_gw.head(5)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[8], line 1
----> 1 table_gw = table * 0.001
2 table_gw.head(5)
NameError: name 'table' is not defined
Iteration and indexing
Each row is a (timestamp, [values...]) tuple.
[9]:
ts_val, row_vals = table[0]
print(f"Timestamp: {ts_val}")
print(f"Values: {row_vals}")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[9], line 1
----> 1 ts_val, row_vals = table[0]
2 print(f"Timestamp: {ts_val}")
3 print(f"Values: {row_vals}")
NameError: name 'table' is not defined
[10]:
for ts_val, row_vals in table.head(4):
wind_mw, solar_mw, hydro_mw = row_vals
print(f"{ts_val:%Y-%m-%d %H:%M} wind={wind_mw:6.1f} solar={solar_mw:5.1f} hydro={hydro_mw:5.1f}")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[10], line 1
----> 1 for ts_val, row_vals in table.head(4):
2 wind_mw, solar_mw, hydro_mw = row_vals
3 print(f"{ts_val:%Y-%m-%d %H:%M} wind={wind_mw:6.1f} solar={solar_mw:5.1f} hydro={hydro_mw:5.1f}")
NameError: name 'table' is not defined
Conversion to pandas DataFrame
[11]:
df = table.to_pandas_dataframe()
df.head()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[11], line 1
----> 1 df = table.to_pandas_dataframe()
2 df.head()
NameError: name 'table' is not defined
Summary
TimeSeriesTablestores multiple aligned columns with per-column metadataselect_column()extracts a single column as aTimeSeriesTimeSeries.merge()combines univariate series into a tableto_univariate_list()decomposes a table back to individual seriesScalar arithmetic applies across all columns
Next up: nb_06 covers TimeSeriesCube and TimeSeriesCollection for higher-dimensional data.