Plots#
[1]:
# Import to be able to import python package from src
import sys
sys.path.insert(0, '../src')
[2]:
import pandas as pd
import ontime as on
from darts.datasets import EnergyDataset
The `LightGBM` module could not be imported. To enable LightGBM support in Darts, follow the detailed instructions in the installation guide: https://github.com/unit8co/darts/blob/master/INSTALL.md
The `Prophet` module could not be imported. To enable Prophet support in Darts, follow the detailed instructions in the installation guide: https://github.com/unit8co/darts/blob/master/INSTALL.md
Load data#
[3]:
ts = EnergyDataset().load()
Complete TimeSeries
[4]:
df = ts.pd_dataframe()
df = df.interpolate()
cols = ['generation biomass', 'generation solar', 'generation nuclear']
df = df[cols]
[5]:
ts = on.TimeSeries.from_dataframe(df)
Prepare data
[6]:
ts_uni = ts['generation solar'].slice(pd.Timestamp('2015'), pd.Timestamp('2016'))
ts_multi = ts.slice(pd.Timestamp('2015'), pd.Timestamp('2016'))
Primitive Plots#
Line(s)#
With univariate TimeSeries
[7]:
on.Plot(ts_uni.head(400))\
.add(on.marks.line)\
.properties(width=600)\
.show()
[7]:
with multivariate TimeSeries
[8]:
on.Plot(ts_multi.head(400))\
.add(on.marks.line)\
.properties(width=600)\
.show()
[8]:
Dots#
With univariate TimeSeries
[9]:
on.Plot(ts_uni.head(400))\
.add(on.marks.dots)\
.properties(width=600)\
.show()
[9]:
with multivariate TimeSeries
[10]:
on.Plot(ts_multi.head(400))\
.add(on.marks.dots)\
.properties(width=600)\
.show()
[10]:
Areas#
With a single time series
[11]:
on.Plot(ts_uni.head(400))\
.add(on.marks.area)\
.properties(width=600)\
.show()
[11]:
With a multivariate time series it works with exactly two
[12]:
from darts import concatenate
[13]:
# First we create the series with two components
ts_ci = concatenate([
ts_multi.univariate_component(0),
ts_multi.univariate_component(1)
], axis=1)
ts_ci = on.TimeSeries.from_darts(ts_ci)
[14]:
# Then we plot it
on.Plot(ts_ci.head(200))\
.add(on.marks.area, title='Diff. between solar and biomass generation')\
.properties(width=600, height=200)\
.show()
[14]:
Heatmaps#
with univariate TimeSeries
[15]:
on.Plot(ts_uni.head(1000))\
.add(on.marks.heatmap)\
.properties(width=600, height=50)\
.show()
[15]:
with multivariate Heatmap
[23]:
on.Plot(ts_multi.head(1000))\
.add(on.marks.heatmap)\
.properties(width=600, height=150)\
.show()
[23]:
Combined Plots#
Most of the plots in onTime can be combined as they are based on Altair layered charts. For instance, you can do the following to have a dots on a line.
[24]:
on.Plot()\
.add(on.marks.dots, ts_multi.univariate_component(1).head(400))\
.add(on.marks.line, ts_multi.univariate_component(0).head(400))\
.properties(width=600, height=200)\
.show()
[24]:
Thematic Plots#
Forecasts#
[25]:
ts_train, ts_test = ts_uni.split_before(0.9)
[26]:
from ontime.context import common
[27]:
model = common.GenericPredictor()
model.fit(ts_train)
[27]:
<ontime.context.common.generic_predictor.GenericPredictor at 0x1759654b0>
[28]:
ts_pred = model.predict(24 * 3)
[29]:
ts_train = ts_train.rename({'generation solar':'Training set'})
ts_test = ts_test.rename({'generation solar':'Test set'})
ts_pred = ts_pred.rename({'generation solar':'Forecast'})
Plot a prediction
[30]:
(
on.Plot()
.add(on.marks.line, ts_test.head(24 * 3), type='dashed')
.add(on.marks.line, ts_train.tail(24 * 4))
.add(on.marks.line, ts_pred)
.properties(width=600, height=200)
.show()
)
[30]:
Anomalies#
Create the mock data
[56]:
td_point = on.detectors.quantile(high_quantile=0.99)
td_collective = on.detectors.threshold(low_threshold=-30)
td_contextual = on.detectors.quantile(high_quantile=0.98)
Add anomalies
[57]:
import numpy as np
import random
def add_point_anomalies(ts, n, value):
df = ts.pd_dataframe()
random_indices = np.random.choice(df.index, size=n, replace=False)
df.loc[random_indices] = value
return on.TimeSeries.from_dataframe(df)
def add_collective_anomalies(ts, n, min_duration=10, max_duration=20):
df = ts.pd_dataframe()
for i in range(n+1):
block_duration = random.randint(min_duration, max_duration)
start_index = np.random.choice(df.index[:-block_duration])
end_index = start_index + pd.Timedelta(days=block_duration - 1)
df.loc[start_index:end_index] = -40
return on.TimeSeries.from_dataframe(df)
Select univariate component
[58]:
ts = ts.univariate_component(0)
[59]:
ts = add_point_anomalies(ts, 10, 30)
ts = add_collective_anomalies(ts, 4)
Create binary time series
[60]:
td_point.fit(ts)
td_contextual.fit(ts)
ts_ano_point = td_point.detect(ts)
ts_ano_collective = td_collective.detect(ts)
ts_ano_contextual = td_contextual.detect(ts)
[61]:
ts_ano_point = ts_ano_point.rename({'0': 'Ponctual anomalies'})
ts_ano_collective = ts_ano_collective.rename({'0': 'Collective anomalies'})
ts_ano_contextual = ts_ano_contextual.rename({'0': 'Contextual anomalies'})
Plot the time series with marked anomalies
[64]:
# Define windows for plotting
start = 24 * 7 * 4 * 9
duration = 24 * 7 * 10
end = start + duration
[67]:
# Actually plot
(
on.Plot(ts[start:end])
.add(on.marks.mark, data=ts_ano_contextual[start:end], type='highlight')
.add(on.marks.mark, data=ts_ano_collective[start:end], type='background')
.add(on.marks.line)
.add(on.marks.mark, data=ts_ano_point[start:end], type='dot')
.properties(width=800, height=200)
.show()
)
[67]:
Confidence Intervals#
[91]:
# Generate two time series
ts1 = on.generators.random_walk().generate(start=pd.Timestamp('2022-01-01'), end=pd.Timestamp('2022-12-31'))
ts2 = on.generators.random_walk().generate(start=pd.Timestamp('2022-01-01'), end=pd.Timestamp('2022-12-31'))
[92]:
# First we create the series with two components
ts1_abs = ts1.map(np.abs)
ts2_abs = ts2.map(np.abs)
ts_ci = concatenate([ts1_abs, ts2_abs], axis=1)
ts_ci = on.TimeSeries.from_darts(ts_ci)
ts_ci = ts_ci.rename({'random_walk': 'CI Upper bound', 'random_walk_1': 'CI Lower bound'})
# Then the hypothetical measurement
ts_mid = (ts1_abs + ts2_abs) / 2
ts_mid = ts_mid.rename({'random_walk': 'Measurement'})
[93]:
# Then we plot it
(
on.Plot() # main line
.add(on.marks.area, ts_ci.head(200), title='Confidence interval')
.add(on.marks.line, ts_mid.head(200))
.properties(width=600, height=200)
.show()
)
[93]:
[ ]: