import%20marimo%0A%0A__generated_with%20%3D%20%220.14.16%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20width%3D%22medium%22%2C%0A%20%20%20%20app_title%3D%22Sessionized%20Data%20Pattern%22%2C%0A%20%20%20%20css_file%3D%22marimo_custom.css%22%2C%0A)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20text_cell(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%23%20Sessionized%20Data%0A%0A%20%20%20%20Group%20event%20data%20into%20sessions%20using%20map%2Freduce%20patterns.%0A%0A%20%20%20%20%23%23%20Overview%0A%0A%20%20%20%20Sessionization%20groups%20event%20data%20(like%20flights)%20into%20sessions%20based%20on%20common%0A%20%20%20%20attributes%20like%20date%2C%20carrier%2C%20and%20identifier%20(e.g.%2C%20tail%20number).%20This%20pattern%0A%20%20%20%20demonstrates%20the%20map%2Freduce%20approach%20where%20you%3A%0A%20%20%20%201.%20**Map**%20-%20Group%20events%20into%20sessions%20with%20aggregated%20measures%0A%20%20%20%202.%20**Nest**%20-%20Create%20nested%20lists%20of%20detailed%20events%20within%20each%20session%0A%20%20%20%203.%20**Reduce**%20-%20Unnest%20to%20normalize%20back%20to%20individual%20events%0A%0A%20%20%20%20**Malloy%20reference%3A**%20%5BSessionized%20Data%5D(https%3A%2F%2Fdocs.malloydata.dev%2Fdocumentation%2Fpatterns%2Fsessionize)%0A%0A%20%20%20%20This%20pattern%20is%20essential%20for%3A%0A%20%20%20%20-%20**Event%20sequencing**%20-%20Analyzing%20ordered%20sequences%20of%20events%0A%20%20%20%20-%20**Session%20metrics**%20-%20Calculating%20aggregates%20per%20session%0A%20%20%20%20-%20**Hierarchical%20data**%20-%20Building%20parent-child%20relationships%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20text_cell()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20ibis%0A%20%20%20%20from%20ibis%20import%20_%0A%20%20%20%20from%20boring_semantic_layer%20import%20to_semantic_table%2C%20to_ibis%0A%20%20%20%20import%20textwrap%0A%0A%20%20%20%20BASE_URL%20%3D%20%22https%3A%2F%2Fpub-a45a6a332b4646f2a6f44775695c64df.r2.dev%22%0A%0A%20%20%20%20%23%20Define%20code%20as%20strings%20for%20accordion%0A%20%20%20%20imports_code%20%3D%20textwrap.dedent(%22%22%22%5C%0A%20%20%20%20import%20ibis%0A%20%20%20%20from%20ibis%20import%20_%0A%20%20%20%20from%20boring_semantic_layer%20import%20to_semantic_table%2C%20to_ibis%0A%20%20%20%20%22%22%22)%0A%0A%20%20%20%20data_code%20%3D%20textwrap.dedent(f%22%22%22%5C%0A%20%20%20%20BASE_URL%20%3D%20%22%7BBASE_URL%7D%22%0A%20%20%20%20con%20%3D%20ibis.duckdb.connect(%22%3Amemory%3A%22)%0A%0A%20%20%20%20%23%20Load%20flights%20data%0A%20%20%20%20flights_tbl%20%3D%20con.read_parquet(f%22%7B%7BBASE_URL%7D%7D%2Fflights.parquet%22)%0A%20%20%20%20%22%22%22)%0A%0A%20%20%20%20semantic_code%20%3D%20textwrap.dedent(%22%22%22%5C%0A%20%20%20%20flights%20%3D%20(%0A%20%20%20%20%20%20%20%20to_semantic_table(flights_tbl%2C%20name%3D%22flights%22)%0A%20%20%20%20%20%20%20%20.with_measures(%0A%20%20%20%20%20%20%20%20%20%20%20%20flight_count%3Dlambda%20t%3A%20t.count()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20total_distance%3Dlambda%20t%3A%20t.distance.sum()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20max_delay%3Dlambda%20t%3A%20t.dep_delay.max()%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20%22%22%22)%0A%0A%20%20%20%20%23%20Execute%20setup%0A%20%20%20%20con%20%3D%20ibis.duckdb.connect(%22%3Amemory%3A%22)%0A%20%20%20%20flights_tbl%20%3D%20con.read_parquet(f%22%7BBASE_URL%7D%2Fflights.parquet%22)%0A%0A%20%20%20%20flights%20%3D%20to_semantic_table(flights_tbl%2C%20name%3D%22flights%22).with_measures(%0A%20%20%20%20%20%20%20%20flight_count%3Dlambda%20t%3A%20t.count()%2C%0A%20%20%20%20%20%20%20%20total_distance%3Dlambda%20t%3A%20t.distance.sum()%2C%0A%20%20%20%20%20%20%20%20max_delay%3Dlambda%20t%3A%20t.dep_delay.max()%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Display%20accordion%20with%20setup%20code%0A%20%20%20%20_title%20%3D%20mo.md(%22%23%23%20Define%20Semantic%20Model%22)%0A%20%20%20%20_desc%20%3D%20mo.md(%22We%20create%20a%20semantic%20table%20with%20flight%20measures%3A%22)%0A%20%20%20%20_accordion%20%3D%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%220%EF%B8%8F%E2%83%A3%20Imports%22%3A%20mo.md(f%22%60%60%60python%5Cn%7Bimports_code%7D%5Cn%60%60%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%221%EF%B8%8F%E2%83%A3%20Load%20data%22%3A%20mo.md(f%22%60%60%60python%5Cn%7Bdata_code%7D%5Cn%60%60%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%222%EF%B8%8F%E2%83%A3%20Define%20semantic%20table%22%3A%20mo.md(f%22%60%60%60python%5Cn%7Bsemantic_code%7D%5Cn%60%60%60%22)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B_title%2C%20_desc%2C%20_accordion%5D)%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20text_cell(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%23%23%20Create%20Sessions%20with%20Nested%20Flight%20Legs%0A%0A%20%20%20%20Filter%20for%20carrier%20WN%20on%202002-03-03%20and%20group%20flights%20into%20sessions%20by%0A%20%20%20%20aircraft%20(tail_num)%2C%20creating%20nested%20lists%20of%20flight%20legs%3A%0A%20%20%20%20%22%22%22%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%20q1%20%3D%20%22%22%22%0A%20%20%20%20flights.filter(%0A%20%20%20%20%20%20%20%20lambda%20t%3A%20(t.carrier%20%3D%3D%20%22WN%22)%20%26%20(t.dep_time.date()%20%3D%3D%20ibis.date(2002%2C%203%2C%203))%2C%0A%20%20%20%20)%0A%20%20%20%20.mutate(flight_date%3Dlambda%20t%3A%20t.dep_time.date())%0A%20%20%20%20.group_by(%22flight_date%22%2C%20%22carrier%22%2C%20%22tail_num%22)%0A%20%20%20%20.aggregate(%0A%20%20%20%20%20%20%20%20%22flight_count%22%2C%0A%20%20%20%20%20%20%20%20%22max_delay%22%2C%0A%20%20%20%20%20%20%20%20%22total_distance%22%2C%0A%20%20%20%20%20%20%20%20nest%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22flight_legs%22%3A%20lambda%20t%3A%20t.select(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22tail_num%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22dep_time%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22destination%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22dep_delay%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arr_delay%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20)%0A%20%20%20%20.mutate(session_id%3Dlambda%20t%3A%20ibis.row_number().over(ibis.window()))%0A%20%20%20%20.order_by(%22session_id%22)%0A%20%20%20%20%22%22%22%0A%0A%20%20%20%20q1_e%20%3D%20eval(%22(%22%20%2B%20q1%20%2B%20%22)%22)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(f%22%60%60%60python%5Cn%7Bq1%7D%5Cn%60%60%60%22)%2C%0A%20%20%20%20%20%20%20%20mo.ui.tabs(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%F0%9F%93%8A%20Table%22%3A%20mo.ui.table(q1_e.execute())%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%F0%9F%92%BB%20SQL%22%3A%20mo.md(f%22%60%60%60sql%5Cn%7Bq1_e.sql()%7D%5Cn%60%60%60%22)%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20text_cell(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%23%23%20Normalize%20Sessions%20(Unnest)%0A%0A%20%20%20%20Convert%20the%20nested%20sessions%20back%20to%20a%20flat%20table%20where%20each%20flight%20leg%0A%20%20%20%20is%20its%20own%20row.%20This%20demonstrates%20the%20%22reduce%22%20part%20of%20map%2Freduce%3A%0A%20%20%20%20%22%22%22%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%20%23%20Note%3A%20This%20requires%20running%20the%20previous%20query%20first%0A%20%20%20%20import%20ibis%0A%20%20%20%20from%20boring_semantic_layer%20import%20to_ibis%2C%20to_semantic_table%0A%0A%20%20%20%20BASE_URL%20%3D%20%22https%3A%2F%2Fpub-a45a6a332b4646f2a6f44775695c64df.r2.dev%22%0A%20%20%20%20con%20%3D%20ibis.duckdb.connect(%22%3Amemory%3A%22)%0A%20%20%20%20flights_tbl%20%3D%20con.read_parquet(f%22%7BBASE_URL%7D%2Fflights.parquet%22)%0A%0A%20%20%20%20flights%20%3D%20to_semantic_table(flights_tbl%2C%20name%3D%22flights%22).with_measures(%0A%20%20%20%20%20%20%20%20flight_count%3Dlambda%20t%3A%20t.count()%2C%0A%20%20%20%20%20%20%20%20total_distance%3Dlambda%20t%3A%20t.distance.sum()%2C%0A%20%20%20%20%20%20%20%20max_delay%3Dlambda%20t%3A%20t.dep_delay.max()%2C%0A%20%20%20%20)%0A%0A%20%20%20%20sessions%20%3D%20(%0A%20%20%20%20%20%20%20%20flights.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20lambda%20t%3A%20(t.carrier%20%3D%3D%20%22WN%22)%20%26%20(t.dep_time.date()%20%3D%3D%20ibis.date(2002%2C%203%2C%203))%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.mutate(flight_date%3Dlambda%20t%3A%20t.dep_time.date())%0A%20%20%20%20%20%20%20%20.group_by(%22flight_date%22%2C%20%22carrier%22%2C%20%22tail_num%22)%0A%20%20%20%20%20%20%20%20.aggregate(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22flight_count%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22max_delay%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22total_distance%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20nest%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22flight_legs%22%3A%20lambda%20t%3A%20t.select(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22tail_num%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22dep_time%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22destination%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22dep_delay%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arr_delay%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.mutate(session_id%3Dlambda%20t%3A%20ibis.row_number().over(ibis.window()))%0A%20%20%20%20%20%20%20%20.order_by(%22session_id%22)%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Normalize%20by%20unnesting%20flight_legs%0A%20%20%20%20sessions_ibis%20%3D%20to_ibis(sessions)%0A%20%20%20%20unnested%20%3D%20sessions_ibis.unnest(%22flight_legs%22)%0A%0A%20%20%20%20%23%20Unpack%20the%20struct%20fields%20into%20individual%20columns%0A%20%20%20%20struct_col%20%3D%20unnested.flight_legs%0A%20%20%20%20normalized%20%3D%20unnested.select(%0A%20%20%20%20%20%20%20%20%22flight_date%22%2C%0A%20%20%20%20%20%20%20%20%22carrier%22%2C%0A%20%20%20%20%20%20%20%20%22tail_num%22%2C%0A%20%20%20%20%20%20%20%20%22flight_count%22%2C%0A%20%20%20%20%20%20%20%20%22max_delay%22%2C%0A%20%20%20%20%20%20%20%20%22total_distance%22%2C%0A%20%20%20%20%20%20%20%20%22session_id%22%2C%0A%20%20%20%20%20%20%20%20leg_tail_num%3Dstruct_col.tail_num%2C%0A%20%20%20%20%20%20%20%20dep_time%3Dstruct_col.dep_time%2C%0A%20%20%20%20%20%20%20%20origin%3Dstruct_col.origin%2C%0A%20%20%20%20%20%20%20%20destination%3Dstruct_col.destination%2C%0A%20%20%20%20%20%20%20%20dep_delay%3Dstruct_col.dep_delay%2C%0A%20%20%20%20%20%20%20%20arr_delay%3Dstruct_col.arr_delay%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Unnested%20Flight%20Legs%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20Each%20row%20now%20represents%20a%20single%20flight%20leg%2C%20with%20session-level%0A%20%20%20%20%20%20%20%20aggregates%20preserved%20in%20each%20row%3A%0A%20%20%20%20%20%20%20%20%22%22%22)%2C%0A%20%20%20%20%20%20%20%20mo.ui.table(normalized.execute())%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20text_cell(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%23%23%20Key%20Insights%0A%0A%20%20%20%20The%20sessionization%20pattern%20demonstrates%3A%0A%20%20%20%20-%20**Aggregation**%20-%20Session-level%20metrics%20(flight_count%2C%20total_distance%2C%20max_delay)%0A%20%20%20%20-%20**Nesting**%20-%20Detailed%20flight%20legs%20nested%20within%20each%20session%0A%20%20%20%20-%20**Normalization**%20-%20Ability%20to%20unnest%20back%20to%20individual%20events%0A%0A%20%20%20%20This%20is%20powerful%20for%3A%0A%20%20%20%20-%20Analyzing%20aircraft%20daily%20operations%0A%20%20%20%20-%20Computing%20session-level%20statistics%0A%20%20%20%20-%20Maintaining%20hierarchical%20relationships%20while%20allowing%20flat%20views%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%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
ab4f4863f686c500d273ff7a43d86ebacb19b046bc68c93e21019e6029649df3