%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22yohou%5Bplotting%5D%22%2C%0A%23%20%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.8%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Window%20Transformers%0A%0A%20%20%20%20Window%20transformers%20create%20features%20from%20temporal%20windows%20of%20data.%20They%20are%0A%20%20%20%20the%20core%20building%20blocks%20for%20feature%20engineering%20in%20time%20series%20forecasting.%0A%0A%20%20%20%20This%20notebook%20shows%20how%20to%20engineer%20features%20with%20LagTransformer%2C%20RollingStatisticsTransformer%2C%20SlidingWindowFunctionTransformer%2C%20and%20ExponentialMovingAverage%20on%20time%20series%20data.%0A%0A%20%20%20%20**Prerequisites%3A**%20Basic%20understanding%20of%20feature%20engineering%20and%20time%20series%20concepts.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%0A%20%20%20%20from%20yohou.compose%20import%20FeatureUnion%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_tourism_monthly%0A%20%20%20%20from%20yohou.plotting%20import%20plot_rolling_statistics%2C%20plot_time_series%0A%20%20%20%20from%20yohou.preprocessing%20import%20(%0A%20%20%20%20%20%20%20%20ExponentialMovingAverage%2C%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20RollingStatisticsTransformer%2C%0A%20%20%20%20%20%20%20%20SlidingWindowFunctionTransformer%2C%0A%20%20%20%20)%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20ExponentialMovingAverage%2C%0A%20%20%20%20%20%20%20%20FeatureUnion%2C%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20RollingStatisticsTransformer%2C%0A%20%20%20%20%20%20%20%20SlidingWindowFunctionTransformer%2C%0A%20%20%20%20%20%20%20%20fetch_tourism_monthly%2C%0A%20%20%20%20%20%20%20%20plot_rolling_statistics%2C%0A%20%20%20%20%20%20%20%20plot_time_series%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%201.%20Prepare%20Data%0A%0A%20%20%20%20We%20load%20the%20monthly%20tourism%20series%20from%20the%20Monash%20repository%20using%0A%20%20%20%20%60fetch_tourism_monthly()%60%2C%20select%20a%20single%20target%20column%2C%20and%20rename%20it%0A%20%20%20%20for%20readability.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_tourism_monthly%2C%20plot_time_series)%3A%0A%20%20%20%20y%20%3D%20fetch_tourism_monthly().frame.select(%22time%22%2C%20%22T1__tourists%22).drop_nulls().rename(%7B%22T1__tourists%22%3A%20%22tourists%22%7D)%0A%20%20%20%20plot_time_series(y%2C%20title%3D%22Monthly%20Tourism%20(T1)%22)%0A%20%20%20%20return%20(y%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%202.%20LagTransformer%0A%0A%20%20%20%20%5B%60LagTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.LagTransformer%2F)%20creates%20new%20columns%20by%20shifting%20the%20original%20values%0A%20%20%20%20backward%20by%20the%20specified%20number%20of%20steps.%20For%20example%2C%20%60lag%3D3%60%20creates%0A%20%20%20%20a%20column%20whose%20value%20at%20time%20*t*%20equals%20the%20original%20value%20at%20*t-3*.%0A%20%20%20%20The%20first%20%60max(lag)%60%20rows%20are%20consumed%20as%20the%20transformer's%0A%20%20%20%20%60observation_horizon%60%20because%20they%20have%20no%20valid%20lagged%20value.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LagTransformer%2C%20plot_time_series%2C%20y)%3A%0A%20%20%20%20lag_tf%20%3D%20LagTransformer(lag%3D%5B1%2C%203%2C%206%2C%2012%5D)%0A%20%20%20%20lag_tf.fit(y)%0A%20%20%20%20y_lagged%20%3D%20lag_tf.transform(y)%0A%20%20%20%20plot_time_series(y_lagged%2C%20title%3D%22LagTransformer%20(lag%3D%5B1%2C%203%2C%206%2C%2012%5D)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%203.%20RollingStatisticsTransformer%0A%0A%20%20%20%20%5B%60RollingStatisticsTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.RollingStatisticsTransformer%2F)%20computes%20one%20or%20more%20summary%20statistics%0A%20%20%20%20over%20a%20sliding%20window%20of%20the%20most%20recent%20%60window_size%60%20observations.%0A%20%20%20%20Supported%20statistics%20include%20%60%22mean%22%60%2C%20%60%22std%22%60%2C%20%60%22min%22%60%2C%20%60%22max%22%60%2C%0A%20%20%20%20%60%22median%22%60%2C%20%60%22sum%22%60%2C%20and%20%60%22var%22%60.%20Multiple%20statistics%20can%20be%20computed%0A%20%20%20%20in%20a%20single%20call.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RollingStatisticsTransformer%2C%20plot_time_series%2C%20y)%3A%0A%20%20%20%20roll_tf%20%3D%20RollingStatisticsTransformer(%0A%20%20%20%20%20%20%20%20window_size%3D12%2C%0A%20%20%20%20%20%20%20%20statistics%3D%5B%22mean%22%2C%20%22std%22%2C%20%22min%22%2C%20%22max%22%5D%2C%0A%20%20%20%20)%0A%20%20%20%20roll_tf.fit(y)%0A%20%20%20%20y_rolled%20%3D%20roll_tf.transform(y)%0A%20%20%20%20plot_time_series(y_rolled%2C%20title%3D%22Rolling%20Statistics%20(window%3D12)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%5B%60plot_rolling_statistics%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_rolling_statistics%2F)%20is%20a%20dedicated%20helper%20that%20renders%20the%20original%0A%20%20%20%20series%20together%20with%20its%20rolling%20mean%20and%20standard%20deviation%20bands%2C%0A%20%20%20%20giving%20a%20quick%20visual%20summary%20of%20time-varying%20location%20and%20spread.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_rolling_statistics%2C%20y)%3A%0A%20%20%20%20plot_rolling_statistics(%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20window_size%3D12%2C%0A%20%20%20%20%20%20%20%20statistics%3D%5B%22mean%22%2C%20%22std%22%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22Rolling%20Statistics%20(window%3D12)%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%204.%20SlidingWindowFunctionTransformer%0A%0A%20%20%20%20%5B%60SlidingWindowFunctionTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.SlidingWindowFunctionTransformer%2F)%20lets%20you%20apply%20any%20custom%20function%0A%20%20%20%20over%20a%20sliding%20window.%20The%20function%20receives%20a%20polars%20DataFrame%0A%20%20%20%20containing%20%60window_size%60%20rows%20and%20must%20return%20a%20scalar%2C%20a%20dictionary%2C%20or%0A%20%20%20%20an%20array.%20Below%20we%20compute%20the%20range%20(max%20minus%20min)%20over%20the%20last%206%0A%20%20%20%20periods%20as%20a%20volatility%20proxy.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(SlidingWindowFunctionTransformer%2C%20plot_time_series%2C%20y)%3A%0A%20%20%20%20%23%20Custom%3A%20range%20(max%20-%20min)%20over%20last%206%20periods%0A%20%20%20%20%23%20func%20receives%20a%20polars%20DataFrame%20window%2C%20must%20return%20scalar%2C%20dict%2C%20or%20ndarray%0A%20%20%20%20range_tf%20%3D%20SlidingWindowFunctionTransformer(%0A%20%20%20%20%20%20%20%20func%3Dlambda%20df%3A%20%7Bcol%3A%20df%5Bcol%5D.max()%20-%20df%5Bcol%5D.min()%20for%20col%20in%20df.columns%20if%20col%20!%3D%20%22time%22%7D%2C%0A%20%20%20%20%20%20%20%20window_size%3D6%2C%0A%20%20%20%20)%0A%20%20%20%20range_tf.fit(y)%0A%20%20%20%20y_range%20%3D%20range_tf.transform(y)%0A%20%20%20%20_combined%20%3D%20y.rename(%7B%22tourists%22%3A%20%22original%22%7D).join(%0A%20%20%20%20%20%20%20%20y_range.rename(%7B%22tourists%22%3A%20%22range%20(max-min)%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22SlidingWindowFunction%3A%20Range%20vs%20Original%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%205.%20ExponentialMovingAverage%0A%0A%20%20%20%20%5B%60ExponentialMovingAverage%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.ExponentialMovingAverage%2F)%20computes%20an%20exponentially%20weighted%20moving%0A%20%20%20%20average%20where%20recent%20observations%20receive%20more%20weight%20than%20older%20ones.%0A%20%20%20%20The%20%60alpha%60%20parameter%20(between%200%20and%201)%20controls%20the%20decay%3A%20higher%0A%20%20%20%20values%20respond%20faster%20to%20recent%20changes.%20Unlike%20rolling%20statistics%2C%20EWMA%0A%20%20%20%20has%20%60observation_horizon%3D0%60%20because%20it%20is%20a%20purely%20recursive%20calculation%0A%20%20%20%20that%20does%20not%20discard%20initial%20rows.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ExponentialMovingAverage%2C%20plot_time_series%2C%20y)%3A%0A%20%20%20%20ema_tf%20%3D%20ExponentialMovingAverage(alpha%3D0.3)%0A%20%20%20%20ema_tf.fit(y)%0A%20%20%20%20y_ema%20%3D%20ema_tf.transform(y)%0A%20%20%20%20_combined%20%3D%20y.rename(%7B%22tourists%22%3A%20%22original%22%7D).join(%0A%20%20%20%20%20%20%20%20y_ema.rename(%7B%22tourists_ewma%22%3A%20%22EMA%20(alpha%3D0.3)%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22Exponential%20Moving%20Average%20vs%20Original%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%206.%20Combining%20Transformers%20with%20FeatureUnion%0A%0A%20%20%20%20%5B%60FeatureUnion%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.feature_union.FeatureUnion%2F)%20runs%20multiple%20transformers%20in%20parallel%20on%20the%20same%20input%0A%20%20%20%20and%20concatenates%20their%20outputs%20horizontally.%20The%20combined%0A%20%20%20%20%60observation_horizon%60%20equals%20the%20maximum%20across%20all%20transformers%2C%20so%0A%20%20%20%20early%20rows%20that%20any%20single%20transformer%20cannot%20fill%20are%20dropped.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ExponentialMovingAverage%2C%0A%20%20%20%20FeatureUnion%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20RollingStatisticsTransformer%2C%0A%20%20%20%20plot_time_series%2C%0A%20%20%20%20y%2C%0A)%3A%0A%20%20%20%20union%20%3D%20FeatureUnion(%0A%20%20%20%20%20%20%20%20transformer_list%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22lags%22%2C%20LagTransformer(lag%3D%5B1%2C%2012%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22rolling%22%2C%20RollingStatisticsTransformer(window_size%3D6%2C%20statistics%3D%22mean%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22ema%22%2C%20ExponentialMovingAverage(alpha%3D0.3))%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20union.fit(y)%0A%20%20%20%20y_combined%20%3D%20union.transform(y)%0A%20%20%20%20plot_time_series(y_combined%2C%20title%3D%22FeatureUnion%3A%20All%20Window%20Features%20Combined%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Next%20Steps%0A%0A%20%20%20%20-%20%5BUse%20Preprocessing%20Transformers%5D(%2Fpages%2Fhow-to%2Fuse-preprocessing-transformers%2F)%20for%20the%20full%20guide%0A%20%20%20%20-%20%5BCompose%20Feature%20Pipelines%5D(%2Fpages%2Fhow-to%2Fcompose-feature-pipelines%2F)%20for%20related%20techniques%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
f4868b7e7b2e76721d4c77a116aea942