%23%20%2F%2F%2F%20script%0A%23%20%5Btool.marimo.opengraph%5D%0A%23%20title%20%3D%20%22Construction%20Cost%20EDA%22%0A%23%20description%20%3D%20%22Explore%20tabular%20and%20satellite%20feature%20distributions%20for%20the%20construction-cost%20dataset.%22%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.3%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22%2C%20auto_download%3D%5B%22html%22%5D)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Construction%20Cost%20Prediction%20(EDA)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20init()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20altair%20as%20alt%0A%20%20%20%20import%20duckdb%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20_%20%3D%20alt.data_transformers.enable(%22vegafusion%22)%0A%0A%20%20%20%20_con%20%3D%20duckdb.connect(%22inferred%2Fworkspace.duckdb%22%2C%20read_only%3DTrue)%0A%20%20%20%20df%20%3D%20_con.sql(%0A%20%20%20%20%20%20%20%20%22SELECT%20b.*%2C%20s.*%20EXCLUDE%20(location_id%2C%20timestamp%2C%20split)%20%22%0A%20%20%20%20%20%20%20%20%22FROM%20base_table%20b%20JOIN%20satellite_features%20s%20USING%20(location_id%2C%20timestamp)%22%0A%20%20%20%20).df()%0A%20%20%20%20_con.close()%0A%0A%20%20%20%20train_df%20%3D%20df%5Bdf%5B%22split%22%5D%20%3D%3D%20%22train%22%5D.reset_index(drop%3DTrue)%0A%20%20%20%20train_df%5B%22log_cost%22%5D%20%3D%20np.log(train_df%5B%22construction_cost_per_m2_usd%22%5D)%0A%20%20%20%20train_df%5B%22log_viirs%22%5D%20%3D%20np.log1p(train_df%5B%22viirs_mean%22%5D)%0A%20%20%20%20train_df%5B%22is_2020%22%5D%20%3D%20train_df%5B%22year%22%5D%20%3D%3D%202020%0A%20%20%20%20train_df%5B%22year_str%22%5D%20%3D%20train_df%5B%22year%22%5D.astype(str)%0A%20%20%20%20train_df%5B%22log_gdp%22%5D%20%3D%20np.log(train_df%5B%22deflated_gdp_usd%22%5D)%0A%0A%20%20%20%20COUNTRY_COLORS%20%3D%20alt.Scale(%0A%20%20%20%20%20%20%20%20domain%3D%5B%22Japan%22%2C%20%22Philippines%22%5D%2C%20range%3D%5B%22%231565C0%22%2C%20%22%23E65100%22%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22**Data%20loaded%3A**%20%7Blen(df)%3A%2C%7D%20total%20rows%20%E2%80%94%20%22%0A%20%20%20%20%20%20%20%20f%22%7Blen(train_df)%3A%2C%7D%20train%20and%20%7Blen(df)%20-%20len(train_df)%3A%2C%7D%20eval.%20%22%0A%20%20%20%20%20%20%20%20f%22%20DuckDB%20joined%20%7Btrain_df.shape%5B1%5D%7D%20features%20per%20row.%22%0A%20%20%20%20)%0A%20%20%20%20return%20COUNTRY_COLORS%2C%20alt%2C%20df%2C%20mo%2C%20np%2C%20pd%2C%20train_df%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20intro(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20What%20exactly%20are%20we%20predicting%3F%0A%0A%20%20%20%20The%20target%20**construction%20cost%20per%20square%20metre%20(USD%2Fm%C2%B2)**%20is%20a%20target%20value%20dependent%20on%20labour%20markets%2C%20material%20prices%2C%20economic%20development%2C%20urbanisation%2C%20geographic%20challenges...%20The%20data%20covers%20**Japan**%20and%20the%20**Philippines**%20across%20all%20quarters%20from%202019%20to%202024.%0A%0A%20%20%20%20**What%20do%20we%20have%3F**%0A%0A%20%20%20%20-%20**1024%20labelled%20training%20observations**%20across%20125%20distinct%20locations%0A%20%20%20%20-%20**Tabular%20metadata**%3A%20macroeconomic%20indicators%20(GDP%2C%20CPI)%2C%20geographic%20attributes%2C%20climate%20zone%2C%20access%20to%20infrastructure%20measures%0A%20%20%20%20-%20**Sentinel-2%20satellite%20images**%20with%2012%20bands.%20All%20the%20same%201024x1024%20pixel%20resolution%2C%20but%20optical%20resolution%20differ%20across%20bands.%20L2%3A%20Not%20raw%20data%2C%20but%20corrected%20for%20athmospheric%20disturbances.%20Clouds%20have%20been%20removed%2C%20but%20not%20by%20using%20the%20most%20modern%20and%20best%20performing%20model.%20All%20in%20all%20we%20derive%20from%20this%2038%20features%20based%20on%20summary%20statistics%2C%20including%3A%0A%20%20%20%20%20%20-%20NDVI%20(Normalized%20Difference%20Vegetation%20Index)%0A%20%20%20%20%20%20-%20NDBI%20(Normalized%20Difference%20Built-Up%20Index)%0A%20%20%20%20%20%20-%20NDWI%20(Normalized%20Difference%20Water%20Index)%0A%20%20%20%20-%20**Visible%20Infrared%20Imaging%20Radiometer%20Suite%20(VIIRS)**%20scaled%20to%20the%20same%20pixel%20resolution%20as%20Sentinel-2%20(effective%20optical%20ends%20up%20being%20very%20low).%20We%20derived%2011%20features.%20These%20appear%20to%20work%20well%20as%20a%20proxy%20for%20human%20economic%0A%20%20%20%20%20%20activity%20and%20urbanisation%20density%0A%0A%20%20%20%20The%20two%20satellite%20sources%20are%20displaying%20the%20same%20geographical%20areas%20for%20every%20location%20(same%20geotransform%20has%20been%20pre-applied%20for%20each%20location-date%20pair).%20Scaling%20(and%20hence%20optical%20resolution)%20is%20not%20the%20same%20across%20locations.%20It%20also%20varies%20hugely%20how%20much%20of%20the%20image%20deipicts%20the%20actual%20urbanized%20%22administrative%22%20area%20that%20the%20tabular%20data%20refers%20to.%0A%0A%20%20%20%20**Three%20questions%20to%20answer%3A**%0A%0A%20%20%20%201.%20What%20is%20the%20underlying%20factors%20of%20the%20huge%20cost%20gap%20between%20Japan%20and%20the%20Philippines%3F%0A%20%20%20%202.%20Is%202020%20somehow%20distinct%3F%20Did%20COVID-19%20disrupt%20normal%20construction%20cost%20patterns%3F%0A%20%20%20%203.%20Which%20features%20carry%20the%20strongest%20signal%2C%20and%20does%20it%20differ%20between%20countries%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20dataset_overview(df%2C%20mo%2C%20train_df)%3A%0A%20%20%20%20_n_train%20%3D%20len(train_df)%0A%20%20%20%20_n_eval%20%3D%20len(df)%20-%20_n_train%0A%20%20%20%20_n_locs%20%3D%20df%5B%22location_id%22%5D.nunique()%0A%20%20%20%20_year_min%20%3D%20int(train_df%5B%22year%22%5D.min())%0A%20%20%20%20_year_max%20%3D%20int(train_df%5B%22year%22%5D.max())%0A%20%20%20%20_n_jp%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Japan%22%5D%5B%22location_id%22%5D.nunique()%0A%20%20%20%20_n_ph%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Philippines%22%5D%5B%22location_id%22%5D.nunique()%0A%20%20%20%20_n_sat_feats%20%3D%20len(%0A%20%20%20%20%20%20%20%20%5Bc%20for%20c%20in%20train_df.columns%20if%20c.startswith(%22s2_%22)%20or%20c.startswith(%22viirs_%22)%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20What%20are%20we%20working%20with%3F%22)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B%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(f%22**%7B_n_train%20%2B%20_n_eval%3A%2C%7D**%20observations%5Cn%5Cn%7B_n_train%3A%2C%7D%20train%20%C2%B7%20%7B_n_eval%3A%2C%7D%20eval%22)%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%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**%7B_n_locs%7D**%20unique%20locations%5Cn%5Cn%7B_n_jp%7D%20Japan%20%C2%B7%20%7B_n_ph%7D%20Philippines%22)%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%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**6%20years**%20of%20data%5Cn%5Cn%7B_year_min%7D%E2%80%93%7B_year_max%7D%2C%20quarterly%22)%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%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**%7B_n_sat_feats%7D**%20satellite%20features%5Cn%5CnS2%20bands%2C%20indices%2C%20VIIRS%22)%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)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20location_split_imbalance(COUNTRY_COLORS%2C%20alt%2C%20df%2C%20mo%2C%20pd)%3A%0A%0A%20%20%20%20_loc_counts%20%3D%20(%0A%20%20%20%20%20%20%20%20df.assign(%0A%20%20%20%20%20%20%20%20%20%20%20%20train_flag%3D(df%5B%22split%22%5D%20%3D%3D%20%22train%22).astype(int)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20eval_flag%3D(df%5B%22split%22%5D%20%3D%3D%20%22eval%22).astype(int)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.groupby(%5B%22location_id%22%2C%20%22geolocation_name%22%2C%20%22country%22%5D%2C%20as_index%3DFalse)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20min_year%3D(%22year%22%2C%20%22min%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20max_year%3D(%22year%22%2C%20%22max%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20total_rows%3D(%22split%22%2C%20%22size%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20train_rows%3D(%22train_flag%22%2C%20%22sum%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20eval_rows%3D(%22eval_flag%22%2C%20%22sum%22)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_loc_counts%5B%22train_share%22%5D%20%3D%20_loc_counts%5B%22train_rows%22%5D%20%2F%20_loc_counts%5B%22total_rows%22%5D%0A%20%20%20%20_loc_counts%5B%22eval_share%22%5D%20%3D%20_loc_counts%5B%22eval_rows%22%5D%20%2F%20_loc_counts%5B%22total_rows%22%5D%0A%20%20%20%20_loc_counts%5B%22gap%22%5D%20%3D%20_loc_counts%5B%22eval_rows%22%5D%20-%20_loc_counts%5B%22train_rows%22%5D%0A%20%20%20%20_loc_counts%5B%22eval_train_ratio%22%5D%20%3D%20(%0A%20%20%20%20%20%20%20%20_loc_counts%5B%22eval_rows%22%5D%20%2F%20_loc_counts%5B%22train_rows%22%5D%0A%20%20%20%20).round(2)%0A%20%20%20%20_loc_counts%5B%22year_range%22%5D%20%3D%20(%0A%20%20%20%20%20%20%20%20_loc_counts%5B%22min_year%22%5D.astype(str)%20%2B%20%22-%22%20%2B%20_loc_counts%5B%22max_year%22%5D.astype(str)%0A%20%20%20%20)%0A%0A%20%20%20%20_top_imbalanced%20%3D%20_loc_counts.sort_values(%0A%20%20%20%20%20%20%20%20%5B%22train_share%22%2C%20%22eval_rows%22%2C%20%22train_rows%22%2C%20%22country%22%2C%20%22geolocation_name%22%5D%2C%0A%20%20%20%20%20%20%20%20ascending%3D%5BTrue%2C%20False%2C%20True%2C%20True%2C%20True%5D%2C%0A%20%20%20%20).reset_index(drop%3DTrue)%0A%0A%20%20%20%20_totals%20%3D%20df%5B%22split%22%5D.value_counts()%0A%20%20%20%20_n_partial_ph%20%3D%20int(%0A%20%20%20%20%20%20%20%20((_loc_counts%5B%22country%22%5D%20%3D%3D%20%22Philippines%22)%20%26%20(_loc_counts%5B%22total_rows%22%5D%20%3C%2012)).sum()%0A%20%20%20%20)%0A%0A%0A%20%20%20%20def%20_country_scatter(_country%2C%20_max_rows)%3A%0A%20%20%20%20%20%20%20%20_data%20%3D%20_loc_counts%5B_loc_counts%5B%22country%22%5D%20%3D%3D%20_country%5D%0A%20%20%20%20%20%20%20%20_points%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Chart(_data)%0A%20%20%20%20%20%20%20%20%20%20%20%20.mark_circle(size%3D85%2C%20opacity%3D0.75)%0A%20%20%20%20%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22train_rows%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Train%20rows%20per%20location%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scale%3Dalt.Scale(domain%3D%5B0%2C%20_max_rows%5D%2C%20nice%3DFalse)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eval_rows%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Evaluation%20rows%20per%20location%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scale%3Dalt.Scale(domain%3D%5B0%2C%20_max_rows%5D%2C%20nice%3DFalse)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%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%20%20%20%20%20alt.Tooltip(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year_range%3AN%22%2C%20title%3D%22Year%20range%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22total_rows%3AQ%22%2C%20title%3D%22Total%20rows%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22train_rows%3AQ%22%2C%20title%3D%22Train%20rows%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22eval_rows%3AQ%22%2C%20title%3D%22Eval%20rows%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22train_share%3AQ%22%2C%20title%3D%22Train%20share%22%2C%20format%3D%22.0%25%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22eval_share%3AQ%22%2C%20title%3D%22Eval%20share%22%2C%20format%3D%22.0%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)%0A%20%20%20%20%20%20%20%20%20%20%20%20.properties(width%3D250%2C%20height%3D240%2C%20title%3D_country)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_diag%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Chart(pd.DataFrame(%7B%22train_rows%22%3A%20%5B0%2C%20_max_rows%5D%2C%20%22eval_rows%22%3A%20%5B0%2C%20_max_rows%5D%7D))%0A%20%20%20%20%20%20%20%20%20%20%20%20.mark_line(color%3D%22%235F6368%22%2C%20strokeDash%3D%5B6%2C%204%5D%2C%20opacity%3D0.9)%0A%20%20%20%20%20%20%20%20%20%20%20%20.encode(x%3D%22train_rows%3AQ%22%2C%20y%3D%22eval_rows%3AQ%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20return%20alt.layer(_points%2C%20_diag)%0A%0A%0A%20%20%20%20_scatter%20%3D%20alt.hconcat(%0A%20%20%20%20%20%20%20%20_country_scatter(%22Japan%22%2C%2024)%2C%0A%20%20%20%20%20%20%20%20_country_scatter(%22Philippines%22%2C%2012)%2C%0A%20%20%20%20).properties(title%3D%22Per-location%20split%20counts%22)%0A%0A%0A%20%20%20%20def%20_country_hist(_country)%3A%0A%20%20%20%20%20%20%20%20_data%20%3D%20_loc_counts%5B_loc_counts%5B%22country%22%5D%20%3D%3D%20_country%5D%0A%20%20%20%20%20%20%20%20_bars%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Chart(_data)%0A%20%20%20%20%20%20%20%20%20%20%20%20.mark_bar(opacity%3D0.8%2C%20binSpacing%3D1)%0A%20%20%20%20%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22train_share%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bin%3Dalt.Bin(step%3D0.1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Train%20share%20of%20available%20rows%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scale%3Dalt.Scale(domain%3D%5B0%2C%201%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22count()%3AQ%22%2C%20title%3D%22Locations%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%5Balt.Tooltip(%22count()%3AQ%22%2C%20title%3D%22Locations%22)%5D%2C%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.properties(width%3D250%2C%20height%3D180%2C%20title%3D_country)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_rule%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Chart(pd.DataFrame(%7B%22train_share%22%3A%20%5B0.5%5D%7D))%0A%20%20%20%20%20%20%20%20%20%20%20%20.mark_rule(color%3D%22%23C62828%22%2C%20strokeDash%3D%5B5%2C%203%5D%2C%20strokeWidth%3D2)%0A%20%20%20%20%20%20%20%20%20%20%20%20.encode(x%3D%22train_share%3AQ%22)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20return%20alt.layer(_bars%2C%20_rule)%0A%0A%0A%20%20%20%20_hist%20%3D%20alt.hconcat(%0A%20%20%20%20%20%20%20%20_country_hist(%22Japan%22)%2C%0A%20%20%20%20%20%20%20%20_country_hist(%22Philippines%22)%2C%0A%20%20%20%20).properties(title%3D%22Train-share%20distribution%20by%20country%22)%0A%0A%20%20%20%20_table%20%3D%20mo.ui.table(%0A%20%20%20%20%20%20%20%20_top_imbalanced.loc%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%3A%2C%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%22geolocation_name%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22country%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22year_range%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22total_rows%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22train_rows%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eval_rows%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22train_share%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22gap%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eval_train_ratio%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%5D.rename(%0A%20%20%20%20%20%20%20%20%20%20%20%20columns%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22geolocation_name%22%3A%20%22location%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22year_range%22%3A%20%22years%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22total_rows%22%3A%20%22rows%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22train_rows%22%3A%20%22train%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eval_rows%22%3A%20%22eval%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20pagination%3DTrue%2C%0A%20%20%20%20%20%20%20%20page_size%3D10%2C%0A%20%20%20%20%20%20%20%20selection%3DNone%2C%0A%20%20%20%20%20%20%20%20show_download%3DFalse%2C%0A%20%20%20%20%20%20%20%20format_mapping%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22train_share%22%3A%20lambda%20x%3A%20f%22%7Bx%3A.0%25%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22eval_train_ratio%22%3A%20lambda%20x%3A%20f%22%7Bx%3A.2f%7Dx%22%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20freeze_columns_left%3D%5B%22location%22%5D%2C%0A%20%20%20%20%20%20%20%20label%3D%22Locations%20ranked%20by%20lowest%20train%20share%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Imbalanced%20split%3F%22)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22The%20full%20dataset%20is%20balanced%20overall%20(as%20can%20be%20seen%20above%3B%20**%7Bint(_totals%5B'train'%5D)%3A%2C%7D**%20train%20and%20**%7Bint(_totals%5B'eval'%5D)%3A%2C%7D**%20eval%20rows)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22but%20this%20balance%20is%20not%20uniform%20across%20locations.%20Japan%20contributes%2024%20quarters%20per%20location%20(2019-2024)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22most%20Philippines%20locations%20contribute%2012%20(2019-2021)%2C%20and%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22**%7B_n_partial_ph%7D**%20Philippines%20locations%20have%20even%20fewer%20training%20samples.%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%20kind%3D%22warn%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_scatter%2C%20_hist%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Locations%20with%20the%20least%20training%20samples%22)%2C%0A%20%20%20%20%20%20%20%20_table%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cost_by_country(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20train_df)%3A%0A%20%20%20%20_jp%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Japan%22%5D%0A%20%20%20%20_ph%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Philippines%22%5D%0A%20%20%20%20_jp_med%20%3D%20float(_jp%5B%22construction_cost_per_m2_usd%22%5D.median())%0A%20%20%20%20_ph_med%20%3D%20float(_ph%5B%22construction_cost_per_m2_usd%22%5D.median())%0A%20%20%20%20_ratio%20%3D%20_jp_med%20%2F%20_ph_med%0A%0A%20%20%20%20_hist%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_bar(opacity%3D0.75%2C%20binSpacing%3D1)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22log_cost%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bin%3Dalt.Bin(maxbins%3D28)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%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%20%20%20%20alt.Y(%22count()%3AQ%22%2C%20title%3D%22Locations%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.facet(facet%3Dalt.Facet(%22country%3AN%22%2C%20title%3DNone)%2C%20columns%3D2)%0A%20%20%20%20%20%20%20%20.resolve_scale(y%3D%22independent%22)%0A%20%20%20%20%20%20%20%20.properties(title%3D%22Cost%20distribution%20by%20country%20(natural%20log%20scale)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_box%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_boxplot(extent%3D%22min-max%22%2C%20size%3D40)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22country%3AN%22%2C%20title%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22construction_cost_per_m2_usd%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Construction%20cost%20(USD%2Fm%C2%B2)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scale%3Dalt.Scale(type%3D%22log%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%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D220%2C%20height%3D300%2C%20title%3D%22Spread%20(log%20scale)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Cost%20in%20Japan%20vs%20Philippines%22)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_hist%2C%20_box%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22Japan's%20median%20construction%20cost%20is%20%24%7B_jp_med%3A%2C.0f%7D%2Fm%C2%B2%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22vs.%20%24%7B_ph_med%3A%2C.0f%7D%2Fm%C2%B2%20in%20the%20Philippines%2C%20which%20is%20a%20**%7B_ratio%3A.1f%7D%C3%97%20gap**.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22How%20constructions%20are%20made%20and%20the%20infrastructure%20behind%20construction%2C%20is%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22likely%20structurally%20different%20between%20the%20countries.%20Do%20we%20need%20to%20modell%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22them%20separately%20to%20allowed%20the%20model%20to%20learn%20country-specific%20signals%3F%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%20kind%3D%22success%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20temporal_trends(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20pd%2C%20train_df)%3A%0A%20%20%20%20_yearly%20%3D%20(%0A%20%20%20%20%20%20%20%20train_df.groupby(%5B%22year%22%2C%20%22country%22%5D)%5B%22construction_cost_per_m2_usd%22%5D%0A%20%20%20%20%20%20%20%20.agg(%5B%22median%22%2C%20%22mean%22%2C%20%22std%22%5D)%0A%20%20%20%20%20%20%20%20.reset_index()%0A%20%20%20%20)%0A%20%20%20%20_yearly.columns%20%3D%20%5B%22year%22%2C%20%22country%22%2C%20%22median_cost%22%2C%20%22mean_cost%22%2C%20%22std_cost%22%5D%0A%20%20%20%20_yearly%5B%22year%22%5D%20%3D%20_yearly%5B%22year%22%5D.astype(int)%0A%0A%20%20%20%20_line%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_yearly)%0A%20%20%20%20%20%20%20%20.mark_line(point%3Dalt.OverlayMarkDef(size%3D70)%2C%20strokeWidth%3D2.5)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22year%3AO%22%2C%20title%3D%22Year%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22median_cost%3AQ%22%2C%20title%3D%22Median%20cost%20(USD%2Fm%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22median_cost%3AQ%22%2C%20title%3D%22Median%20cost%22%2C%20format%3D%22%2C.0f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22mean_cost%3AQ%22%2C%20title%3D%22Mean%20cost%22%2C%20format%3D%22%2C.0f%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%3D580%2C%20height%3D300%2C%20title%3D%22Median%20construction%20cost%20per%20year%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_rule%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(pd.DataFrame(%7B%22year%22%3A%20%5B2020%5D%7D))%0A%20%20%20%20%20%20%20%20.mark_rule(color%3D%22%23E53935%22%2C%20strokeDash%3D%5B5%2C%203%5D%2C%20strokeWidth%3D2%2C%20opacity%3D0.6)%0A%20%20%20%20%20%20%20%20.encode(alt.X(%22year%3AO%22))%0A%20%20%20%20)%0A%0A%20%20%20%20_label%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(pd.DataFrame(%7B%22year%22%3A%20%5B2020%5D%2C%20%22label%22%3A%20%5B%22COVID-19%22%5D%7D))%0A%20%20%20%20%20%20%20%20.mark_text(dy%3D-10%2C%20dx%3D6%2C%20color%3D%22%23E53935%22%2C%20fontSize%3D11%2C%20align%3D%22left%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(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.value(20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3Dalt.Text(%22label%3AN%22)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20The%20start%20of%20COVID%22)%2C%0A%20%20%20%20%20%20%20%20alt.layer(_line%2C%20_rule%2C%20_label)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%22The%20dashed%20red%20line%20marks%202020.%20Do%20we%20ned%20to%20also%20treat%202020%20as%20distinct%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22similarly%20to%20Philippines%20vs.%20Japan%3F%20Should%20we%20train%20separate%20modells%20handling%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22this%3F%20If%20not%2C%20is%20just%20adding%20a%20%60is_2020%60%20binary%20flag%20worth%20anything%3F%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%20kind%3D%22warn%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20macro_features(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20np%2C%20train_df)%3A%0A%20%20%20%20_gdp_scatter%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_circle(size%3D55%2C%20opacity%3D0.55)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22log_gdp%3AQ%22%2C%20title%3D%22log(Deflated%20GDP%2C%20USD)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22log_cost%3AQ%22%2C%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Shape(%22country%3AN%22%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22deflated_gdp_usd%3AQ%22%2C%20title%3D%22GDP%22%2C%20format%3D%22.3s%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%3D320%2C%20height%3D280%2C%20title%3D%22GDP%20vs%20Construction%20Cost%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_cpi_scatter%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_circle(size%3D55%2C%20opacity%3D0.55)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22us_cpi%3AQ%22%2C%20title%3D%22US%20CPI%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22log_cost%3AQ%22%2C%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Shape(%22country%3AN%22%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22us_cpi%3AQ%22%2C%20title%3D%22US%20CPI%22%2C%20format%3D%22.1f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%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%3D320%2C%20height%3D280%2C%20title%3D%22US%20CPI%20vs%20Construction%20Cost%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_jp%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Japan%22%5D%0A%20%20%20%20_ph%20%3D%20train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Philippines%22%5D%0A%20%20%20%20_jp_r%20%3D%20float(np.corrcoef(_jp%5B%22log_gdp%22%5D%2C%20_jp%5B%22log_cost%22%5D)%5B0%2C%201%5D)%0A%20%20%20%20_ph_r%20%3D%20float(np.corrcoef(_ph%5B%22log_gdp%22%5D%2C%20_ph%5B%22log_cost%22%5D)%5B0%2C%201%5D)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Macroeconomics%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22The%20competition%20allows%20us%20to%20pull%20in%20external%20datasources.%20Could%20one%20idea%20be%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22to%20derive%20an%20external%20cost%20baseline%20from%20some%20historical%20construction%20cost%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22database%20and%20modell%20a%20residual%3F%20Our%20two%20existing%20good%20proxies%20would%20be%20GDP%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22(economic%20size)%20and%20US%20CPI%20(global%20price%20level).%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Figure%20out%20how%20much%20each%20location%20deviate%20from%20the%20macro%20trend%3F%20%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_gdp_scatter%2C%20_cpi_scatter%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22Pearson%20r%20between%20log(GDP)%20and%20log(cost)%3A%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22**%7B_jp_r%3A.2f%7D**%20(Japan)%2C%20**%7B_ph_r%3A.2f%7D**%20(Philippines).%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22The%20relationship%20is%20tighter%20in%20Japan%2C%20where%20economic%20variance%20across%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22prefectures%20maps%20more%20directly%20to%20construction%20markets.%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%20kind%3D%22info%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20viirs_deep_dive(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20np%2C%20pd%2C%20train_df)%3A%0A%20%20%20%20_scatter%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_circle(size%3D55%2C%20opacity%3D0.55)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22log_viirs%3AQ%22%2C%20title%3D%22log(1%20%2B%20VIIRS%20mean%20radiance)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22log_cost%3AQ%22%2C%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22viirs_mean%3AQ%22%2C%20title%3D%22VIIRS%20mean%22%2C%20format%3D%22.2f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%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%3D360%2C%20height%3D300%2C%20title%3D%22VIIRS%20nighttime%20light%20vs%20cost%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_viirs_cols%20%3D%20%5B%0A%20%20%20%20%20%20%20%20c%20for%20c%20in%20train_df.columns%0A%20%20%20%20%20%20%20%20if%20c.startswith(%22viirs_%22)%20and%20train_df%5Bc%5D.dtype.kind%20%3D%3D%20%22f%22%0A%20%20%20%20%5D%0A%20%20%20%20with%20np.errstate(invalid%3D%22ignore%22%2C%20divide%3D%22ignore%22)%3A%0A%20%20%20%20%20%20%20%20_corr_data%20%3D%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22feature%22%3A%20_viirs_cols%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22r%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20float(np.corrcoef(train_df%5Bc%5D%2C%20train_df%5B%22log_cost%22%5D)%5B0%2C%201%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20c%20in%20_viirs_cols%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%7D).sort_values(%22r%22%2C%20ascending%3DFalse)%0A%0A%20%20%20%20_bar%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_corr_data)%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%20alt.X(%22r%3AQ%22%2C%20title%3D%22Pearson%20r%20with%20log(cost)%22%2C%20scale%3Dalt.Scale(domain%3D%5B-0.2%2C%200.8%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22feature%3AN%22%2C%20sort%3D%22-x%22%2C%20title%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.condition(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.datum.r%20%3E%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.value(%22%231565C0%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.value(%22%23E65100%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%20%20%20%20tooltip%3D%5B%22feature%3AN%22%2C%20%22r%3AQ%22%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D300%2C%20height%3D280%2C%20title%3D%22VIIRS%20feature%20correlations%20with%20log(cost)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_top_r%20%3D%20float(_corr_data%5B%22r%22%5D.iloc%5B0%5D)%0A%20%20%20%20_top_feat%20%3D%20_corr_data%5B%22feature%22%5D.iloc%5B0%5D%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20VIIRS%3A%20Nighttime%20Light%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Nighttime%20light%20intensity%20is%20a%20direct%20proxy%20for%20economic%20activity%20and%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22infrastructure%20density.%20Brighter%20pixels%20mean%20more%20electricity%2C%20more%20commerce%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22more%20density%20%E2%80%94%20all%20of%20which%20correlate%20with%20higher%20construction%20costs.%20%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_scatter%2C%20_bar%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22**%60%7B_top_feat%7D%60**%20is%20the%20strongest%20VIIRS%20predictor%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22(r%20%3D%20%7B_top_r%3A.2f%7D%20with%20log%20cost).%20%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%20kind%3D%22success%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20threshold_slider(mo)%3A%0A%20%20%20%20from%20wigglystuff%20import%20TangleSlider%20as%20_TangleSlider%0A%0A%20%20%20%20threshold_slider%20%3D%20mo.ui.anywidget(%0A%20%20%20%20%20%20%20%20_TangleSlider(%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%3D25%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20min_value%3D5%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20max_value%3D100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20step%3D5%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20prefix%3D%22NTL%20%3E%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20suffix%3D%22%20W%C2%B7cm%E2%81%BB%C2%B2%C2%B7sr%E2%81%BB%C2%B9%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels_per_step%3D3%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20return%20(threshold_slider%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20viirs_threshold_chart(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20threshold_slider%2C%20train_df)%3A%0A%20%20%20%20_t%20%3D%20threshold_slider.value%5B%22amount%22%5D%0A%20%20%20%20_col%20%3D%20f%22viirs_ntl_frac_gt_%7Bint(_t)%7D%22%0A%20%20%20%20_col%20%3D%20_col%20if%20_col%20in%20train_df.columns%20else%20%22viirs_ntl_frac_gt_25%22%0A%0A%20%20%20%20_chart%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_circle(size%3D60%2C%20opacity%3D0.6)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7B_col%7D%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3Df%22Fraction%20of%20pixels%20with%20NTL%20%3E%20%7Bint(_t)%7D%20W%C2%B7cm%5E2%C2%B7sr%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%20%20%20%20alt.Y(%22log_cost%3AQ%22%2C%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(f%22%7B_col%7D%3AQ%22%2C%20title%3D%22Bright%20pixel%20fraction%22%2C%20format%3D%22.3f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%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%3D560%2C%20height%3D340)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20How%20Bright%3F%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22When%20does%20a%20pixel%20value%20become%20bright%20enough%20to%20count%20as%20a%20bright%20pixel%3F%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Use%20this%20slider%20to%20find%20out%3A%20**%7Bthreshold_slider%7D**.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Higher%20thresholds%20should%20be%20better%20at%20finding%20just%20the%20bright%20urban%20cores%3B%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22while%20lower%20thresholds%20shoudl%20equal%20broader%2Fwider%20human%20activity.%22%0A%20%20%20%20%20%20%20%20)%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(hide_code%3DTrue)%0Adef%20s2_spectral_indices(COUNTRY_COLORS%2C%20alt%2C%20mo%2C%20train_df)%3A%0A%20%20%20%20_ndvi_box%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_boxplot(extent%3D%22min-max%22%2C%20size%3D40)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22country%3AN%22%2C%20title%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22s2_ndvi_mean%3AQ%22%2C%20title%3D%22Mean%20NDVI%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D180%2C%20height%3D260%2C%20title%3D%22NDVI%20(vegetation)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_ndbi_box%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_boxplot(extent%3D%22min-max%22%2C%20size%3D40)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22country%3AN%22%2C%20title%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22s2_ndbi_mean%3AQ%22%2C%20title%3D%22Mean%20NDBI%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D180%2C%20height%3D260%2C%20title%3D%22NDBI%20(built-up)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_builtup%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(train_df)%0A%20%20%20%20%20%20%20%20.mark_circle(size%3D55%2C%20opacity%3D0.55)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22s2_builtup_ratio%3AQ%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Built-up%20ratio%20(fraction%20of%20pixels%20with%20NDBI%20%3E%20NDVI)%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%20%20%20%20alt.Y(%22log_cost%3AQ%22%2C%20title%3D%22log(Construction%20cost%20per%20m%C2%B2)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Color(%22country%3AN%22%2C%20scale%3DCOUNTRY_COLORS%2C%20legend%3Dalt.Legend(orient%3D%22top-left%22%2C%20title%3DNone))%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(%22geolocation_name%3AN%22%2C%20title%3D%22Location%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22country%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22s2_builtup_ratio%3AQ%22%2C%20title%3D%22Built-up%20ratio%22%2C%20format%3D%22.2f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%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%3D340%2C%20height%3D260%2C%20title%3D%22Built-up%20ratio%20vs%20cost%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_jp_ndvi%20%3D%20float(train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Japan%22%5D%5B%22s2_ndvi_mean%22%5D.median())%0A%20%20%20%20_ph_ndvi%20%3D%20float(train_df%5Btrain_df%5B%22country%22%5D%20%3D%3D%20%22Philippines%22%5D%5B%22s2_ndvi_mean%22%5D.median())%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Sentinel-2%3A%20Vegetation%20vs%20Urbanisation%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22NDVI%20measures%20green%20vegetation%20coverage%20(more%20forest%2Fagriculture%20if%20high)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22NDBI%20measures%20built-up%20surfaces%20(more%20concrete%2Fsteel%20if%20high)%2C%20and%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%60s2_builtup_ratio%60%20becomes%20the%20fraction%20of%20pixels%20where%20NDBI%20%3E%20NDVI.%20%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_ndvi_box%2C%20_ndbi_box%2C%20_builtup%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22Japan's%20median%20NDVI%20(%7B_jp_ndvi%3A.2f%7D)%20is%20lower%20than%20Philippines%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22(%7B_ph_ndvi%3A.2f%7D)%20%E2%80%94%20Japanese%20locations%20skew%20to%20more%20urban.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%20higher%20built-up%20ratio%20correlates%20with%20higher%20costs%2C%20but%20the%20relationship%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22is%20noisy.%20The%20VIIRS%20signal%20investigated%20earlier%20is%20clean%20in%20comparison.%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%20kind%3D%22info%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20correlation_heatmap(alt%2C%20mo%2C%20np%2C%20pd%2C%20train_df)%3A%0A%20%20%20%20_feat_cols%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22log_gdp%22%2C%20%22us_cpi%22%2C%20%22straight_distance_to_capital_km%22%2C%0A%20%20%20%20%20%20%20%20%22developed_country%22%2C%20%22landlocked%22%2C%20%22access_to_airport%22%2C%0A%20%20%20%20%20%20%20%20%22access_to_port%22%2C%20%22access_to_highway%22%2C%20%22access_to_railway%22%2C%0A%20%20%20%20%20%20%20%20%22flood_risk_class%22%2C%20%22log_viirs%22%2C%20%22viirs_mean%22%2C%20%22viirs_std%22%2C%0A%20%20%20%20%20%20%20%20%22viirs_p90%22%2C%20%22viirs_p95%22%2C%20%22viirs_bright_ratio_p75%22%2C%0A%20%20%20%20%20%20%20%20%22viirs_ntl_frac_gt_5%22%2C%20%22viirs_ntl_frac_gt_10%22%2C%20%22viirs_ntl_frac_gt_25%22%2C%0A%20%20%20%20%20%20%20%20%22viirs_ntl_frac_gt_50%22%2C%20%22viirs_ntl_frac_gt_100%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndvi_mean%22%2C%20%22s2_ndvi_std%22%2C%20%22s2_ndbi_mean%22%2C%20%22s2_ndbi_std%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndwi_mean%22%2C%20%22s2_ndwi_std%22%2C%20%22s2_builtup_ratio%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndbi_minus_ndvi_std%22%2C%0A%20%20%20%20%20%20%20%20%22s2_B4_mean%22%2C%20%22s2_B8_mean%22%2C%20%22s2_B11_mean%22%2C%20%22s2_B12_mean%22%2C%0A%20%20%20%20%5D%0A%20%20%20%20_feat_cols%20%3D%20%5Bc%20for%20c%20in%20_feat_cols%20if%20c%20in%20train_df.columns%5D%0A%0A%20%20%20%20def%20_safe_corr(col%2C%20target)%3A%0A%20%20%20%20%20%20%20%20x%20%3D%20pd.to_numeric(col%2C%20errors%3D%22coerce%22).fillna(0).astype(float)%0A%20%20%20%20%20%20%20%20with%20np.errstate(invalid%3D%22ignore%22%2C%20divide%3D%22ignore%22)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20r%20%3D%20np.corrcoef(x%2C%20target)%5B0%2C%201%5D%0A%20%20%20%20%20%20%20%20return%20float(0.0%20if%20np.isnan(r)%20else%20r)%0A%0A%20%20%20%20_corr%20%3D%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22feature%22%3A%20_feat_cols%2C%0A%20%20%20%20%20%20%20%20%22r%22%3A%20%5B_safe_corr(train_df%5Bc%5D%2C%20train_df%5B%22log_cost%22%5D)%20for%20c%20in%20_feat_cols%5D%2C%0A%20%20%20%20%7D)%0A%20%20%20%20_corr%5B%22abs_r%22%5D%20%3D%20_corr%5B%22r%22%5D.abs()%0A%20%20%20%20_corr%20%3D%20_corr.sort_values(%22abs_r%22%2C%20ascending%3DFalse)%0A%0A%20%20%20%20_chart%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_corr)%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%20alt.X(%22r%3AQ%22%2C%20title%3D%22Pearson%20r%20with%20log(cost)%22%2C%20scale%3Dalt.Scale(domain%3D%5B-0.8%2C%200.8%5D))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22feature%3AN%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sort%3Dalt.EncodingSortField(%22abs_r%22%2C%20order%3D%22descending%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3DNone%2C%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%20color%3Dalt.condition(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.datum.r%20%3E%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.value(%22%231565C0%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.value(%22%23E65100%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%20%20%20%20tooltip%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22feature%3AN%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22r%3AQ%22%2C%20format%3D%22.3f%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%3D500%2C%20height%3D500%2C%20title%3D%22Feature%20correlations%20with%20log(construction%20cost)%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_top5%20%3D%20_corr.head(5)%5B%22feature%22%5D.tolist()%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20What%20Predicts%20Construction%20Cost%3F%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Pearson%20correlation%20with%20log(cost)%20across%20all%201%2C024%20training%20rows.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20is%20a%20univariate%20view%20(it%20doesn't%20get%20interactions)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22but%20does%20give%20a%20clean%20ranking%20of%20individual%20feature's%20importance.%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20_chart%2C%0A%20%20%20%20%20%20%20%20mo.callout(%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%20f%22Top%205%20features%20by%20%7Cr%7C%3A%20**%7B'%2C%20'.join(f'%60%7Bf%7D%60'%20for%20f%20in%20_top5)%7D**.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22VIIRS%20and%20macroeconomic%20features%20dominate%3B%20satellite%20spectral%20indices%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22are%20meh.%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%20kind%3D%22success%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20location_select(mo%2C%20train_df)%3A%0A%20%20%20%20_locations%20%3D%20sorted(train_df%5B%22geolocation_name%22%5D.unique().tolist())%0A%20%20%20%20_default%20%3D%20next((l%20for%20l%20in%20_locations%20if%20%22Tokyo%22%20in%20l)%2C%20_locations%5B0%5D)%0A%20%20%20%20location_select%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3D_locations%2C%0A%20%20%20%20%20%20%20%20value%3D_default%2C%0A%20%20%20%20%20%20%20%20label%3D%22Location%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(location_select%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20location_chart(alt%2C%20location_select%2C%20mo%2C%20train_df)%3A%0A%20%20%20%20_loc%20%3D%20location_select.value%0A%20%20%20%20_loc_df%20%3D%20train_df%5Btrain_df%5B%22geolocation_name%22%5D%20%3D%3D%20_loc%5D.sort_values(%22timestamp%22)%0A%20%20%20%20_country%20%3D%20_loc_df%5B%22country%22%5D.iloc%5B0%5D%20if%20len(_loc_df)%20%3E%200%20else%20%22Japan%22%0A%20%20%20%20_color%20%3D%20%22%231565C0%22%20if%20_country%20%3D%3D%20%22Japan%22%20else%20%22%23E65100%22%0A%0A%20%20%20%20_cost_line%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_loc_df)%0A%20%20%20%20%20%20%20%20.mark_line(point%3DTrue%2C%20color%3D_color%2C%20strokeWidth%3D2)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%20(USD%2Fm%C2%B2)%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(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22%2C%20timeUnit%3D%22yearquarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22construction_cost_per_m2_usd%3AQ%22%2C%20title%3D%22Cost%22%2C%20format%3D%22%2C.0f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%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%3D340%2C%20height%3D200%2C%20title%3Df%22Construction%20cost%20%E2%80%94%20%7B_loc%7D%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_viirs_line%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_loc_df)%0A%20%20%20%20%20%20%20%20.mark_line(point%3DTrue%2C%20color%3D_color%2C%20strokeWidth%3D2)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22viirs_mean%3AQ%22%2C%20title%3D%22VIIRS%20mean%20radiance%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(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22%2C%20timeUnit%3D%22yearquarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22viirs_mean%3AQ%22%2C%20title%3D%22VIIRS%20mean%22%2C%20format%3D%22.3f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%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%3D340%2C%20height%3D200%2C%20title%3Df%22VIIRS%20nighttime%20light%20%E2%80%94%20%7B_loc%7D%22)%0A%20%20%20%20)%0A%0A%20%20%20%20_ndvi_line%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_loc_df)%0A%20%20%20%20%20%20%20%20.mark_line(point%3DTrue%2C%20color%3D_color%2C%20strokeWidth%3D2)%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.X(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Y(%22s2_ndvi_mean%3AQ%22%2C%20title%3D%22Mean%20NDVI%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(%22timestamp%3AT%22%2C%20title%3D%22Quarter%22%2C%20timeUnit%3D%22yearquarter%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22s2_ndvi_mean%3AQ%22%2C%20title%3D%22NDVI%20mean%22%2C%20format%3D%22.3f%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip(%22year%3AO%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%3D340%2C%20height%3D200%2C%20title%3Df%22NDVI%20(vegetation)%20%E2%80%94%20%7B_loc%7D%22)%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Location%20Explorer%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22How%20do%20signals%20evolve%20over%20time%3F%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Select%20a%20location%20to%20see%20how%20construction%20cost%2C%20nighttime%20light%2C%20and%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22vegetation%20index%20have%20changed%20quarter-by-quarter.%20%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20location_select%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B_cost_line%2C%20_viirs_line%2C%20_ndvi_line%5D%2C%20justify%3D%22start%22)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20location_satellite_thumbnails(%0A%20%20%20%20df%2C%0A%20%20%20%20location_select%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20read_s2_band_thumb%2C%0A%20%20%20%20read_s2_rgb_thumb%2C%0A%20%20%20%20read_viirs_thumb%2C%0A%20%20%20%20resolve_tiff_path%2C%0A%20%20%20%20s2_band_select%2C%0A%20%20%20%20s2_band_to_index%2C%0A)%3A%0A%0A%20%20%20%20loc%20%3D%20location_select.value%0A%20%20%20%20loc_df%20%3D%20(%0A%20%20%20%20%20%20%20%20df%5Bdf%5B%22geolocation_name%22%5D%20%3D%3D%20loc%5D%0A%20%20%20%20%20%20%20%20.sort_values(%22timestamp%22)%0A%20%20%20%20%20%20%20%20.reset_index(drop%3DTrue)%0A%20%20%20%20)%0A%0A%20%20%20%20cards%20%3D%20%5B%5D%0A%20%20%20%20for%20_%2C%20row%20in%20loc_df.iterrows()%3A%0A%20%20%20%20%20%20%20%20ts%20%3D%20row%5B%22timestamp%22%5D%0A%20%20%20%20%20%20%20%20quarter%20%3D%20f%22%7Bts.year%7D-Q%7B((ts.month%20-%201)%20%2F%2F%203)%20%2B%201%7D%22%0A%0A%20%20%20%20%20%20%20%20s2_path%20%3D%20resolve_tiff_path(row%5B%22split%22%5D%2C%20row%5B%22sentinel2_tiff_file_name%22%5D)%0A%20%20%20%20%20%20%20%20v_path%20%3D%20resolve_tiff_path(row%5B%22split%22%5D%2C%20row%5B%22viirs_tiff_file_name%22%5D)%0A%0A%20%20%20%20%20%20%20%20if%20s2_path%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20s2_rgb_panel%20%3D%20mo.callout(mo.md(%22Sentinel-2%20file%20not%20found.%22)%2C%20kind%3D%22warn%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20s2_band_panel%20%3D%20mo.callout(mo.md(%22Sentinel-2%20file%20not%20found.%22)%2C%20kind%3D%22warn%22)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rgb%20%3D%20read_s2_rgb_thumb(str(s2_path)%2C%20224)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20s2_rgb_panel%20%3D%20mo.image(rgb%2C%20width%3D260%2C%20caption%3Df%22Sentinel-2%20RGB%20(%7Bs2_path.name%7D)%22)%0A%20%20%20%20%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%20%20%20%20s2_rgb_panel%20%3D%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22Sentinel-2%20RGB%20read%20failed%3A%20%60%7Btype(e).__name__%7D%3A%20%7Be%7D%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind%3D%22danger%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20band_name%20%3D%20s2_band_select.value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20band_idx%20%3D%20s2_band_to_index%5Bband_name%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20band%20%3D%20read_s2_band_thumb(str(s2_path)%2C%20band_idx%2C%20224)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20s2_band_panel%20%3D%20mo.image(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20band%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width%3D260%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20caption%3Df%22Sentinel-2%20%7Bband_name%7D%20(%7Bs2_path.name%7D)%22%2C%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%20except%20Exception%20as%20e%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20s2_band_panel%20%3D%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22Sentinel-2%20%7Bs2_band_select.value%7D%20read%20failed%3A%20%60%7Btype(e).__name__%7D%3A%20%7Be%7D%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind%3D%22danger%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20v_path%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20v_panel%20%3D%20mo.callout(mo.md(%22VIIRS%20file%20not%20found.%22)%2C%20kind%3D%22warn%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20viirs%20%3D%20read_viirs_thumb(str(v_path)%2C%20224)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20v_panel%20%3D%20mo.image(viirs%2C%20width%3D260%2C%20caption%3Df%22VIIRS%20(%7Bv_path.name%7D)%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%20v_panel%20%3D%20mo.callout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22VIIRS%20read%20failed%3A%20%60%7Btype(e).__name__%7D%3A%20%7Be%7D%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind%3D%22danger%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20cards.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**%7Bquarter%7D**%20%C2%B7%20split%3A%20%60%7Brow%5B'split'%5D%7D%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.hstack(%5Bs2_rgb_panel%2C%20s2_band_panel%2C%20v_panel%5D%2C%20justify%3D%22start%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%0A%20%20%20%20thumb_view%20%3D%20(%0A%20%20%20%20%20%20%20%20mo.carousel(cards)%0A%20%20%20%20%20%20%20%20if%20len(cards)%20%3E%201%0A%20%20%20%20%20%20%20%20else%20(cards%5B0%5D%20if%20cards%20else%20mo.md(%22No%20rows%20for%20selected%20location.%22))%0A%20%20%20%20)%0A%0A%20%20%20%20thumb_view%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20s2_band_select(mo%2C%20s2_bands)%3A%0A%20%20%20%20s2_band_select%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3Ds2_bands%2C%0A%20%20%20%20%20%20%20%20value%3D%22B5%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Sentinel-2%20band%3A%22%2C%0A%20%20%20%20)%0A%20%20%20%20s2_band_select%0A%20%20%20%20return%20(s2_band_select%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20satellite_thumbnail_helpers()%3A%0A%0A%20%20%20%20from%20pathlib%20import%20Path%20as%20_Path%0A%20%20%20%20from%20functools%20import%20lru_cache%0A%0A%20%20%20%20import%20numpy%20as%20_np%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20import%20rasterio%20as%20_rasterio%0A%20%20%20%20%20%20%20%20from%20rasterio.enums%20import%20Resampling%20as%20_Resampling%0A%20%20%20%20%20%20%20%20_RASTERIO_AVAILABLE%20%3D%20True%0A%20%20%20%20except%20ImportError%3A%0A%20%20%20%20%20%20%20%20_RASTERIO_AVAILABLE%20%3D%20False%0A%0A%20%20%20%20s2_bands%20%3D%20%5B%22B1%22%2C%20%22B2%22%2C%20%22B3%22%2C%20%22B4%22%2C%20%22B5%22%2C%20%22B6%22%2C%20%22B7%22%2C%20%22B8%22%2C%20%22B8A%22%2C%20%22B9%22%2C%20%22B11%22%2C%20%22B12%22%5D%0A%20%20%20%20s2_band_to_index%20%3D%20%7Bband%3A%20idx%20for%20idx%2C%20band%20in%20enumerate(s2_bands%2C%20start%3D1)%7D%0A%0A%0A%20%20%20%20def%20robust_scale(arr%2C%20p_low%3D2.0%2C%20p_high%3D98.0)%3A%0A%20%20%20%20%20%20%20%20arr%20%3D%20_np.asarray(arr%2C%20dtype%3D%22float32%22)%0A%20%20%20%20%20%20%20%20mask%20%3D%20_np.isfinite(arr)%0A%20%20%20%20%20%20%20%20out%20%3D%20_np.zeros_like(arr%2C%20dtype%3D%22float32%22)%0A%20%20%20%20%20%20%20%20if%20not%20mask.any()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20out%0A%0A%20%20%20%20%20%20%20%20vals%20%3D%20arr%5Bmask%5D%0A%20%20%20%20%20%20%20%20lo%2C%20hi%20%3D%20_np.percentile(vals%2C%20%5Bp_low%2C%20p_high%5D)%0A%20%20%20%20%20%20%20%20if%20not%20_np.isfinite(lo)%20or%20not%20_np.isfinite(hi)%20or%20hi%20%3C%3D%20lo%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20lo%20%3D%20float(vals.min())%0A%20%20%20%20%20%20%20%20%20%20%20%20hi%20%3D%20float(vals.max())%0A%20%20%20%20%20%20%20%20den%20%3D%20max(hi%20-%20lo%2C%201e-6)%0A%20%20%20%20%20%20%20%20out%5Bmask%5D%20%3D%20_np.clip((arr%5Bmask%5D%20-%20lo)%20%2F%20den%2C%200.0%2C%201.0)%0A%20%20%20%20%20%20%20%20return%20out%0A%0A%0A%20%20%20%20def%20resolve_tiff_path(split%2C%20filename)%3A%0A%20%20%20%20%20%20%20%20if%20split%20not%20in%20%7B%22train%22%2C%20%22eval%22%7D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20None%0A%20%20%20%20%20%20%20%20root%20%3D%20_Path(%22data%2Ftrain_composite%22)%20if%20split%20%3D%3D%20%22train%22%20else%20_Path(%22data%2Fevaluation_composite%22)%0A%20%20%20%20%20%20%20%20path%20%3D%20root%20%2F%20str(filename)%0A%20%20%20%20%20%20%20%20return%20path%20if%20path.exists()%20else%20None%0A%0A%0A%20%20%20%20def%20_read_with_retry(path_str%2C%20indexes%2C%20size)%3A%0A%20%20%20%20%20%20%20%20if%20not%20_RASTERIO_AVAILABLE%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20ImportError(%22rasterio%20not%20installed%20%E2%80%94%20install%20the%20'eo'%20group%20to%20view%20thumbnails%22)%0A%20%20%20%20%20%20%20%20with%20_rasterio.open(path_str)%20as%20ds%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20isinstance(indexes%2C%20int)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shape%20%3D%20(size%2C%20size)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shape%20%3D%20(len(indexes)%2C%20size%2C%20size)%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20ds.read(indexes%2C%20out_shape%3Dshape%2C%20resampling%3D_Resampling.bilinear)%0A%20%20%20%20%20%20%20%20%20%20%20%20except%20RuntimeError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20ds.read(indexes%2C%20out_shape%3Dshape%2C%20resampling%3D_Resampling.nearest)%0A%0A%0A%20%20%20%20%40lru_cache(maxsize%3D512)%0A%20%20%20%20def%20read_s2_rgb_thumb(path_str%2C%20size%3D224)%3A%0A%20%20%20%20%20%20%20%20rgb%20%3D%20_read_with_retry(path_str%2C%20%5B4%2C%203%2C%202%5D%2C%20size)%0A%20%20%20%20%20%20%20%20rgb%20%3D%20robust_scale(rgb)%0A%20%20%20%20%20%20%20%20return%20_np.moveaxis(rgb%2C%200%2C%20-1)%0A%0A%0A%20%20%20%20%40lru_cache(maxsize%3D512)%0A%20%20%20%20def%20read_s2_band_thumb(path_str%2C%20band_index%2C%20size%3D224)%3A%0A%20%20%20%20%20%20%20%20band%20%3D%20_read_with_retry(path_str%2C%20int(band_index)%2C%20size)%0A%20%20%20%20%20%20%20%20return%20robust_scale(band)%0A%0A%0A%20%20%20%20%40lru_cache(maxsize%3D512)%0A%20%20%20%20def%20read_viirs_thumb(path_str%2C%20size%3D224)%3A%0A%20%20%20%20%20%20%20%20band%20%3D%20_read_with_retry(path_str%2C%201%2C%20size)%0A%20%20%20%20%20%20%20%20return%20robust_scale(band)%0A%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20read_s2_band_thumb%2C%0A%20%20%20%20%20%20%20%20read_s2_rgb_thumb%2C%0A%20%20%20%20%20%20%20%20read_viirs_thumb%2C%0A%20%20%20%20%20%20%20%20resolve_tiff_path%2C%0A%20%20%20%20%20%20%20%20s2_band_to_index%2C%0A%20%20%20%20%20%20%20%20s2_bands%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20country_feature_comparison(mo%2C%20train_df)%3A%0A%20%20%20%20from%20wigglystuff%20import%20ParallelCoordinates%20as%20_ParallelCoords%0A%0A%20%20%20%20_feat_subset%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22country%22%2C%20%22log_cost%22%2C%20%22log_viirs%22%2C%20%22viirs_std%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndvi_mean%22%2C%20%22s2_ndbi_mean%22%2C%20%22s2_builtup_ratio%22%2C%0A%20%20%20%20%20%20%20%20%22log_gdp%22%2C%20%22us_cpi%22%2C%0A%20%20%20%20%5D%0A%20%20%20%20_plot_df%20%3D%20train_df%5B%5Bc%20for%20c%20in%20_feat_subset%20if%20c%20in%20train_df.columns%5D%5D.copy()%0A%20%20%20%20_plot_df%20%3D%20_plot_df.rename(columns%3D%7B%0A%20%20%20%20%20%20%20%20%22log_cost%22%3A%20%22log(cost)%22%2C%0A%20%20%20%20%20%20%20%20%22log_viirs%22%3A%20%22log(VIIRS)%22%2C%0A%20%20%20%20%20%20%20%20%22viirs_std%22%3A%20%22VIIRS%20std%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndvi_mean%22%3A%20%22NDVI%22%2C%0A%20%20%20%20%20%20%20%20%22s2_ndbi_mean%22%3A%20%22NDBI%22%2C%0A%20%20%20%20%20%20%20%20%22s2_builtup_ratio%22%3A%20%22built-up%22%2C%0A%20%20%20%20%20%20%20%20%22log_gdp%22%3A%20%22log(GDP)%22%2C%0A%20%20%20%20%20%20%20%20%22us_cpi%22%3A%20%22CPI%22%2C%0A%20%20%20%20%7D)%0A%0A%20%20%20%20_pc%20%3D%20_ParallelCoords(%0A%20%20%20%20%20%20%20%20data%3D_plot_df%2C%0A%20%20%20%20%20%20%20%20color_by%3D%22country%22%2C%0A%20%20%20%20%20%20%20%20color_map%3D%7B%22Japan%22%3A%20%22%231565C0%22%2C%20%22Philippines%22%3A%20%22%23E65100%22%7D%2C%0A%20%20%20%20%20%20%20%20height%3D440%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Comparing%20Features%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20is%20a%20parallel%20coordinates%20plot%2C%20showing%20above%20key%20features%20for%20all%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%221024%20training%20rows.%20Each%20line%20is%20one%20observation.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22**Drag%20to%20reorder%20axes.%20Brush%20on%20any%20axis%20to%20filter.**%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22We%20see%20that%20Japan%20(blue)%20and%20Philippines%20(orange)%20occupy%20distinct%20regions%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22of%20the%20feature%20space.%20The%20Philippines%20lines%20is%20narrower%20in%20VIIRS%20and%20cost%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22reflecting%20lower%20variance%20in%20economic%20density.%20%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20_pc%2C%0A%20%20%20%20%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
9b1c914293575f2204098318b5273a4a