%22%22%22%0ANYC%20Taxi%20Marimo%20-%20Notebook%2004%3A%20High-Volume%20FHV%20Deep%20Dive%0A%0ADeep%20analysis%20of%20Uber%2C%20Lyft%2C%20Via%2C%20and%20Juno%20trip%20data%20(HVFHS%20dataset).%0AThis%20is%20the%20richest%20dataset%20with%20detailed%20pricing%2C%20shared%20rides%2C%20and%20driver%20pay.%0A%0ALearning%20Objectives%3A%0A%20%20%20%201.%20Identify%20trips%20by%20company%20using%20hvfhs_license_num%0A%20%20%20%202.%20Analyze%20pricing%20structures%20(base%20fare%2C%20tips%2C%20driver%20pay)%0A%20%20%20%203.%20Explore%20shared%2Fpooled%20ride%20patterns%0A%20%20%20%204.%20Compare%20company%20market%20share%20and%20behaviour%0A%20%20%20%205.%20Investigate%20congestion%20pricing%20impact%20by%20company%0A%0ACompany%20Identification%3A%0A%20%20%20%20-%20HV0002%3A%20Juno%20(defunct%20since%202019%2C%20historical%20data%20only)%0A%20%20%20%20-%20HV0003%3A%20Uber%0A%20%20%20%20-%20HV0004%3A%20Via%0A%20%20%20%20-%20HV0005%3A%20Lyft%0A%0AData%20Richness%3A%0A%20%20%20%20Unlike%20basic%20FHV%20data%2C%20HVFHS%20includes%3A%0A%20%20%20%20-%20Detailed%20pricing%3A%20base_passenger_fare%2C%20tolls%2C%20tips%2C%20driver_pay%0A%20%20%20%20-%20Shared%20ride%20flags%3A%20shared_request_flag%2C%20shared_match_flag%0A%20%20%20%20-%20Accessibility%3A%20wav_request_flag%2C%20wav_match_flag%0A%20%20%20%20-%20Congestion%20fees%3A%20congestion_surcharge%2C%20cbd_congestion_fee%2C%20airport_fee%0A%0ATime%20estimate%3A%2090-120%20minutes%0A%22%22%22%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.19.5%22%0Aapp%20%3D%20marimo.App(width%3D%22full%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20datetime%20import%20datetime%0A%0A%20%20%20%20import%20duckdb%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20plotly.express%20as%20px%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20return%20datetime%2C%20duckdb%2C%20mo%2C%20pl%2C%20px%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20utils.company_codes%20import%20(%0A%20%20%20%20%20%20%20%20COMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20HVFHS_COMPANIES%2C%0A%20%20%20%20)%0A%20%20%20%20from%20utils.styling%20import%20(%0A%20%20%20%20%20%20%20%20format_currency%2C%0A%20%20%20%20%20%20%20%20format_large_number%2C%0A%20%20%20%20)%0A%20%20%20%20from%20utils.zone_lookup%20import%20(%0A%20%20%20%20%20%20%20%20MANHATTAN_CBD_ZONES%2C%0A%20%20%20%20%20%20%20%20load_zone_lookup%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20COMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20HVFHS_COMPANIES%2C%0A%20%20%20%20%20%20%20%20MANHATTAN_CBD_ZONES%2C%0A%20%20%20%20%20%20%20%20format_currency%2C%0A%20%20%20%20%20%20%20%20format_large_number%2C%0A%20%20%20%20%20%20%20%20load_zone_lookup%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(duckdb)%3A%0A%20%20%20%20conn%20%3D%20duckdb.connect()%0A%20%20%20%20return%20(conn%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20analysis_options%20%3D%20mo.ui.dictionary(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22sample_pct%22%3A%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20start%3D1%2C%20stop%3D100%2C%20step%3D1%2C%20value%3D5%2C%20label%3D%22Sample%20%25%20(HVFHS%20is%20large!)%22%0A%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%22include_dec_2024%22%3A%20mo.ui.checkbox(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22Include%20Dec%202024%20for%20YoY%20comparison%22%2C%20value%3DTrue%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20analysis_options%5B%22sample_pct%22%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20analysis_options%5B%22include_dec_2024%22%5D%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20gap%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(analysis_options%2C)%0A%0A%0A%40app.cell%0Adef%20_(conn%2C%20mo)%3A%0A%20%20%20%20_test_urls%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22Jan%202025%22%2C%20%22fhvhv_tripdata_2025-01.parquet%22)%2C%0A%20%20%20%20%20%20%20%20(%22Dec%202024%22%2C%20%22fhvhv_tripdata_2024-12.parquet%22)%2C%0A%20%20%20%20%20%20%20%20(%22Nov%202024%22%2C%20%22fhvhv_tripdata_2024-11.parquet%22)%2C%0A%20%20%20%20%20%20%20%20(%22Oct%202024%22%2C%20%22fhvhv_tripdata_2024-10.parquet%22)%2C%0A%20%20%20%20%20%20%20%20(%22Jan%202024%22%2C%20%22fhvhv_tripdata_2024-01.parquet%22)%2C%0A%20%20%20%20%5D%0A%0A%20%20%20%20_base%20%3D%20%22https%3A%2F%2Fd37ci6vzurychx.cloudfront.net%2Ftrip-data%22%0A%20%20%20%20_results%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20label%2C%20filename%20in%20_test_urls%3A%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_count%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22SELECT%20COUNT(*)%20FROM%20read_parquet('%7B_base%7D%2F%7Bfilename%7D')%20LIMIT%201%22%0A%20%20%20%20%20%20%20%20%20%20%20%20).fetchone()%5B0%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20_results.append(f%22%E2%9C%85%20%7Blabel%7D%3A%20Available%22)%0A%20%20%20%20%20%20%20%20except%20Exception%20as%20e%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_results.append(f%22%E2%9D%8C%20%7Blabel%7D%3A%20%7Bstr(e)%5B%3A50%5D%7D%22)%0A%0A%20%20%20%20mo.md(%22%5Cn%22.join(%5B%22%23%23%23%20HVFHS%20File%20Availability%22%5D%20%2B%20_results))%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(HVFHS_COMPANIES%2C%20analysis_options%2C%20datetime%2C%20duckdb%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_sample_pct%20%3D%20analysis_options.value%5B%22sample_pct%22%5D%0A%20%20%20%20_sample_clause%20%3D%20f%22USING%20SAMPLE%20%7B_sample_pct%7D%20PERCENT%22%20if%20_sample_pct%20%3C%20100%20else%20%22%22%0A%0A%20%20%20%20%23%20Fresh%20connection%20for%20HVFHS%0A%20%20%20%20_hvfhs_conn%20%3D%20duckdb.connect()%0A%0A%20%20%20%20%23%20Load%20Jan%202025%0A%20%20%20%20_hvfhs_jan%20%3D%20_hvfhs_conn.execute(f%22%22%22%0A%20%20%20%20%20%20%20%20SELECT%20%0A%20%20%20%20%20%20%20%20%20%20%20%20hvfhs_license_num%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dispatching_base_num%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20request_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pickup_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dropoff_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20PULocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20DOLocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20trip_miles%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20trip_time%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20base_passenger_fare%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tolls%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20bcf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sales_tax%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20congestion_surcharge%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20airport_fee%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tips%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20driver_pay%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20shared_request_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20shared_match_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20wav_request_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20wav_match_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cbd_congestion_fee%0A%20%20%20%20%20%20%20%20FROM%20read_parquet('data%2Ffhvhv_tripdata_2025-01.parquet')%0A%20%20%20%20%20%20%20%20WHERE%20base_passenger_fare%20%3E%200%0A%20%20%20%20%20%20%20%20%20%20AND%20trip_miles%20%3E%200%0A%20%20%20%20%20%20%20%20%7B_sample_clause%7D%0A%20%20%20%20%22%22%22).pl()%0A%0A%20%20%20%20%23%20Load%20Dec%202024%20if%20selected%0A%20%20%20%20if%20analysis_options.value%5B%22include_dec_2024%22%5D%3A%0A%20%20%20%20%20%20%20%20_hvfhs_dec%20%3D%20_hvfhs_conn.execute(f%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20SELECT%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hvfhs_license_num%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dispatching_base_num%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20request_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pickup_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dropoff_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20PULocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DOLocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trip_miles%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trip_time%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20base_passenger_fare%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tolls%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bcf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sales_tax%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20congestion_surcharge%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20airport_fee%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tips%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20driver_pay%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shared_request_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shared_match_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20wav_request_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20wav_match_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NULL%3A%3ADOUBLE%20as%20cbd_congestion_fee%0A%20%20%20%20%20%20%20%20%20%20%20%20FROM%20read_parquet('data%2Ffhvhv_tripdata_2024-12.parquet')%0A%20%20%20%20%20%20%20%20%20%20%20%20WHERE%20base_passenger_fare%20%3E%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20AND%20trip_miles%20%3E%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B_sample_clause%7D%0A%20%20%20%20%20%20%20%20%22%22%22).pl()%0A%0A%20%20%20%20%20%20%20%20hvfhs_df%20%3D%20pl.concat(%5B_hvfhs_jan%2C%20_hvfhs_dec%5D%2C%20how%3D%22diagonal%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20hvfhs_df%20%3D%20_hvfhs_jan%0A%0A%20%20%20%20%23%20Add%20derived%20columns%0A%20%20%20%20hvfhs_df%20%3D%20hvfhs_df.with_columns(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.hour().alias(%22hour%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.weekday().alias(%22weekday%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.date().alias(%22trip_date%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.day().alias(%22day%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.year().alias(%22year%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.month().alias(%22month%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22pickup_datetime%22)%20%3E%3D%20pl.lit(datetime(2025%2C%201%2C%205))).alias(%22post_congestion%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22hvfhs_license_num%22).replace(HVFHS_COMPANIES).alias(%22company%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20_months%20%3D%20%22Jan%202025%20%2B%20Dec%202024%22%20if%20analysis_options.value%5B%22include_dec_2024%22%5D%20else%20%22Jan%202025%22%0A%20%20%20%20mo.md(f%22**HVFHS%20Data**%3A%20%7Blen(hvfhs_df)%3A%2C%7D%20trips%20loaded%20(%7B_sample_pct%7D%25%20sample)%20-%20%7B_months%7D%22)%0A%20%20%20%20return%20(hvfhs_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_company_counts%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.group_by(%22company%22).agg(pl.len().alias(%22trips%22)).sort(%22trips%22%2C%20descending%3DTrue)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Company%20Distribution%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_company_counts%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Market%20Share%20Analysis%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(HVFHS_COMPANIES%2C%20conn%2C%20mo%2C%20pl)%3A%0A%20%20%20%20hvfhs_2024_df%20%3D%20conn.execute(%22%22%22%0A%20%20%20%20%20%20%20%20SELECT%0A%20%20%20%20%20%20%20%20%20%20%20%20hvfhs_license_num%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pickup_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dropoff_datetime%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20PULocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20DOLocationID%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20trip_miles%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20trip_time%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20base_passenger_fare%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tolls%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tips%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20driver_pay%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20shared_request_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20shared_match_flag%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20congestion_surcharge%0A%20%20%20%20%20%20%20%20FROM%20read_parquet('data%2Ffhvhv_tripdata_2024-01.parquet')%0A%20%20%20%20%20%20%20%20WHERE%20pickup_datetime%20%3E%3D%20'2024-01-01'%0A%20%20%20%20%20%20%20%20%20%20AND%20pickup_datetime%20%3C%20'2024-02-01'%0A%20%20%20%20%20%20%20%20%20%20AND%20base_passenger_fare%20%3E%200%0A%20%20%20%20%20%20%20%20%20%20AND%20trip_miles%20%3E%200%0A%20%20%20%20%20%20%20%20USING%20SAMPLE%205%20PERCENT%0A%20%20%20%20%22%22%22).pl()%0A%0A%20%20%20%20hvfhs_2024_df%20%3D%20hvfhs_2024_df.with_columns(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.hour().alias(%22hour%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.weekday().alias(%22weekday%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.date().alias(%22trip_date%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pickup_datetime%22).dt.day().alias(%22day%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.lit(2024).alias(%22year%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22hvfhs_license_num%22).replace(HVFHS_COMPANIES).alias(%22company%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.md(f%22**Jan%202024%20HVFHS%20baseline**%3A%20%7Blen(hvfhs_2024_df)%3A%2C%7D%20trips%20loaded%20(5%25%20sample)%22)%0A%20%20%20%20return%20(hvfhs_2024_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_market_share%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips%22))%0A%20%20%20%20%20%20%20%20.with_columns((pl.col(%22trips%22).cast(pl.Float64)%20%2F%20pl.col(%22trips%22).sum()%20*%20100).alias(%22pct%22))%0A%20%20%20%20%20%20%20%20.sort(%22trips%22%2C%20descending%3DTrue)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_market%20%3D%20px.pie(%0A%20%20%20%20%20%20%20%20_market_share.to_pandas()%2C%0A%20%20%20%20%20%20%20%20values%3D%22trips%22%2C%0A%20%20%20%20%20%20%20%20names%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22HVFHS%20Market%20Share%20(Jan%202025)%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20hole%3D0.4%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_market%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_market_share%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_daily_share%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22year%22)%20%3D%3D%202025)%0A%20%20%20%20%20%20%20%20.group_by(%5B%22trip_date%22%2C%20%22company%22%5D)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips%22))%0A%20%20%20%20%20%20%20%20.sort(%5B%22trip_date%22%2C%20%22company%22%5D)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_daily%20%3D%20px.area(%0A%20%20%20%20%20%20%20%20_daily_share.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22trip_date%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22trips%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Daily%20Trip%20Volume%20by%20Company%20(Jan%202025)%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22trip_date%22%3A%20%22Date%22%2C%20%22trips%22%3A%20%22Trips%22%2C%20%22company%22%3A%20%22Company%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Manual%20vline%20using%20add_shape%20instead%0A%20%20%20%20fig_daily.add_shape(%0A%20%20%20%20%20%20%20%20type%3D%22line%22%2C%0A%20%20%20%20%20%20%20%20x0%3D%222025-01-05%22%2C%0A%20%20%20%20%20%20%20%20x1%3D%222025-01-05%22%2C%0A%20%20%20%20%20%20%20%20y0%3D0%2C%0A%20%20%20%20%20%20%20%20y1%3D1%2C%0A%20%20%20%20%20%20%20%20yref%3D%22paper%22%2C%0A%20%20%20%20%20%20%20%20line%3Ddict(dash%3D%22dash%22%2C%20color%3D%22black%22%2C%20width%3D1)%2C%0A%20%20%20%20)%0A%20%20%20%20fig_daily.add_annotation(%0A%20%20%20%20%20%20%20%20x%3D%222025-01-05%22%2C%0A%20%20%20%20%20%20%20%20y%3D1%2C%0A%20%20%20%20%20%20%20%20yref%3D%22paper%22%2C%0A%20%20%20%20%20%20%20%20text%3D%22Congestion%20Pricing%22%2C%0A%20%20%20%20%20%20%20%20showarrow%3DFalse%2C%0A%20%20%20%20%20%20%20%20yshift%3D10%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_daily%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20pl%2C%20px)%3A%0A%20%20%20%20_hourly%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%5B%22hour%22%2C%20%22company%22%5D)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips%22))%0A%20%20%20%20%20%20%20%20.sort(%5B%22hour%22%2C%20%22company%22%5D)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_hourly%20%3D%20px.line(%0A%20%20%20%20%20%20%20%20_hourly.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22hour%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22trips%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Hourly%20Trip%20Pattern%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22hour%22%3A%20%22Hour%20of%20Day%22%2C%20%22trips%22%3A%20%22Trips%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20markers%3DTrue%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig_hourly.add_vrect(x0%3D7%2C%20x1%3D9%2C%20fillcolor%3D%22gray%22%2C%20opacity%3D0.1%2C%20annotation_text%3D%22AM%20Rush%22)%0A%20%20%20%20fig_hourly.add_vrect(x0%3D17%2C%20x1%3D19%2C%20fillcolor%3D%22gray%22%2C%20opacity%3D0.1%2C%20annotation_text%3D%22PM%20Rush%22)%0A%20%20%20%20fig_hourly.update_layout(xaxis%3Ddict(tickmode%3D%22linear%22%2C%20dtick%3D2))%0A%0A%20%20%20%20fig_hourly%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20load_zone_lookup%2C%20pl%2C%20px)%3A%0A%20%20%20%20_zones%20%3D%20load_zone_lookup(%22data%2Ftaxi_zone_lookup.csv%22)%0A%0A%20%20%20%20_borough_company%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.join(%0A%20%20%20%20%20%20%20%20%20%20%20%20_zones.select(%5B%22LocationID%22%2C%20%22Borough%22%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20left_on%3D%22PULocationID%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20right_on%3D%22LocationID%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20how%3D%22left%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%5B%22Borough%22%2C%20%22company%22%5D)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips%22))%0A%20%20%20%20%20%20%20%20.filter(pl.col(%22Borough%22).is_not_null())%0A%20%20%20%20)%0A%0A%20%20%20%20fig_borough%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_borough_company.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22Borough%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22trips%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20barmode%3D%22group%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Pickup%20Borough%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22Borough%22%3A%20%22Borough%22%2C%20%22trips%22%3A%20%22Trips%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig_borough%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Pricing%20Analysis%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_driver_analysis%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20(pl.col(%22driver_pay%22)%20%3E%200))%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20Total%20passenger%20cost%20(what%20rider%20pays%20minus%20tips%20which%20go%20to%20driver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22base_passenger_fare%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22tolls%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22bcf%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22sales_tax%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22congestion_surcharge%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22cbd_congestion_fee%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22airport_fee%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22total_passenger_cost%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22driver_pay%22)%20%2F%20pl.col(%22total_passenger_cost%22)%20*%20100).alias(%22driver_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22driver_pay%22).mean().alias(%22avg_driver_pay%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22total_passenger_cost%22).mean().alias(%22avg_passenger_cost%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22driver_pct%22).mean().alias(%22avg_driver_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20_fare_components%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22base_passenger_fare%22).mean().alias(%22Base%20Fare%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22tolls%22).fill_null(0).mean().alias(%22Tolls%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22tips%22).fill_null(0).mean().alias(%22Tips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22congestion_surcharge%22).fill_null(0).mean().alias(%22Congestion%20Surcharge%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22cbd_congestion_fee%22).fill_null(0).mean().alias(%22CBD%20Fee%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22airport_fee%22).fill_null(0).mean().alias(%22Airport%20Fee%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22bcf%22).fill_null(0).mean().alias(%22BCF%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22sales_tax%22).fill_null(0).mean().alias(%22Sales%20Tax%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Melt%20for%20stacked%20bar%0A%20%20%20%20_melted%20%3D%20_fare_components.unpivot(%0A%20%20%20%20%20%20%20%20index%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20variable_name%3D%22component%22%2C%0A%20%20%20%20%20%20%20%20value_name%3D%22amount%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig_components%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_melted.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22amount%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22component%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Average%20Fare%20Components%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22amount%22%3A%20%22Amount%20(%24)%22%7D%2C%0A%20%20%20%20%20%20%20%20barmode%3D%22stack%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_components%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22*BCF%20%3D%20Black%20Car%20Fund%2C%20a%20per-ride%20surcharge%20for%20driver%20benefits*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20fig_driver%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_driver_analysis.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22avg_driver_pct%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Driver%20Pay%20as%20%25%20of%20Passenger%20Cost%20(excl.%20tips)%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22avg_driver_pct%22%3A%20%22Driver%20%25%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22avg_driver_pct%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_driver.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_driver%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_driver_analysis.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_driver_pay%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_passenger_cost%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_driver_pct%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%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%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Driver%20pay%20%25%20excludes%20tips%20(which%20go%20directly%20to%20drivers)%20and%20tolls%20(reimbursed%20separately)%22%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%20%20%20%20kind%3D%22info%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%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_per_mile%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22post_congestion%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_miles%22)%20%3E%3D%200.5)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_miles%22)%20%3C%3D%2030)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22base_passenger_fare%22)%20%3E%200)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns((pl.col(%22base_passenger_fare%22)%20%2F%20pl.col(%22trip_miles%22)).alias(%22fare_per_mile%22))%0A%20%20%20%20%20%20%20%20.filter((pl.col(%22fare_per_mile%22)%20%3E%200)%20%26%20(pl.col(%22fare_per_mile%22)%20%3C%2050))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22fare_per_mile%22).mean().alias(%22avg_per_mile%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22fare_per_mile%22).median().alias(%22median_per_mile%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_per_mile%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_per_mile.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22avg_per_mile%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Average%20Fare%20per%20Mile%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22avg_per_mile%22%3A%20%22%24%2Fmile%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22avg_per_mile%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_per_mile.update_traces(texttemplate%3D%22%24%25%7Btext%3A.2f%7D%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_per_mile%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_per_mile.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_per_mile%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22median_per_mile%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20tip_analysis%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20(pl.col(%22base_passenger_fare%22)%20%3E%200))%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22tips%22).fill_null(0)%20%2F%20pl.col(%22base_passenger_fare%22)%20*%20100).alias(%22tip_pct%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22tips%22)%20%3E%200).sum().alias(%22trips_with_tip%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22tips%22).fill_null(0).mean().alias(%22avg_tip%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22tip_pct%22).mean().alias(%22avg_tip_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22trips_with_tip%22).cast(pl.Float64)%20%2F%20pl.col(%22trips%22)%20*%20100).alias(%22pct_tipped%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_tip%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20tip_analysis.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22pct_tipped%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22%25%20of%20Trips%20with%20Tips%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22pct_tipped%22%3A%20%22%25%20Tipped%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22pct_tipped%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_tip.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_tip%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tip_analysis.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_tip%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_tip_pct%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22pct_tipped%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20).select(%5B%22company%22%2C%20%22trips%22%2C%20%22pct_tipped%22%2C%20%22avg_tip%22%2C%20%22avg_tip_pct%22%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22*Unlike%20taxis%2C%20all%20rideshare%20tips%20are%20captured%20electronically*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Shared%20Rides%20Analysis%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_shared_requests%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22total_trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_request_flag%22)%20%3D%3D%20%22Y%22).sum().alias(%22shared_requested%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_requested%22).cast(pl.Float64)%20%2F%20pl.col(%22total_trips%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22request_pct%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_shared_req%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_shared_requests.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22request_pct%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22%25%20of%20Trips%20Requesting%20Shared%2FPool%20Ride%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22request_pct%22%3A%20%22%25%20Requested%20Shared%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22request_pct%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_shared_req.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_shared_req%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_shared_requests.with_columns(pl.col(%22request_pct%22).round(1))%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_match_rate%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20(pl.col(%22shared_request_flag%22)%20%3D%3D%20%22Y%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22shared_requested%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_match_flag%22)%20%3D%3D%20%22Y%22).sum().alias(%22shared_matched%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_matched%22).cast(pl.Float64)%20%2F%20pl.col(%22shared_requested%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22match_pct%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_match%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_match_rate.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22match_pct%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Shared%20Ride%20Match%20Success%20Rate%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22match_pct%22%3A%20%22%25%20Matched%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22match_pct%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_match.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_match%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_match_rate.with_columns(pl.col(%22match_pct%22).round(1))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22**Note**%3A%20Lyft%20flags%20rides%20where%20shared%20was%20requested%20but%20NOT%20matched%2C%20so%20Lyft's%20numbers%20may%20differ%22%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%20%20%20%20kind%3D%22info%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%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_savings%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22post_congestion%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22shared_request_flag%22)%20%3D%3D%20%22Y%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_miles%22)%20%3E%3D%200.5)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_miles%22)%20%3C%3D%2015)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns((pl.col(%22base_passenger_fare%22)%20%2F%20pl.col(%22trip_miles%22)).alias(%22fare_per_mile%22))%0A%20%20%20%20%20%20%20%20.group_by(%22shared_match_flag%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22base_passenger_fare%22).mean().alias(%22avg_fare%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22trip_miles%22).mean().alias(%22avg_miles%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22fare_per_mile%22).mean().alias(%22avg_per_mile%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.when(pl.col(%22shared_match_flag%22)%20%3D%3D%20%22Y%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(pl.lit(%22Matched%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.otherwise(pl.lit(%22Not%20Matched%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22status%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Shared%20Ride%20Savings%20(for%20those%20who%20requested)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_savings.select(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%22status%22%2C%20%22trips%22%2C%20%22avg_fare%22%2C%20%22avg_miles%22%2C%20%22avg_per_mile%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20).with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_fare%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_miles%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_per_mile%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%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%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22*Compare%20'Matched'%20vs%20'Not%20Matched'%20to%20estimate%20savings%20from%20successful%20pooling*%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_shared_hourly%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22hour%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22total%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_request_flag%22)%20%3D%3D%20%22Y%22).sum().alias(%22shared%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared%22).cast(pl.Float64)%20%2F%20pl.col(%22total%22)%20*%20100).alias(%22shared_pct%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.sort(%22hour%22)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_shared_hour%20%3D%20px.line(%0A%20%20%20%20%20%20%20%20_shared_hourly.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22hour%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22shared_pct%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Shared%20Ride%20Request%20Rate%20by%20Hour%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22hour%22%3A%20%22Hour%22%2C%20%22shared_pct%22%3A%20%22%25%20Requesting%20Shared%22%7D%2C%0A%20%20%20%20%20%20%20%20markers%3DTrue%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig_shared_hour.add_vrect(x0%3D7%2C%20x1%3D9%2C%20fillcolor%3D%22gray%22%2C%20opacity%3D0.1%2C%20annotation_text%3D%22AM%20Rush%22)%0A%20%20%20%20fig_shared_hour.add_vrect(%0A%20%20%20%20%20%20%20%20x0%3D17%2C%20x1%3D19%2C%20fillcolor%3D%22gray%22%2C%20opacity%3D0.1%2C%20annotation_text%3D%22PM%20Rush%22%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_shared_hour%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22*Commuters%20during%20rush%20hours%20may%20be%20more%20price-sensitive%20and%20request%20pooling*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Wheelchair%20Accessible%20Vehicles%20(WAV)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_wav_analysis%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22total_trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22wav_request_flag%22)%20%3D%3D%20%22Y%22).sum().alias(%22wav_requested%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20((pl.col(%22wav_request_flag%22)%20%3D%3D%20%22Y%22)%20%26%20(pl.col(%22wav_match_flag%22)%20%3D%3D%20%22Y%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.sum()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22wav_matched%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22wav_requested%22).cast(pl.Float64)%20%2F%20pl.col(%22total_trips%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22request_pct%22%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%20%20%20%20(pl.col(%22wav_matched%22).cast(pl.Float64)%20%2F%20pl.col(%22wav_requested%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22match_pct%22%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%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_wav%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_wav_analysis.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22match_pct%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22WAV%20Match%20Rate%20(%25%20of%20WAV%20requests%20fulfilled)%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22match_pct%22%3A%20%22%25%20Matched%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22match_pct%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_wav.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_wav%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_wav_analysis.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22request_pct%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22match_pct%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20).select(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22company%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22total_trips%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22wav_requested%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22wav_matched%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22request_pct%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22match_pct%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%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%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WAV%20availability%20is%20critical%20for%20accessibility.%20Low%20match%20rates%20indicate%20gaps%20in%20service.%22%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%20%20%20%20kind%3D%22info%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%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_wait_comparison%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22post_congestion%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20pl.col(%22request_datetime%22).is_not_null()%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20pl.col(%22pickup_datetime%22).is_not_null()%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22pickup_datetime%22)%20-%20pl.col(%22request_datetime%22)).dt.total_seconds()%20%2F%2060%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22wait_mins%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.filter((pl.col(%22wait_mins%22)%20%3E%200)%20%26%20(pl.col(%22wait_mins%22)%20%3C%2060))%0A%20%20%20%20%20%20%20%20.group_by(%22wav_request_flag%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22).mean().alias(%22avg_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22).median().alias(%22median_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.when(pl.col(%22wav_request_flag%22)%20%3D%3D%20%22Y%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(pl.lit(%22WAV%20Requested%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.otherwise(pl.lit(%22Standard%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22type%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Wait%20Time%3A%20WAV%20vs%20Standard%20Trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_wait_comparison.select(%5B%22type%22%2C%20%22trips%22%2C%20%22avg_wait%22%2C%20%22median_wait%22%5D).with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_wait%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22median_wait%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%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%20mo.md(%22*Longer%20WAV%20wait%20times%20indicate%20accessibility%20service%20gaps*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_cbd_by_company%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22total_trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22cbd_congestion_fee%22).fill_null(0)%20%3E%200).sum().alias(%22trips_with_fee%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22trips_with_fee%22).cast(pl.Float64)%20%2F%20pl.col(%22total_trips%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pct_with_fee%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_cbd_company%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_cbd_by_company.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22pct_with_fee%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22%25%20of%20Trips%20with%20CBD%20Fee%20by%20Company%20(Post%20Jan%205)%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22pct_with_fee%22%3A%20%22%25%20with%20Fee%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22pct_with_fee%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_cbd_company.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%25%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_cbd_company%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_cbd_by_company.with_columns(pl.col(%22pct_with_fee%22).round(1))%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_cbd_burden%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20(pl.col(%22cbd_congestion_fee%22).fill_null(0)%20%3E%200))%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22base_passenger_fare%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22tolls%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22tips%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22congestion_surcharge%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20pl.col(%22cbd_congestion_fee%22).fill_null(0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22total_cost%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22cbd_congestion_fee%22)%20%2F%20pl.col(%22total_cost%22)%20*%20100).alias(%22cbd_pct_of_total%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20_burden_by_distance%20%3D%20(%0A%20%20%20%20%20%20%20%20_cbd_burden.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.when(pl.col(%22trip_miles%22)%20%3C%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(pl.lit(%22Short%20(%3C2%20mi)%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.when(pl.col(%22trip_miles%22)%20%3C%205)%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(pl.lit(%22Medium%20(2-5%20mi)%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.otherwise(pl.lit(%22Long%20(5%2B%20mi)%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22distance_bucket%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%22distance_bucket%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22cbd_congestion_fee%22).mean().alias(%22avg_fee%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22total_cost%22).mean().alias(%22avg_total%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22cbd_pct_of_total%22).mean().alias(%22avg_cbd_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20CBD%20Fee%20Burden%20by%20Trip%20Distance%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_burden_by_distance.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_fee%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_total%22).round(2)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_cbd_pct%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%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%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22The%20%241.50%20CBD%20fee%20is%20a%20larger%20%25%20of%20short%20trips%20%E2%80%94%20a%20regressive%20impact%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind%3D%22warn%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%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MANHATTAN_CBD_ZONES%2C%20hvfhs_2024_df%2C%20hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_cbd_zones%20%3D%20set(MANHATTAN_CBD_ZONES)%0A%0A%20%20%20%20%23%202025%20CBD%20analysis%20(post-congestion)%0A%20%20%20%20_hvfhs_2025_cbd%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22PULocationID%22).is_in(_cbd_zones)%20%7C%20pl.col(%22DOLocationID%22).is_in(_cbd_zones)%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22cbd_trip%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%22cbd_trip%22)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips_2025%22))%0A%20%20%20%20)%0A%0A%20%20%20%20%23%202024%20CBD%20analysis%20(same%20period%3A%20Jan%205-31)%0A%20%20%20%20_hvfhs_2024_cbd%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_2024_df.filter(pl.col(%22day%22)%20%3E%3D%205)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22PULocationID%22).is_in(_cbd_zones)%20%7C%20pl.col(%22DOLocationID%22).is_in(_cbd_zones)%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22cbd_trip%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.group_by(%22cbd_trip%22)%0A%20%20%20%20%20%20%20%20.agg(pl.len().alias(%22trips_2024%22))%0A%20%20%20%20)%0A%0A%20%20%20%20hvfhs_cbd_yoy%20%3D%20_hvfhs_2025_cbd.join(_hvfhs_2024_cbd%2C%20on%3D%22cbd_trip%22%2C%20how%3D%22full%22).with_columns(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22trips_2025%22).cast(pl.Float64)%20-%20pl.col(%22trips_2024%22).cast(pl.Float64))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%20pl.col(%22trips_2024%22).cast(pl.Float64)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20100%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22change_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.when(pl.col(%22cbd_trip%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(pl.lit(%22CBD%20Trip%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.otherwise(pl.lit(%22Non-CBD%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22trip_type%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20HVFHS%20CBD%20vs%20Non-CBD%3A%20Year-over-Year%20(Jan%205-31)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hvfhs_cbd_yoy.select(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%22trip_type%22%2C%20%22trips_2024%22%2C%20%22trips_2025%22%2C%20%22change_pct%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20).with_columns(pl.col(%22change_pct%22).round(1))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22*Compare%20CBD%20trip%20change%20to%20assess%20if%20riders%20are%20avoiding%20Manhattan*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Trip%20Timing%20Analysis%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_wait_by_company%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22post_congestion%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20pl.col(%22request_datetime%22).is_not_null()%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20pl.col(%22pickup_datetime%22).is_not_null()%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22pickup_datetime%22)%20-%20pl.col(%22request_datetime%22)).dt.total_seconds()%20%2F%2060%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22wait_mins%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.filter((pl.col(%22wait_mins%22)%20%3E%200)%20%26%20(pl.col(%22wait_mins%22)%20%3C%2060))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22).mean().alias(%22avg_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22).median().alias(%22median_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22).quantile(0.9).alias(%22p90_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_wait%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_wait_by_company.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22avg_wait%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Average%20Wait%20Time%20by%20Company%20(Request%20to%20Pickup)%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22avg_wait%22%3A%20%22Avg%20Wait%20(mins)%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22avg_wait%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_wait.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%20min%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_wait%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_wait_by_company.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22avg_wait%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22median_wait%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22p90_wait%22).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(hvfhs_df%2C%20load_zone_lookup%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_zones%20%3D%20load_zone_lookup(%22data%2Ftaxi_zone_lookup.csv%22)%0A%0A%20%20%20%20_wait_heatmap%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20pl.col(%22request_datetime%22).is_not_null())%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22pickup_datetime%22)%20-%20pl.col(%22request_datetime%22)).dt.total_seconds()%20%2F%2060%0A%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22wait_mins%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.filter((pl.col(%22wait_mins%22)%20%3E%200)%20%26%20(pl.col(%22wait_mins%22)%20%3C%2060))%0A%20%20%20%20%20%20%20%20.join(%0A%20%20%20%20%20%20%20%20%20%20%20%20_zones.select(%5B%22LocationID%22%2C%20%22Borough%22%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20left_on%3D%22PULocationID%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20right_on%3D%22LocationID%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20how%3D%22left%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.filter(pl.col(%22Borough%22).is_not_null())%0A%20%20%20%20%20%20%20%20.group_by(%5B%22Borough%22%2C%20%22hour%22%5D)%0A%20%20%20%20%20%20%20%20.agg(pl.col(%22wait_mins%22).mean().alias(%22avg_wait%22))%0A%20%20%20%20)%0A%0A%20%20%20%20_pivot%20%3D%20_wait_heatmap.pivot(values%3D%22avg_wait%22%2C%20index%3D%22Borough%22%2C%20on%3D%22hour%22).fill_null(0)%0A%0A%20%20%20%20_boroughs%20%3D%20%5B%22Manhattan%22%2C%20%22Brooklyn%22%2C%20%22Queens%22%2C%20%22Bronx%22%2C%20%22Staten%20Island%22%5D%0A%20%20%20%20_borough_order%20%3D%20%5Bb%20for%20b%20in%20_boroughs%20if%20b%20in%20_pivot%5B%22Borough%22%5D.to_list()%5D%0A%0A%20%20%20%20fig_heatmap%20%3D%20px.imshow(%0A%20%20%20%20%20%20%20%20_pivot.filter(pl.col(%22Borough%22).is_in(_borough_order))%0A%20%20%20%20%20%20%20%20.sort(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22Borough%22).map_elements(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lambda%20x%3A%20_borough_order.index(x)%20if%20x%20in%20_borough_order%20else%2099%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return_dtype%3Dpl.Int64%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.select(pl.exclude(%22Borough%22))%0A%20%20%20%20%20%20%20%20.to_numpy()%2C%0A%20%20%20%20%20%20%20%20x%3Dlist(range(24))%2C%0A%20%20%20%20%20%20%20%20y%3D_borough_order%2C%0A%20%20%20%20%20%20%20%20labels%3Ddict(x%3D%22Hour%22%2C%20y%3D%22Borough%22%2C%20color%3D%22Wait%20(min)%22)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Average%20Wait%20Time%3A%20Borough%20%C3%97%20Hour%22%2C%0A%20%20%20%20%20%20%20%20color_continuous_scale%3D%22YlOrRd%22%2C%0A%20%20%20%20%20%20%20%20aspect%3D%22auto%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_heatmap%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22*Darker%20%3D%20longer%20wait%20times.%20Identify%20underserved%20areas%2Ftimes.*%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(COMPANY_COLORS%2C%20hvfhs_df%2C%20mo%2C%20pl%2C%20px)%3A%0A%20%20%20%20_speed_by_company%20%3D%20(%0A%20%20%20%20%20%20%20%20hvfhs_df.filter(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22post_congestion%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_time%22)%20%3E%2060)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_time%22)%20%3C%2010800)%0A%20%20%20%20%20%20%20%20%20%20%20%20%26%20(pl.col(%22trip_miles%22)%20%3E%200.5)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.with_columns((pl.col(%22trip_miles%22)%20%2F%20(pl.col(%22trip_time%22)%20%2F%203600)).alias(%22speed_mph%22))%0A%20%20%20%20%20%20%20%20.filter((pl.col(%22speed_mph%22)%20%3E%201)%20%26%20(pl.col(%22speed_mph%22)%20%3C%2060))%0A%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22speed_mph%22).mean().alias(%22avg_speed%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22speed_mph%22).median().alias(%22median_speed%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20fig_speed%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20_speed_by_company.to_pandas()%2C%0A%20%20%20%20%20%20%20%20x%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22avg_speed%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22company%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Average%20Trip%20Speed%20by%20Company%22%2C%0A%20%20%20%20%20%20%20%20labels%3D%7B%22company%22%3A%20%22Company%22%2C%20%22avg_speed%22%3A%20%22Avg%20Speed%20(mph)%22%7D%2C%0A%20%20%20%20%20%20%20%20color_discrete_map%3DCOMPANY_COLORS%2C%0A%20%20%20%20%20%20%20%20text%3D%22avg_speed%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig_speed.update_traces(texttemplate%3D%22%25%7Btext%3A.1f%7D%20mph%22%2C%20textposition%3D%22outside%22)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20fig_speed%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Speed%20should%20be%20similar%20across%20companies%20(same%20traffic).%20Differences%20may%20indicate%20routing%20efficiency.%22%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%20%20%20%20kind%3D%22info%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%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Company%20Comparison%20Dashboard%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(HVFHS_COMPANIES%2C%20mo)%3A%0A%20%20%20%20company_selector%20%3D%20mo.ui.multiselect(%0A%20%20%20%20%20%20%20%20options%3Dlist(HVFHS_COMPANIES.values())%2C%0A%20%20%20%20%20%20%20%20value%3D%5B%22Uber%22%2C%20%22Lyft%22%5D%2C%0A%20%20%20%20%20%20%20%20label%3D%22Select%20companies%20to%20compare%22%2C%0A%20%20%20%20)%0A%20%20%20%20company_selector%0A%20%20%20%20return%20(company_selector%2C)%0A%0A%0A%40app.cell%0Adef%20_(company_selector%2C%20format_currency%2C%20hvfhs_df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20_selected%20%3D%20company_selector.value%0A%0A%20%20%20%20if%20len(_selected)%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20output%20%3D%20mo.callout(mo.md(%22Select%20at%20least%20one%20company%22)%2C%20kind%3D%22warn%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_comparison%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20hvfhs_df.filter(pl.col(%22post_congestion%22)%20%26%20pl.col(%22company%22).is_in(_selected))%0A%20%20%20%20%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22pickup_datetime%22)%20-%20pl.col(%22request_datetime%22)).dt.total_seconds()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2060%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20).alias(%22wait_mins%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22tips%22).fill_null(0)%20%2F%20pl.col(%22base_passenger_fare%22)%20*%20100).alias(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22tip_pct%22%0A%20%20%20%20%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%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20.group_by(%22company%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.len().alias(%22trips%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22base_passenger_fare%22).mean().alias(%22avg_fare%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22wait_mins%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.filter((pl.col(%22wait_mins%22)%20%3E%200)%20%26%20(pl.col(%22wait_mins%22)%20%3C%2060))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.mean()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.alias(%22avg_wait%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22tip_pct%22).mean().alias(%22avg_tip_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_request_flag%22)%20%3D%3D%20%22Y%22).mean().alias(%22shared_rate%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22cbd_congestion_fee%22).fill_null(0)%20%3E%200).mean().alias(%22cbd_rate%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22shared_rate%22)%20*%20100).alias(%22shared_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(%22cbd_rate%22)%20*%20100).alias(%22cbd_pct%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20_cards%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20row%20in%20_comparison.iter_rows(named%3DTrue)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_cards.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22%23%23%23%20%7Brow%5B'company'%5D%7D%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Trips%22%2C%20value%3Df%22%7Brow%5B'trips'%5D%3A%2C%7D%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Avg%20Fare%22%2C%20value%3Dformat_currency(row%5B%22avg_fare%22%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22Avg%20Wait%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%3Df%22%7Brow%5B'avg_wait'%5D%3A.1f%7D%20min%22%20if%20row%5B%22avg_wait%22%5D%20else%20%22N%2FA%22%2C%0A%20%20%20%20%20%20%20%20%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%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Avg%20Tip%20%25%22%2C%20value%3Df%22%7Brow%5B'avg_tip_pct'%5D%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Shared%20Request%20%25%22%2C%20value%3Df%22%7Brow%5B'shared_pct'%5D%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22CBD%20Trip%20%25%22%2C%20value%3Df%22%7Brow%5B'cbd_pct'%5D%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20output%20%3D%20mo.hstack(_cards%2C%20justify%3D%22space-around%22)%0A%0A%20%20%20%20output%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Summary%20Dashboard%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MANHATTAN_CBD_ZONES%2C%0A%20%20%20%20format_currency%2C%0A%20%20%20%20format_large_number%2C%0A%20%20%20%20hvfhs_2024_df%2C%0A%20%20%20%20hvfhs_df%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20pl%2C%0A)%3A%0A%20%20%20%20_cbd_zones%20%3D%20set(MANHATTAN_CBD_ZONES)%0A%0A%20%20%20%20%23%202025%20stats%0A%20%20%20%20_h25%20%3D%20hvfhs_df.filter(pl.col(%22post_congestion%22))%0A%20%20%20%20_h25_trips%20%3D%20len(_h25)%0A%20%20%20%20_h25_fare%20%3D%20_h25%5B%22base_passenger_fare%22%5D.mean()%0A%20%20%20%20_h25_cbd_pct%20%3D%20(%0A%20%20%20%20%20%20%20%20_h25.filter(pl.col(%22cbd_congestion_fee%22).fill_null(0)%20%3E%200).height%20%2F%20_h25_trips%20*%20100%0A%20%20%20%20)%0A%0A%20%20%20%20%23%202024%20stats%0A%20%20%20%20_h24%20%3D%20hvfhs_2024_df.filter(pl.col(%22day%22)%20%3E%3D%205)%0A%20%20%20%20_h24_trips%20%3D%20len(_h24)%0A%20%20%20%20_trip_change%20%3D%20(_h25_trips%20-%20_h24_trips)%20%2F%20_h24_trips%20*%20100%0A%0A%20%20%20%20%23%20Market%20share%0A%20%20%20%20_uber_share%20%3D%20_h25.filter(pl.col(%22company%22)%20%3D%3D%20%22Uber%22).height%20%2F%20_h25_trips%20*%20100%0A%20%20%20%20_lyft_share%20%3D%20_h25.filter(pl.col(%22company%22)%20%3D%3D%20%22Lyft%22).height%20%2F%20_h25_trips%20*%20100%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Key%20Metrics%20(Jan%205-31%2C%202025)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22HVFHS%20Trips%22%2C%20value%3Dformat_large_number(_h25_trips))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22vs%202024%22%2C%20value%3Df%22%7B_trip_change%3A%2B.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Avg%20Base%20Fare%22%2C%20value%3Dformat_currency(_h25_fare))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22%25%20with%20CBD%20Fee%22%2C%20value%3Df%22%7B_h25_cbd_pct%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Uber%20Share%22%2C%20value%3Df%22%7B_uber_share%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.stat(label%3D%22Lyft%20Share%22%2C%20value%3Df%22%7B_lyft_share%3A.1f%7D%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20justify%3D%22space-around%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%5D%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
a8707ba41c0c865614579b1ffb29d27f