import%20marimo%0A%0A__generated_with%20%3D%20%220.23.9%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%20St.%20Petersburg%20housing%20market%20%E2%80%94%20the%20flood%20%26%20wind%20risk%20landscape%0A%0A%20%20%20%20A%20descriptive%20read%20of%20how%20the%20city's%20single-family%20housing%20stock%20is%20distributed%0A%20%20%20%20across%20**flood**%20risk%20(ground%20elevation%2C%20FEMA%20zone%2C%20realized%20NFIP%20claims)%20and%0A%20%20%20%20**wind**%20risk%20(construction%20type%2C%20age%20vs.%20building-code%20eras)%2C%20and%20how%20that%0A%20%20%20%20intersects%20price.%0A%0A%20%20%20%20**Scope.**%20All%20St-Pete%20single-family%20parcels%20(%60municipality%20%3D%20'ST%20PETERSBURG'%60%3B%0A%20%20%20%20%60parcels%60%20is%20already%20filtered%20to%20FL%20DOR%20use%20code%20%6001%60).%20Read-only%20against%0A%20%20%20%20%60analytics.db%60.%0A%0A%20%20%20%20**Sources.**%20%60parcels%60%20(flood_zone%2C%20evac_zone%2C%20construction_type%2C%20year_built%2C%0A%20%20%20%20sale_price%2C%20lat%2Flon)%2C%20the%20USGS%203DEP%20DEM%20(ground%20elevation)%2C%20and%20the%20realized-flood%0A%20%20%20%20layers%20%60flood_claims_bg%60%20%2B%20%60parcel_block_group%60.%0A%0A%20%20%20%20**Caveat%20(state%20it%20up%20front)%3A**%20there%20is%20**no%20roof-age%20field**%20in%20the%20data%20%E2%80%94%20only%0A%20%20%20%20%60roof_type%60.%20The%20%22roof%20%3E%2020%20yr%22%20wind%20disqualifier%20therefore%20can't%20be%20charted%0A%20%20%20%20directly%3B%20%60year_built%60%20is%20the%20available%20wind-code%20proxy.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%20%20%20%20from%20urllib.request%20import%20urlopen%0A%0A%20%20%20%20import%20altair%20as%20alt%0A%20%20%20%20import%20duckdb%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20rasterio%0A%0A%20%20%20%20return%20Path%2C%20alt%2C%20duckdb%2C%20mo%2C%20np%2C%20pd%2C%20rasterio%2C%20urlopen%0A%0A%0A%40app.cell%0Adef%20_(Path%2C%20duckdb)%3A%0A%20%20%20%20def%20_find_root()%20-%3E%20Path%3A%0A%20%20%20%20%20%20%20%20for%20d%20in%20%5BPath.cwd()%2C%20*Path.cwd().parents%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(d%20%2F%20%22analytics.db%22).exists()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20d%0A%20%20%20%20%20%20%20%20raise%20FileNotFoundError(%22analytics.db%20not%20found%20walking%20up%20from%20cwd%22)%0A%0A%20%20%20%20ROOT%20%3D%20_find_root()%0A%20%20%20%20conn%20%3D%20duckdb.connect(str(ROOT%20%2F%20%22analytics.db%22)%2C%20read_only%3DTrue)%20%20%23%20read-only%3A%20project%20convention%0A%20%20%20%20return%20ROOT%2C%20conn%0A%0A%0A%40app.cell%0Adef%20_(ROOT%2C%20mo%2C%20urlopen)%3A%0A%20%20%20%20%23%20USGS%203DEP%201%2F3%20arc-second%20tile%20covering%20Tampa%20Bay%20%2F%20St.%20Pete%20(NAVD88%20meters).%0A%20%20%20%20%23%20Regenerable%2C%20~300%20MB%20%E2%86%92%20gitignored%20under%20data%2Fdem%2F.%20Auto-download%20if%20missing.%0A%20%20%20%20DEM_PATH%20%3D%20ROOT%20%2F%20%22data%22%20%2F%20%22dem%22%20%2F%20%22USGS_13_n28w083.tif%22%0A%20%20%20%20DEM_URL%20%3D%20(%0A%20%20%20%20%20%20%20%20%22https%3A%2F%2Fprd-tnm.s3.amazonaws.com%2FStagedProducts%2FElevation%2F13%2FTIFF%2F%22%0A%20%20%20%20%20%20%20%20%22current%2Fn28w083%2FUSGS_13_n28w083.tif%22%0A%20%20%20%20)%0A%20%20%20%20if%20not%20DEM_PATH.exists()%3A%0A%20%20%20%20%20%20%20%20DEM_PATH.parent.mkdir(parents%3DTrue%2C%20exist_ok%3DTrue)%0A%20%20%20%20%20%20%20%20with%20urlopen(DEM_URL)%20as%20r%2C%20open(DEM_PATH%2C%20%22wb%22)%20as%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20f.write(r.read())%0A%20%20%20%20mo.md(f%22DEM%20tile%20ready%3A%20%60%7BDEM_PATH.relative_to(ROOT)%7D%60%22)%0A%20%20%20%20return%20(DEM_PATH%2C)%0A%0A%0A%40app.cell%0Adef%20_(DEM_PATH%2C%20conn%2C%20np%2C%20rasterio)%3A%0A%20%20%20%20%23%20One%20elevation%20sample%20per%20St-Pete%20SFR%20parcel%2C%20reused%20by%20several%20charts%20below.%0A%20%20%20%20%23%20parcel_id%20carried%20so%20charts%20can%20join%20to%20block%20group%20%2F%20construction%20%2F%20price.%0A%20%20%20%20_rows%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20SELECT%20parcel_id%2C%20latitude%2C%20longitude%2C%20construction_type%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20year_built%2C%20flood_zone%2C%20evac_zone%2C%20sale_price%0A%20%20%20%20%20%20%20%20FROM%20parcels%0A%20%20%20%20%20%20%20%20WHERE%20municipality%20%3D%20'ST%20PETERSBURG'%0A%20%20%20%20%20%20%20%20%20%20AND%20latitude%20IS%20NOT%20NULL%20AND%20longitude%20IS%20NOT%20NULL%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20with%20rasterio.open(DEM_PATH)%20as%20_ds%3A%0A%20%20%20%20%20%20%20%20_feet%20%3D%20np.array(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bv%5B0%5D%20for%20v%20in%20_ds.sample(zip(_rows.longitude%2C%20_rows.latitude))%5D%2C%20float%0A%20%20%20%20%20%20%20%20)%20*%203.28084%0A%20%20%20%20_rows%5B%22elev_ft%22%5D%20%3D%20_feet%0A%20%20%20%20parcels_geo%20%3D%20_rows%5Bnp.isfinite(_rows.elev_ft)%20%26%20(_rows.elev_ft%20%3E%20-50)%20%26%20(_rows.elev_ft%20%3C%20500)%5D.copy()%0A%20%20%20%20parcels_geo%0A%20%20%20%20return%20(parcels_geo%2C)%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%20Flood%20%E2%80%94%20designation%20vs.%20where%20it%20actually%20floods%0A%0A%20%20%20%20Each%20point%20is%20a%20**census%20block%20group**%20(~a%20few%20blocks).%20X%20%3D%20median%20ground%20elevation%3B%0A%20%20%20%20Y%20%3D%20realized%202024%20NFIP%20claims%20**per%20parcel**%20(%60flood_claims_bg%60)%3B%20size%20%3D%20parcels%3B%0A%20%20%20%20**color%20%3D%20share%20of%20the%20block%20group%20in%20FEMA%20Zone%20X**%20(blue%20%3D%20mostly%20Zone%20X%20%2F%20dry%20on%0A%20%20%20%20paper%2C%20red%20%3D%20mostly%20mapped%20flood%20zone).%20The%20y-axis%20is%20capped%20so%20the%20dense%20low-claim%0A%20%20%20%20cluster%20is%20legible%20%E2%80%94%20the%20few%20block%20groups%20above%20the%20cap%20are%20drawn%20as%20%E2%96%B2%20with%20their%20true%0A%20%20%20%20value.%20If%20realized%20flooding%20tracks%20the%20*ground*%2C%20claims%20fall%20with%20elevation%20regardless%0A%20%20%20%20of%20color%3B%20if%20it%20tracks%20the%20*label*%2C%20the%20red%20(flood-zone)%20points%20carry%20the%20claims.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(conn%2C%20parcels_geo)%3A%0A%20%20%20%20_claims%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22SELECT%20block_group%2C%20SUM(claim_count)%20AS%20claims_2024%20%22%0A%20%20%20%20%20%20%20%20%22FROM%20flood_claims_bg%20WHERE%20year%20%3D%202024%20GROUP%20BY%201%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20_xwalk%20%3D%20conn.execute(%22SELECT%20parcel_id%2C%20block_group%20FROM%20parcel_block_group%22).fetchdf()%0A%20%20%20%20_pg%20%3D%20parcels_geo.merge(_xwalk%2C%20on%3D%22parcel_id%22%2C%20how%3D%22inner%22)%0A%20%20%20%20_bg%20%3D%20(%0A%20%20%20%20%20%20%20%20_pg.groupby(%22block_group%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20parcels%3D(%22parcel_id%22%2C%20%22size%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20median_elev_ft%3D(%22elev_ft%22%2C%20%22median%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zone_x_share%3D(%22flood_zone%22%2C%20lambda%20s%3A%20(s%20%3D%3D%20%22X%22).mean())%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.reset_index()%0A%20%20%20%20)%0A%20%20%20%20bg_flood%20%3D%20_bg.merge(_claims%2C%20on%3D%22block_group%22%2C%20how%3D%22left%22)%0A%20%20%20%20bg_flood%5B%22claims_2024%22%5D%20%3D%20bg_flood%5B%22claims_2024%22%5D.fillna(0)%0A%20%20%20%20bg_flood%5B%22claims_per_parcel%22%5D%20%3D%20bg_flood%5B%22claims_2024%22%5D%20%2F%20bg_flood%5B%22parcels%22%5D%0A%20%20%20%20bg_flood%20%3D%20bg_flood%5Bbg_flood%5B%22parcels%22%5D%20%3E%3D%2010%5D%20%20%23%20drop%20tiny%20block%20groups%20(noise)%0A%20%20%20%20CPP_CAP%20%3D%201.2%20%20%23%20y%20cap%3A%20covers%20~99%25%20of%20block%20groups%3B%20the%203%20extreme%20ones%20pin%20above%20it%0A%20%20%20%20bg_flood%5B%22cpp_capped%22%5D%20%3D%20bg_flood%5B%22claims_per_parcel%22%5D.clip(upper%3DCPP_CAP)%0A%20%20%20%20bg_flood%5B%22over_cap%22%5D%20%3D%20bg_flood%5B%22claims_per_parcel%22%5D%20%3E%20CPP_CAP%0A%20%20%20%20bg_flood%0A%20%20%20%20return%20CPP_CAP%2C%20bg_flood%0A%0A%0A%40app.cell%0Adef%20_(CPP_CAP%2C%20alt%2C%20bg_flood%2C%20mo)%3A%0A%20%20%20%20_y%20%3D%20alt.Y(%22cpp_capped%3AQ%22%2C%20title%3D%222024%20NFIP%20claims%20per%20parcel%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scale%3Dalt.Scale(domain%3D%5B0%2C%20CPP_CAP%5D))%0A%20%20%20%20_x%20%3D%20alt.X(%22median_elev_ft%3AQ%22%2C%20title%3D%22Block-group%20median%20ground%20elevation%20(ft)%22)%0A%20%20%20%20_color%20%3D%20alt.Color(%22zone_x_share%3AQ%22%2C%20title%3D%22share%20in%20FEMA%20Zone%20X%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%20scale%3Dalt.Scale(scheme%3D%22redyellowblue%22%2C%20domain%3D%5B0%2C%201%5D))%0A%20%20%20%20_size%20%3D%20alt.Size(%22parcels%3AQ%22%2C%20title%3D%22parcels%22%2C%20scale%3Dalt.Scale(range%3D%5B20%2C%20400%5D))%0A%20%20%20%20_tip%20%3D%20%5B%0A%20%20%20%20%20%20%20%20alt.Tooltip(%22block_group%3AN%22)%2C%0A%20%20%20%20%20%20%20%20alt.Tooltip(%22parcels%3AQ%22%2C%20format%3D%22%2C%22)%2C%0A%20%20%20%20%20%20%20%20alt.Tooltip(%22median_elev_ft%3AQ%22%2C%20format%3D%22.0f%22%2C%20title%3D%22median%20elev%20(ft)%22)%2C%0A%20%20%20%20%20%20%20%20alt.Tooltip(%22claims_per_parcel%3AQ%22%2C%20format%3D%22.3f%22%2C%20title%3D%22claims%2Fparcel%22)%2C%0A%20%20%20%20%20%20%20%20alt.Tooltip(%22zone_x_share%3AQ%22%2C%20format%3D%22.0%25%22%2C%20title%3D%22Zone%20X%20share%22)%2C%0A%20%20%20%20%5D%0A%20%20%20%20_base%20%3D%20alt.Chart(bg_flood)%0A%20%20%20%20_pts%20%3D%20(%0A%20%20%20%20%20%20%20%20_base.transform_filter(%22!datum.over_cap%22)%0A%20%20%20%20%20%20%20%20.mark_circle(opacity%3D0.6)%0A%20%20%20%20%20%20%20%20.encode(x%3D_x%2C%20y%3D_y%2C%20color%3D_color%2C%20size%3D_size%2C%20tooltip%3D_tip)%0A%20%20%20%20)%0A%20%20%20%20_out%20%3D%20(%0A%20%20%20%20%20%20%20%20_base.transform_filter(%22datum.over_cap%22)%0A%20%20%20%20%20%20%20%20.mark_point(shape%3D%22triangle-up%22%2C%20filled%3DTrue%2C%20opacity%3D0.9%2C%20stroke%3D%22black%22%2C%20strokeWidth%3D0.6)%0A%20%20%20%20%20%20%20%20.encode(x%3D_x%2C%20y%3D_y%2C%20color%3D_color%2C%20size%3D_size%2C%20tooltip%3D_tip)%0A%20%20%20%20)%0A%20%20%20%20_lbl%20%3D%20(%0A%20%20%20%20%20%20%20%20_base.transform_filter(%22datum.over_cap%22)%0A%20%20%20%20%20%20%20%20.mark_text(dy%3D-11%2C%20fontSize%3D10%2C%20color%3D%22%23333%22)%0A%20%20%20%20%20%20%20%20.encode(x%3D_x%2C%20y%3D_y%2C%20text%3Dalt.Text(%22claims_per_parcel%3AQ%22%2C%20format%3D%22.1f%22))%0A%20%20%20%20)%0A%20%20%20%20_chart%20%3D%20(_pts%20%2B%20_out%20%2B%20_lbl).properties(%0A%20%20%20%20%20%20%20%20width%3D640%2C%20height%3D340%2C%0A%20%20%20%20%20%20%20%20title%3Df%22Realized%202024%20flood%20claims%20vs.%20elevation%20%E2%80%94%20%7Blen(bg_flood)%7D%20St-Pete%20block%20groups%22%2C%0A%20%20%20%20)%0A%20%20%20%20_n_over%20%3D%20int(bg_flood%5B%22over_cap%22%5D.sum())%0A%20%20%20%20mo.vstack(%5B_chart%2C%20mo.md(%0A%20%20%20%20%20%20%20%20f%22Y-axis%20capped%20at%20%7BCPP_CAP%3A.1f%7D%3B%20**%7B_n_over%7D%20block%20groups%20exceed%20it**%20(%E2%96%B2%2C%20true%20value%20%22%0A%20%20%20%20%20%20%20%20%22labeled)%20%E2%80%94%20all%20at%20low%20elevation.%20Color%20%3D%20block-group%20share%20in%20FEMA%20Zone%20X%20%22%0A%20%20%20%20%20%20%20%20%22(**red%20%3D%20mostly%20mapped%20flood%20zone%2C%20blue%20%3D%20mostly%20Zone%20X%20%2F%20dry%20on%20paper**).%20Claims%20%22%0A%20%20%20%20%20%20%20%20%22fall%20steeply%20with%20elevation%3B%20that%20the%20low-elevation%2C%20high-claim%20points%20skew%20red%20%22%0A%20%20%20%20%20%20%20%20%22means%20realized%20flooding%20and%20the%20FEMA%20label%20mostly%20agree%20here.%22%0A%20%20%20%20)%5D)%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%20Flood%20%E2%80%94%20the%20storm%20history%20(NFIP%20claims%20by%20ZIP%20%C3%97%20year)%0A%0A%20%20%20%20Realized%20flood-claim%20intensity%20per%20ZIP%20per%20year%2C%20**claims%20per%201%2C000%20homes**%20so%20big%20and%0A%20%20%20%20small%20ZIPs%20compare.%20NFIP%20flood%20claims%20only%20%E2%80%94%20not%20homeowners%2Fwind.%20Color%20is%20**symlog**%3A%0A%20%20%20%202024%20(Helene%2FMilton)%20is%20so%20large%20that%20a%20linear%20scale%20would%20wash%20every%20other%20year%20to%0A%20%20%20%20white%2C%20so%20symlog%20compresses%20it%20to%20keep%20the%20prior%20flares%20(2023%2C%202020%2C%202012%2C%202004)%20legible.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(conn)%3A%0A%20%20%20%20_claims%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20SELECT%20zip%2C%20year%2C%20SUM(claim_count)%20AS%20claims%2C%20SUM(total_paid)%20AS%20paid%0A%20%20%20%20%20%20%20%20FROM%20flood_claims%0A%20%20%20%20%20%20%20%20WHERE%20zip%20IN%20(SELECT%20DISTINCT%20zip%20FROM%20parcels%20WHERE%20municipality%20%3D%20'ST%20PETERSBURG')%0A%20%20%20%20%20%20%20%20%20%20AND%20year%20BETWEEN%201997%20AND%202025%0A%20%20%20%20%20%20%20%20GROUP%20BY%201%2C%202%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20_stock%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22SELECT%20zip%2C%20COUNT(*)%20AS%20parcels%20FROM%20parcels%20%22%0A%20%20%20%20%20%20%20%20%22WHERE%20municipality%20%3D%20'ST%20PETERSBURG'%20GROUP%20BY%201%20HAVING%20COUNT(*)%20%3E%3D%20100%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20claims_zy%20%3D%20_claims.merge(_stock%2C%20on%3D%22zip%22%2C%20how%3D%22inner%22)%20%20%23%20inner%3A%20drop%20sliver%2FZIP%2B4%20artifacts%0A%20%20%20%20claims_zy%5B%22claims_per_1k%22%5D%20%3D%201000%20*%20claims_zy%5B%22claims%22%5D%20%2F%20claims_zy%5B%22parcels%22%5D%0A%20%20%20%20claims_zy%0A%20%20%20%20return%20(claims_zy%2C)%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20claims_zy%2C%20mo)%3A%0A%20%20%20%20_heat%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(claims_zy)%0A%20%20%20%20%20%20%20%20.mark_rect(stroke%3D%22white%22%2C%20strokeWidth%3D0.3)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22year%3AO%22%2C%20title%3D%22Year%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22zip%3AN%22%2C%20title%3D%22ZIP%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sort%3Dalt.EncodingSortField(field%3D%22claims%22%2C%20op%3D%22sum%22%2C%20order%3D%22descending%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.Color(%22claims_per_1k%3AQ%22%2C%20title%3D%22claims%20%2F%201k%20homes%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%20scale%3Dalt.Scale(scheme%3D%22yelloworangered%22%2C%20type%3D%22symlog%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22zip%3AN%22)%2C%20alt.Tooltip(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22claims%3AQ%22%2C%20format%3D%22%2C%22%2C%20title%3D%22claims%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22paid%3AQ%22%2C%20format%3D%22%24%2C.0f%22%2C%20title%3D%22total%20paid%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22claims_per_1k%3AQ%22%2C%20format%3D%22.1f%22%2C%20title%3D%22claims%2F1k%20homes%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D700%2C%20height%3D320%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22NFIP%20flood%20claims%20by%20St-Pete%20ZIP%20%C3%97%20year%20%E2%80%94%20claims%20per%201%2C000%20homes%20(symlog)%22)%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5B_heat%2C%20mo.md(%0A%20%20%20%20%20%20%20%20%222024%20lights%20up%20every%20ZIP%3B%20coastal%2Flow%20ZIPs%20(33708%2C%2033715%2C%2033707%2C%2033703)%20carry%20the%20%22%0A%20%20%20%20%20%20%20%20%22intensity%20across%20the%20whole%20record%2C%20while%20the%20ridge%20ZIP%20**33713%20stays%20near-blank%20%22%0A%20%20%20%20%20%20%20%20%22(~2%20claims%2F1k%20over%2028%20years)**%20and%2033710%20is%20only%20modestly%20warm.%20ZIPs%20sorted%20by%20%22%0A%20%20%20%20%20%20%20%20%22total%20claims%3B%20ZIPs%20with%20%3C100%20St-Pete%20parcels%20dropped%20as%20noise.%22%0A%20%20%20%20)%5D)%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%20Wind%20%E2%80%94%20housing%20age%20vs.%20building-code%20eras%0A%0A%20%20%20%20Wind%20resilience%20is%20largely%20a%20function%20of%20*when*%20a%20house%20was%20built.%20The%20lines%20mark%0A%20%20%20%20Florida%20wind-code%20milestones%3A%20**1994**%20(post-Andrew%20tightening)%2C%20**2002**%20(first%0A%20%20%20%20statewide%20Florida%20Building%20Code)%2C%20**2007**%20(major%20FBC%20update).%20Stock%20to%20the%20left%20of%0A%20%20%20%202002%20predates%20the%20modern%20code.%20(No%20roof-age%20field%20exists%20%E2%80%94%20this%20is%20the%20age%20proxy.)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(conn%2C%20np%2C%20pd)%3A%0A%20%20%20%20_yr%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22SELECT%20year_built%20FROM%20parcels%20%22%0A%20%20%20%20%20%20%20%20%22WHERE%20municipality%20%3D%20'ST%20PETERSBURG'%20AND%20year_built%20BETWEEN%201900%20AND%202026%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20_edges%20%3D%20np.arange(1900%2C%202031%2C%205)%0A%20%20%20%20_counts%2C%20_%20%3D%20np.histogram(_yr.year_built%2C%20bins%3D_edges)%0A%20%20%20%20year_hist%20%3D%20pd.DataFrame(%7B%22yr_lo%22%3A%20_edges%5B%3A-1%5D%2C%20%22yr_hi%22%3A%20_edges%5B1%3A%5D%2C%20%22parcels%22%3A%20_counts%7D)%0A%20%20%20%20year_stats%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22n%22%3A%20int(len(_yr))%2C%0A%20%20%20%20%20%20%20%20%22median%22%3A%20int(_yr.year_built.median())%2C%0A%20%20%20%20%20%20%20%20%22pct_pre2002%22%3A%20float(100%20*%20(_yr.year_built%20%3C%202002).mean())%2C%0A%20%20%20%20%7D%0A%20%20%20%20return%20year_hist%2C%20year_stats%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20mo%2C%20pd%2C%20year_hist%2C%20year_stats)%3A%0A%20%20%20%20_bars%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(year_hist)%0A%20%20%20%20%20%20%20%20.mark_bar(color%3D%22%2374c476%22%2C%20stroke%3D%22white%22%2C%20strokeWidth%3D0.3)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22yr_lo%3AQ%22%2C%20title%3D%22Year%20built%22%2C%20scale%3Dalt.Scale(zero%3DFalse))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x2%3D%22yr_hi%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22parcels%3AQ%22%2C%20title%3D%22St-Pete%20SFR%20parcels%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5Balt.Tooltip(%22yr_lo%3AQ%22%2C%20title%3D%22from%22)%2C%20alt.Tooltip(%22yr_hi%3AQ%22%2C%20title%3D%22to%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22parcels%3AQ%22%2C%20format%3D%22%2C%22)%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_eras%20%3D%20pd.DataFrame(%7B%22yr%22%3A%20%5B1994%2C%202002%2C%202007%5D%2C%20%22label%22%3A%20%5B%221994%22%2C%20%222002%20FBC%22%2C%20%222007%22%5D%7D)%0A%20%20%20%20_rules%20%3D%20alt.Chart(_eras).mark_rule(color%3D%22%23cb181d%22%2C%20strokeDash%3D%5B5%2C%204%5D%2C%20size%3D1.5).encode(x%3D%22yr%3AQ%22)%0A%20%20%20%20_txt%20%3D%20alt.Chart(_eras).mark_text(angle%3D270%2C%20align%3D%22left%22%2C%20dx%3D4%2C%20dy%3D-6%2C%20color%3D%22%23cb181d%22).encode(%0A%20%20%20%20%20%20%20%20x%3D%22yr%3AQ%22%2C%20y%3Dalt.value(12)%2C%20text%3D%22label%3AN%22)%0A%20%20%20%20_chart%20%3D%20(_bars%20%2B%20_rules%20%2B%20_txt).properties(%0A%20%20%20%20%20%20%20%20width%3D640%2C%20height%3D300%2C%20title%3Df%22St-Pete%20SFR%20by%20year%20built%20%E2%80%94%20%7Byear_stats%5B'n'%5D%3A%2C%7D%20parcels%22)%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(f%22**Median%20build%20year%20%7Byear_stats%5B'median'%5D%7D.**%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22**%7Byear_stats%5B'pct_pre2002'%5D%3A.0f%7D%25**%20of%20the%20stock%20predates%20the%202002%20Florida%20Building%20Code.%22)%2C%0A%20%20%20%20%20%20%20%20_chart%2C%0A%20%20%20%20%5D)%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%20Wind%20%E2%80%94%20construction%20mix%20by%20ZIP%0A%0A%20%20%20%20Frame%20vs.%20block%20(masonry)%20share%20of%20each%20ZIP's%20single-family%20stock.%20Frame%20carries%0A%20%20%20%20materially%20higher%20wind%2Finsurance%20exposure%20than%20block.%20ZIPs%20sorted%20by%20frame%20share%0A%20%20%20%20(most%20wind-exposed%20at%20top).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(conn)%3A%0A%20%20%20%20_block_in%20%3D%20(%0A%20%20%20%20%20%20%20%20%22('CB%20STUCCO%2FCB%20RECLAD'%2C'CONCRETE%20BLOCK'%2C'MASONRY'%2C%22%0A%20%20%20%20%20%20%20%20%22'REINFORCED%20CONCRETE'%2C'MASONRY%20BRICK'%2C'MASONRY%20STONE')%22%0A%20%20%20%20)%0A%20%20%20%20_cz%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20SELECT%20zip%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COUNT(*)%20AS%20parcels%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20SUM((construction_type%20IN%20%7B_block_in%7D)%3A%3AINT)%20AS%20block%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20SUM((construction_type%20NOT%20IN%20%7B_block_in%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20OR%20construction_type%20IS%20NULL)%3A%3AINT)%20AS%20frame_other%0A%20%20%20%20%20%20%20%20FROM%20parcels%0A%20%20%20%20%20%20%20%20WHERE%20municipality%20%3D%20'ST%20PETERSBURG'%0A%20%20%20%20%20%20%20%20GROUP%20BY%201%20HAVING%20COUNT(*)%20%3E%3D%20100%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20).fetchdf()%0A%20%20%20%20_cz%5B%22frame_share%22%5D%20%3D%20_cz%5B%22frame_other%22%5D%20%2F%20_cz%5B%22parcels%22%5D%0A%20%20%20%20constr_zip%20%3D%20_cz.melt(%0A%20%20%20%20%20%20%20%20id_vars%3D%5B%22zip%22%2C%20%22parcels%22%2C%20%22frame_share%22%5D%2C%0A%20%20%20%20%20%20%20%20value_vars%3D%5B%22block%22%2C%20%22frame_other%22%5D%2C%0A%20%20%20%20%20%20%20%20var_name%3D%22construction%22%2C%20value_name%3D%22n%22%2C%0A%20%20%20%20)%0A%20%20%20%20constr_zip%5B%22construction%22%5D%20%3D%20constr_zip%5B%22construction%22%5D.map(%0A%20%20%20%20%20%20%20%20%7B%22block%22%3A%20%22block%20(masonry)%22%2C%20%22frame_other%22%3A%20%22frame%20%2F%20other%22%7D%0A%20%20%20%20)%0A%20%20%20%20constr_zip%0A%20%20%20%20return%20(constr_zip%2C)%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20constr_zip%2C%20mo)%3A%0A%20%20%20%20_chart%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(constr_zip)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22n%3AQ%22%2C%20stack%3D%22normalize%22%2C%20title%3D%22share%20of%20single-family%20parcels%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22zip%3AN%22%2C%20title%3D%22ZIP%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sort%3Dalt.EncodingSortField(field%3D%22frame_share%22%2C%20op%3D%22max%22%2C%20order%3D%22descending%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.Color(%22construction%3AN%22%2C%20title%3D%22construction%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%20scale%3Dalt.Scale(domain%3D%5B%22block%20(masonry)%22%2C%20%22frame%20%2F%20other%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%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20range%3D%5B%22%234575b4%22%2C%20%22%23d73027%22%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5Balt.Tooltip(%22zip%3AN%22)%2C%20alt.Tooltip(%22construction%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22n%3AQ%22%2C%20format%3D%22%2C%22%2C%20title%3D%22parcels%22)%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D560%2C%20height%3D380%2C%20title%3D%22Construction%20mix%20by%20St-Pete%20ZIP%20(block%20vs%20frame)%22)%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5B_chart%2C%20mo.md(%0A%20%20%20%20%20%20%20%20%22Frame%20(red)%20%3D%20wind%2Finsurance%20exposure.%20Downtown%20**33701%20(~60%25%20frame)**%20and%20older%20%22%0A%20%20%20%20%20%20%20%20%22inland%20ZIPs%20(33704%2C%2033714%2C%2033711)%20are%20most%20frame-built%3B%20newer%20coastal%20ZIPs%20%22%0A%20%20%20%20%20%20%20%20%22(33708%2C%2033715)%20and%2033710%20are%20mostly%20block.%20Note%20the%20cross-risk%20tension%3A%20the%20dry%20%22%0A%20%20%20%20%20%20%20%20%22ridge%20**33713**%20is%20flood-safe%20yet%20~40%25%20frame%2C%20while%20the%20wettest%20coastal%20ZIPs%20are%20%22%0A%20%20%20%20%20%20%20%20%22block-built%20%E2%80%94%20flood%20and%20wind%20exposure%20run%20somewhat%20opposite%20across%20the%20city.%22%0A%20%20%20%20)%5D)%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%20The%20two%20risks%20together%0A%0A%20%20%20%20Every%20parcel%20placed%20on%20both%20axes%20at%20once%3A%20**elevation%20band**%20(flood)%20%C3%97%20**construction**%0A%20%20%20%20(wind).%20The%20high-and-dry%20masonry%20cells%20(block%20row%2C%2030%E2%80%9340%20%2F%2040%2B%20ft)%20are%20the%20low-risk%20quadrant.%20Toggle%0A%20%20%20%20the%20shading%20between%20how%20many%20houses%20sit%20in%20each%20cell%20and%20what%20they%20cost.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20grid_metric%20%3D%20mo.ui.radio(%0A%20%20%20%20%20%20%20%20options%3D%5B%22parcel%20count%22%2C%20%22median%20price%22%5D%2C%20value%3D%22parcel%20count%22%2C%20inline%3DTrue%2C%0A%20%20%20%20%20%20%20%20label%3D%22Shade%20cells%20by%3A%22)%0A%20%20%20%20grid_metric%0A%20%20%20%20return%20(grid_metric%2C)%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20parcels_geo%2C%20pd)%3A%0A%20%20%20%20BLOCK%20%3D%20(%0A%20%20%20%20%20%20%20%20%22CB%20STUCCO%2FCB%20RECLAD%22%2C%20%22CONCRETE%20BLOCK%22%2C%20%22MASONRY%22%2C%0A%20%20%20%20%20%20%20%20%22REINFORCED%20CONCRETE%22%2C%20%22MASONRY%20BRICK%22%2C%20%22MASONRY%20STONE%22%2C%0A%20%20%20%20)%0A%20%20%20%20_df%20%3D%20parcels_geo.copy()%0A%20%20%20%20_df%5B%22wind%22%5D%20%3D%20np.where(_df.construction_type.isin(BLOCK)%2C%20%22block%20(masonry)%22%2C%20%22frame%20%2F%20other%22)%0A%20%20%20%20_bins%20%3D%20%5B-100%2C%2010%2C%2020%2C%2030%2C%2040%2C%201000%5D%0A%20%20%20%20band_order%20%3D%20%5B%22%3C10%22%2C%20%2210%E2%80%9320%22%2C%20%2220%E2%80%9330%22%2C%20%2230%E2%80%9340%22%2C%20%2240%2B%22%5D%0A%20%20%20%20_df%5B%22elev_band%22%5D%20%3D%20pd.cut(_df.elev_ft%2C%20bins%3D_bins%2C%20labels%3Dband_order)%0A%20%20%20%20_df%20%3D%20_df%5B_df.sale_price%20%3E%200%5D%0A%20%20%20%20risk_grid%20%3D%20(%0A%20%20%20%20%20%20%20%20_df.groupby(%5B%22elev_band%22%2C%20%22wind%22%5D%2C%20observed%3DTrue)%0A%20%20%20%20%20%20%20%20.agg(count%3D(%22parcel_id%22%2C%20%22size%22)%2C%20median_price%3D(%22sale_price%22%2C%20%22median%22))%0A%20%20%20%20%20%20%20%20.reset_index()%0A%20%20%20%20)%0A%20%20%20%20return%20band_order%2C%20risk_grid%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20band_order%2C%20grid_metric%2C%20mo%2C%20risk_grid)%3A%0A%20%20%20%20_field%20%3D%20%22count%22%20if%20grid_metric.value%20%3D%3D%20%22parcel%20count%22%20else%20%22median_price%22%0A%20%20%20%20_fmt%20%3D%20%22%2C%22%20if%20_field%20%3D%3D%20%22count%22%20else%20%22%24%2C.0f%22%0A%20%20%20%20_legend%20%3D%20%22parcels%22%20if%20_field%20%3D%3D%20%22count%22%20else%20%22median%20sale%20price%22%0A%20%20%20%20_heat%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(risk_grid)%0A%20%20%20%20%20%20%20%20.mark_rect()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22elev_band%3AO%22%2C%20sort%3Dband_order%2C%20title%3D%22Ground%20elevation%20band%20(ft)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22wind%3AO%22%2C%20title%3D%22Construction%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.Color(f%22%7B_field%7D%3AQ%22%2C%20title%3D_legend%2C%20scale%3Dalt.Scale(scheme%3D%22blues%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5Balt.Tooltip(%22elev_band%3AO%22)%2C%20alt.Tooltip(%22wind%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22count%3AQ%22%2C%20format%3D%22%2C%22)%2C%20alt.Tooltip(%22median_price%3AQ%22%2C%20format%3D%22%24%2C.0f%22)%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_text%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(risk_grid)%0A%20%20%20%20%20%20%20%20.mark_text(baseline%3D%22middle%22%2C%20fontWeight%3D%22bold%22)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22elev_band%3AO%22%2C%20sort%3Dband_order)%2C%20y%3D%22wind%3AO%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3Dalt.Text(f%22%7B_field%7D%3AQ%22%2C%20format%3D_fmt)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.value(%22%23222%22)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_chart%20%3D%20(_heat%20%2B%20_text).properties(%0A%20%20%20%20%20%20%20%20width%3D560%2C%20height%3D160%2C%20title%3Df%22St-Pete%20SFR%20by%20flood%20%C3%97%20wind%20risk%20%E2%80%94%20shaded%20by%20%7Bgrid_metric.value%7D%22)%0A%20%20%20%20mo.vstack(%5B_chart%2C%20mo.md(%0A%20%20%20%20%20%20%20%20%22Low-risk%20quadrant%20%3D%20**block**%20construction%20at%20**30%E2%80%9340%20%2F%2040%2B%20ft**.%20Switch%20to%20median%20%22%0A%20%20%20%20%20%20%20%20%22price%20to%20see%20whether%20that%20safety%20carries%20a%20premium.%22)%5D)%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%20Where%20the%20safe%20stock%20is%0A%0A%20%20%20%20Parcels%20aggregated%20to%20a%20~110%20m%20lat%2Flon%20grid%3B%20each%20cell%20colored%20by%20the%20**share%20of%20its%0A%20%20%20%20houses%20clearing%20all%20three%20of**%3A%20FEMA%20Zone%20X%2C%20block%20construction%2C%20and%20%E2%89%A5%2020%20ft.%20Green%20%3D%0A%20%20%20%20mostly%20buildable%2C%20red%20%3D%20mostly%20ruled%20out.%20The%20inland%20ridge%20(33713)%20vs.%20the%20low%20west%0A%20%20%20%20(33710)%20shows%20up%20directly.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(parcels_geo)%3A%0A%20%20%20%20GRID_DP%20%3D%202%20%20%23%20from%20Step%201%20%E2%80%94%203%20decimals%20produced%20%3E4000%20cells%2C%20so%20using%202%0A%20%20%20%20_BLOCK%20%3D%20(%0A%20%20%20%20%20%20%20%20%22CB%20STUCCO%2FCB%20RECLAD%22%2C%20%22CONCRETE%20BLOCK%22%2C%20%22MASONRY%22%2C%0A%20%20%20%20%20%20%20%20%22REINFORCED%20CONCRETE%22%2C%20%22MASONRY%20BRICK%22%2C%20%22MASONRY%20STONE%22%2C%0A%20%20%20%20)%0A%20%20%20%20_df%20%3D%20parcels_geo.copy()%0A%20%20%20%20_df%5B%22clears%22%5D%20%3D%20(%0A%20%20%20%20%20%20%20%20(_df.flood_zone%20%3D%3D%20%22X%22)%0A%20%20%20%20%20%20%20%20%26%20(_df.construction_type.isin(_BLOCK))%0A%20%20%20%20%20%20%20%20%26%20(_df.elev_ft%20%3E%3D%2020)%0A%20%20%20%20).astype(int)%0A%20%20%20%20_df%5B%22glat%22%5D%20%3D%20_df.latitude.round(GRID_DP)%0A%20%20%20%20_df%5B%22glon%22%5D%20%3D%20_df.longitude.round(GRID_DP)%0A%20%20%20%20risk_map%20%3D%20(%0A%20%20%20%20%20%20%20%20_df.groupby(%5B%22glat%22%2C%20%22glon%22%5D)%0A%20%20%20%20%20%20%20%20.agg(parcels%3D(%22parcel_id%22%2C%20%22size%22)%2C%20share_clear%3D(%22clears%22%2C%20%22mean%22))%0A%20%20%20%20%20%20%20%20.reset_index()%0A%20%20%20%20)%0A%20%20%20%20risk_map%20%3D%20risk_map%5Brisk_map.parcels%20%3E%3D%202%5D%20%20%23%20drop%20singleton%20cells%0A%20%20%20%20risk_map%0A%20%20%20%20return%20(risk_map%2C)%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20mo%2C%20risk_map)%3A%0A%20%20%20%20_chart%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(risk_map)%0A%20%20%20%20%20%20%20%20.mark_circle()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22glon%3AQ%22%2C%20title%3D%22Longitude%22%2C%20scale%3Dalt.Scale(zero%3DFalse))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22glat%3AQ%22%2C%20title%3D%22Latitude%22%2C%20scale%3Dalt.Scale(zero%3DFalse))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.Color(%22share_clear%3AQ%22%2C%20title%3D%22share%20clearing%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%20scale%3Dalt.Scale(scheme%3D%22redyellowgreen%22%2C%20domain%3D%5B0%2C%201%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20size%3Dalt.Size(%22parcels%3AQ%22%2C%20scale%3Dalt.Scale(range%3D%5B10%2C%20120%5D)%2C%20title%3D%22parcels%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5Balt.Tooltip(%22share_clear%3AQ%22%2C%20format%3D%22.0%25%22)%2C%20alt.Tooltip(%22parcels%3AQ%22%2C%20format%3D%22%2C%22)%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D620%2C%20height%3D520%2C%20title%3Df%22Share%20of%20houses%20clearing%20Zone%20X%20%2B%20block%20%2B%20%E2%89%A520%20ft%20%E2%80%94%20%7Blen(risk_map)%3A%2C%7D%20grid%20cells%22)%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5B_chart%2C%20mo.md(%0A%20%20%20%20%20%20%20%20%22Green%20clusters%20inland%20(the%20ridge)%3B%20red%20along%20the%20low%20coastal%2Fpeninsular%20edges.%22)%5D)%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
2893c0b9b8d91d5ee1c7d8899fe04464