TimeSeriesList Operations
A TimeSeriesList is not just a data container — it supports arithmetic, comparisons, and transformations. This notebook demonstrates how to manipulate time series data without dropping down to raw arrays.
[1]:
from datetime import datetime, timedelta, timezone
import timedatamodel as tdm
base = datetime(2024, 1, 15, tzinfo=timezone.utc)
timestamps = [base + timedelta(hours=i) for i in range(24)]
generation = tdm.TimeSeriesList(
tdm.Frequency.PT1H,
timestamps=timestamps,
values=[
120.0, 115.0, 108.0, 105.0, 102.0, 100.0,
110.0, 135.0, 160.0, 175.0, 180.0, 178.0,
172.0, 170.0, 168.0, 165.0, 175.0, 190.0,
200.0, 195.0, 180.0, 165.0, 145.0, 130.0,
],
name="generation",
unit="MW",
data_type=tdm.DataType.OBSERVATION,
)
consumption = tdm.TimeSeriesList(
tdm.Frequency.PT1H,
timestamps=timestamps,
values=[
90.0, 85.0, 80.0, 78.0, 77.0, 80.0,
95.0, 120.0, 145.0, 155.0, 160.0, 158.0,
155.0, 150.0, 148.0, 150.0, 160.0, 170.0,
165.0, 155.0, 140.0, 120.0, 105.0, 95.0,
],
name="consumption",
unit="MW",
data_type=tdm.DataType.OBSERVATION,
)
Scalar arithmetic
Scale, offset, negate, or round values with natural Python operators. The result is a new TimeSeriesList with metadata preserved.
[2]:
generation_kw = generation * 1000
generation_kw
[2]:
| timestamp | generation |
|---|---|
| 2024-01-15 00:00 | 120000.0 |
| 2024-01-15 01:00 | 115000.0 |
| 2024-01-15 02:00 | 108000.0 |
| … | … |
| 2024-01-15 21:00 | 165000.0 |
| 2024-01-15 22:00 | 145000.0 |
| 2024-01-15 23:00 | 130000.0 |
[3]:
offset = generation + 10.0
negated = -generation
rounded = round(generation / 3, 1)
print(f"Original first value: {generation[0].value}")
print(f"+ 10: {offset[0].value}")
print(f"Negated: {negated[0].value}")
print(f"Divided by 3, rounded: {rounded[0].value}")
Original first value: 120.0
+ 10: 130.0
Negated: -120.0
Divided by 3, rounded: 40.0
Element-wise arithmetic between two TimeSeriesList
Subtract consumption from generation to get net surplus. Both series must share the same timestamps.
[4]:
surplus = generation - consumption
surplus
[4]:
| timestamp | value |
|---|---|
| 2024-01-15 00:00 | 30.0 |
| 2024-01-15 01:00 | 30.0 |
| 2024-01-15 02:00 | 28.0 |
| … | … |
| 2024-01-15 21:00 | 45.0 |
| 2024-01-15 22:00 | 40.0 |
| 2024-01-15 23:00 | 35.0 |
Comparison operators
Comparisons return a TimeSeriesList of 1.0 / 0.0 (or NaN for missing). Useful for flagging thresholds.
[5]:
high_gen = generation > 170.0
high_gen
[5]:
| timestamp | value |
|---|---|
| 2024-01-15 00:00 | 0.0 |
| 2024-01-15 01:00 | 0.0 |
| 2024-01-15 02:00 | 0.0 |
| … | … |
| 2024-01-15 21:00 | 0.0 |
| 2024-01-15 22:00 | 0.0 |
| 2024-01-15 23:00 | 0.0 |
[6]:
gen_exceeds_cons = generation > consumption
gen_exceeds_cons
[6]:
| timestamp | value |
|---|---|
| 2024-01-15 00:00 | 1.0 |
| 2024-01-15 01:00 | 1.0 |
| 2024-01-15 02:00 | 1.0 |
| … | … |
| 2024-01-15 21:00 | 1.0 |
| 2024-01-15 22:00 | 1.0 |
| 2024-01-15 23:00 | 1.0 |
abs() — absolute values
Handy when you have signed deviations or residuals.
[7]:
deviation = generation - consumption
abs_deviation = abs(deviation)
abs_deviation.head(6)
[7]:
| timestamp | value |
|---|---|
| 2024-01-15 00:00 | 30.0 |
| 2024-01-15 01:00 | 30.0 |
| 2024-01-15 02:00 | 28.0 |
head(), tail(), and copy()
Quickly preview or duplicate a series.
[8]:
print("First 3:")
for dp in generation.head(3):
print(f" {dp.timestamp:%H:%M} {dp.value:.1f} MW")
print("\nLast 3:")
for dp in generation.tail(3):
print(f" {dp.timestamp:%H:%M} {dp.value:.1f} MW")
First 3:
00:00 120.0 MW
01:00 115.0 MW
02:00 108.0 MW
Last 3:
21:00 165.0 MW
22:00 145.0 MW
23:00 130.0 MW
[ ]:
[ ]:
Handling missing values in arithmetic
Missing values (None) propagate through operations as NaN, just like numpy.
[9]:
ts_with_gaps = tdm.TimeSeriesList(
tdm.Frequency.PT1H,
timestamps=timestamps[:6],
values=[100.0, None, 110.0, None, 105.0, 108.0],
name="sensor",
unit="MW",
)
doubled = ts_with_gaps * 2
for dp in doubled:
print(f"{dp.timestamp:%H:%M} {dp.value}")
00:00 200.0
01:00 None
02:00 220.0
03:00 None
04:00 210.0
05:00 216.0
Summary
You can treat TimeSeriesList like a numeric object:
Scalar ops:
+,-,*,/,-ts,abs(),round()Element-wise ops between aligned series
Comparisons:
>,>=,<,<=,==,!=Missing values propagate cleanly
Next up: nb_05 introduces multivariate time series with TimeSeriesTable.