-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.json
More file actions
93 lines (93 loc) · 31 KB
/
Copy pathsearch.json
File metadata and controls
93 lines (93 loc) · 31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
[
{
"objectID": "Social_Census_Dashboard.html",
"href": "Social_Census_Dashboard.html",
"title": "Reddit Analysis of Cecil B. Moore Library and Carousel House",
"section": "",
"text": "Code\nimport geopandas as gpd\n\n#PASDA libraries shapefile\nlibraries = gpd.read_file(\"/Users/macbook/Desktop/Python/Week 14/PhiladelphiaLibraries201302/PhiladelphiaLibraries201302.shp\")\n\n#Swiming Pools \npools = gpd.read_file(\"/Users/macbook/Desktop/Python/Week 14/PPR_Swimming_Pools/PPR_Swimming_Pools.shp\")\n\n#Playgrounds and Rec Centers\nplaygrounds = gpd.read_file(\"/Users/macbook/Desktop/Python/Week 14/PPR_Playgrounds/PPR_Playgrounds.shp\")\n\n#Parks\nparks = gpd.read_file(\"/Users/macbook/Desktop/Python/Week 14/PPR_Program_Sites.geojson\") \n\n\n\n\nCode\nfor name, gdf in {\n \"libraries\": libraries,\n \"pools\": pools,\n \"playgrounds\": playgrounds,\n \"parks\": parks\n}.items():\n print(name, gdf.crs)\n\n\nlibraries EPSG:2272\npools EPSG:3857\nplaygrounds EPSG:3857\nparks EPSG:4326\n\n\n\n\nCode\nTARGET_CRS = \"EPSG:2272\"\n\nlayers = {\n \"libraries\": libraries,\n \"pools\": pools,\n \"playgrounds\": playgrounds,\n \"parks\": parks\n}\n\nfor name, gdf in layers.items():\n if gdf.crs != TARGET_CRS:\n layers[name] = gdf.to_crs(TARGET_CRS)\n\nlibraries = layers[\"libraries\"]\npools = layers[\"pools\"]\nplaygrounds = layers[\"playgrounds\"]\nparks = layers[\"parks\"]\n\n\n\n\nCode\nlibraries[\"type\"] = \"Library\"\npools[\"type\"] = \"Pool\"\nplaygrounds[\"type\"] = \"Playground\"\nparks[\"type\"] = \"Park\"\n\n\n\n\nCode\nimport pandas as pd\nimport geopandas as gpd\nimport folium\nimport censusdata\n\n\n\n\nCode\nu18_vars = [\n \"B01001_001E\", # total population\n \"B01001_003E\",\"B01001_004E\",\"B01001_005E\",\"B01001_006E\",\n \"B01001_027E\",\"B01001_028E\",\"B01001_029E\",\"B01001_030E\",\n]\n\nacs_u18 = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n u18_vars\n).reset_index()\n\n\n\n\nCode\nedu_vars = [\n \"B15003_001E\", # total 25+\n \"B15003_022E\",\"B15003_023E\",\"B15003_024E\",\"B15003_025E\"\n]\n\nacs_edu = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n edu_vars\n).reset_index()\n\n\n\n\nCode\ninc_vars = [\"B19013_001E\"]\n\nacs_inc = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n inc_vars\n).reset_index()\n\n\n\n\nCode\ndef make_geoid(df):\n df[\"GEOID\"] = df[\"index\"].apply(\n lambda x: \"\".join([part[1] for part in x.geo])\n )\n return df\n\n\n\n\nCode\nacs_u18 = make_geoid(acs_u18)\nacs_edu = make_geoid(acs_edu)\nacs_inc = make_geoid(acs_inc)\n\n\n\n\nCode\nacs_u18[\"under_18\"] = acs_u18[\n [\n \"B01001_003E\",\"B01001_004E\",\"B01001_005E\",\"B01001_006E\",\n \"B01001_027E\",\"B01001_028E\",\"B01001_029E\",\"B01001_030E\"\n ]\n].sum(axis=1)\n\nacs_u18[\"pct_under_18\"] = (\n acs_u18[\"under_18\"] / acs_u18[\"B01001_001E\"] * 100\n)\n\n\n\n\nCode\nacs_edu[\"bachelors_plus\"] = acs_edu[\n [\"B15003_022E\",\"B15003_023E\",\"B15003_024E\",\"B15003_025E\"]\n].sum(axis=1)\n\nacs_edu[\"pct_bachelors_plus\"] = (\n acs_edu[\"bachelors_plus\"] / acs_edu[\"B15003_001E\"] * 100\n)\n\n\n\n\nCode\nacs_inc = acs_inc.rename(columns={\n \"B19013_001E\": \"median_income\"\n})\n\n\n\n\nCode\nacs_full = (\n acs_u18[[\"GEOID\", \"pct_under_18\"]]\n .merge(\n acs_edu[[\"GEOID\", \"pct_bachelors_plus\"]],\n on=\"GEOID\",\n how=\"left\"\n )\n .merge(\n acs_inc[[\"GEOID\", \"median_income\"]],\n on=\"GEOID\",\n how=\"left\"\n )\n)\n\n\n\n\nCode\nimport geopandas as gpd\n\n# Read tracts geometry and merge the consolidated ACS table (acs_full)\ntracts_geom = gpd.read_file(\n \"https://www2.census.gov/geo/tiger/TIGER2022/TRACT/tl_2022_42_tract.zip\"\n)\n\ntracts_geom = tracts_geom[tracts_geom[\"COUNTYFP\"] == \"101\"]\n\ntracts = tracts_geom.merge(\n acs_full,\n on=\"GEOID\",\n how=\"left\",\n)\n\n\n\n\nCode\n# --- social infrastructure attribute renames and combine ---\nlibraries = libraries.rename(columns={\"ASSET_NAME\": \"name\"})\npools = pools.rename(columns={\"amenity_na\": \"name\"})\nplaygrounds = playgrounds.rename(columns={\"park_name\": \"name\"})\nparks = parks.rename(columns={\"park_name\": \"name\"})\n\n\n\n\nCode\nsocial_infra = gpd.GeoDataFrame(\n pd.concat([\n libraries[[\"name\", \"type\", \"geometry\"]],\n pools[[\"name\", \"type\", \"geometry\"]],\n playgrounds[[\"name\", \"type\", \"geometry\"]],\n parks[[\"name\", \"type\", \"geometry\"]],\n ], ignore_index=True),\n crs=libraries.crs\n)\n\n\n\n\nCode\nsocial_infra_web = social_infra.to_crs(\"EPSG:4326\")\n\n\n\n\nCode\n# Project tracts and points to a projected CRS\ntracts_proj = tracts.to_crs(\"EPSG:2272\")\nsocial_infra_proj = social_infra.to_crs(\"EPSG:2272\")\n\n\n\n\nCode\ninfra_join = gpd.sjoin(\n social_infra_proj,\n tracts_proj[[\"GEOID\", \"geometry\"]],\n how=\"left\",\n predicate=\"within\"\n)\n\n\n\n\nCode\ninfra_counts = (\n infra_join\n .groupby(\"GEOID\")\n .size()\n .reset_index(name=\"facility_count\")\n)\n\n\n\n\nCode\ninfra_counts.head()\ninfra_counts[\"facility_count\"].describe()\n\n\ncount 225.000000\nmean 3.382222\nstd 2.032250\nmin 1.000000\n25% 2.000000\n50% 3.000000\n75% 4.000000\nmax 13.000000\nName: facility_count, dtype: float64\n\n\n\n\nCode\ntype_cols = {\n \"Library\": \"library_count\",\n \"Playground\": \"rec_center_count\",\n \"Rec Center\": \"rec_center_count\",\n \"Park\": \"park_count\",\n \"Pool\": \"pool_count\"\n}\ninfra_by_type = (\n infra_join\n .groupby([\"GEOID\", \"type\"])\n .size()\n .unstack(fill_value=0)\n .reset_index()\n .rename(columns=type_cols)\n)\nfor col in type_cols.values():\n if col not in infra_by_type.columns:\n infra_by_type[col] = 0\n\n\n\n\nCode\ntracts_access = (\n tracts_proj\n .merge(infra_counts, on=\"GEOID\", how=\"left\")\n .merge(infra_by_type, on=\"GEOID\", how=\"left\")\n)\n\n# Replace NA with 0\ncount_cols = [\"facility_count\", \"library_count\", \"rec_center_count\", \"park_count\", \"pool_count\"]\ntracts_access[count_cols] = tracts_access[count_cols].fillna(0)\n\n\n\n\nCode\ntracts_access_web = tracts_access.to_crs(\"EPSG:4326\")\n\n\n\n\nCode\ncount_field_options = [\n (\"Social Infrastructure Count:\", [\"facility_count\"]),\n (\"Libraries:\", [\"library_count\", \"Library\"]),\n (\"Rec Centers:\", [\"rec_center_count\", \"Rec Center\", \"Playground\"]),\n (\"Parks:\", [\"park_count\", \"Park\"]),\n (\"Pools:\", [\"pool_count\", \"Pool\"]),\n]\ntooltip_fields = []\ntooltip_aliases = []\nfor alias, options in count_field_options:\n for col in options:\n if col in tracts_access_web.columns:\n tooltip_fields.append(col)\n tooltip_aliases.append(alias)\n break\nif not tooltip_fields:\n tooltip_fields = [\"facility_count\"]\n tooltip_aliases = [\"Social Infrastructure Count:\"]\n\n\n\n\nCode\nfrom folium.plugins import DualMap\n\ndual_map = DualMap(\n location=[39.9526, -75.1652],\n zoom_start=11,\n tiles=\"CartoDB positron\"\n)\n\n\n\n\nCode\nimport numpy as np\n\ndef style_facilities(feature):\n v = feature[\"properties\"].get(\"facility_count\")\n if v is None or v == 0 or (isinstance(v, float) and np.isnan(v)):\n return {\n \"fillColor\": \"#f0f0f0\",\n \"color\": \"#cccccc\",\n \"weight\": 0.3,\n \"fillOpacity\": 0.45\n }\n return {\n \"fillColor\": cmap_facilities(v),\n \"color\": \"#ffffff\",\n \"weight\": 0.3,\n \"fillOpacity\": 0.9\n }\n\n\n\n\nCode\ntracts_access_web[\"facility_count\"].describe()\n\n\ncount 408.000000\nmean 1.865196\nstd 2.260431\nmin 0.000000\n25% 0.000000\n50% 1.000000\n75% 3.000000\nmax 13.000000\nName: facility_count, dtype: float64\n\n\n\n\nCode\nimport branca.colormap as cm\n\n\nbins = tracts_access_web[\"facility_count\"].quantile(\n [0, 0.2, 0.4, 0.6, 0.8, 1]\n).values\n\ncmap_facilities = cm.StepColormap(\n colors=cm.linear.Blues_06.colors,\n index=bins,\n vmin=bins[0],\n vmax=bins[-1]\n)\n\n\n\n\nCode\nimport censusdata\nimport geopandas as gpd\nimport pandas as pd\nimport folium\n\n\n\n\nCode\nacs_vars = {\n \"total_pop\": \"B01001_001E\",\n \"male_under_18\": [\n \"B01001_003E\",\"B01001_004E\",\"B01001_005E\",\"B01001_006E\"\n ],\n \"female_under_18\": [\n \"B01001_027E\",\"B01001_028E\",\"B01001_029E\",\"B01001_030E\"\n ]\n}\n\ntracts_acs = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n [acs_vars[\"total_pop\"]] +\n acs_vars[\"male_under_18\"] +\n acs_vars[\"female_under_18\"]\n)\n\n\n\n\nCode\ntracts_acs[\"under_18\"] = tracts_acs[\n [\n \"B01001_003E\",\n \"B01001_004E\",\n \"B01001_005E\",\n \"B01001_006E\",\n \"B01001_027E\",\n \"B01001_028E\",\n \"B01001_029E\",\n \"B01001_030E\",\n ]\n].sum(axis=1)\n\n\n\n\nCode\nedu_vars = [\n \"B15003_001E\", # total 25+\n \"B15003_022E\", # bachelor's\n \"B15003_023E\", # master's\n \"B15003_024E\", # professional\n \"B15003_025E\" # doctorate\n]\n\n\n\n\nCode\nincome_vars = [\"B19013_001E\"]\n\n\n\n\nCode\ntracts_acs_edu = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n edu_vars\n)\n\ntracts_acs_inc = censusdata.download(\n \"acs5\",\n 2022,\n censusdata.censusgeo([(\"state\",\"42\"), (\"county\",\"101\"), (\"tract\",\"*\")]),\n income_vars\n)\n\n\n\n\nCode\ntracts_acs_edu = tracts_acs_edu.reset_index()\ntracts_acs_inc = tracts_acs_inc.reset_index()\n\n\n\n\nCode\ntracts_acs_edu = tracts_acs_edu.rename(columns={\n \"B15003_001E\": \"total_25plus\",\n \"B15003_022E\": \"bachelors\",\n \"B15003_023E\": \"masters\",\n \"B15003_024E\": \"professional\",\n \"B15003_025E\": \"doctorate\"\n})\n\n\n\n\nCode\n# If total population is still B01001_001E, rename it first\ntracts_acs = tracts_acs.rename(columns={\n \"B01001_001E\": \"total_pop\"\n})\n\n# Recreate under_18 if needed\nif \"under_18\" not in tracts_acs.columns:\n tracts_acs[\"under_18\"] = tracts_acs[\n [\n \"B01001_003E\",\"B01001_004E\",\"B01001_005E\",\"B01001_006E\",\n \"B01001_027E\",\"B01001_028E\",\"B01001_029E\",\"B01001_030E\"\n ]\n ].sum(axis=1)\n\n# NOW create the percentage\ntracts_acs[\"pct_under_18\"] = (\n tracts_acs[\"under_18\"] / tracts_acs[\"total_pop\"] * 100\n)\n\n\n\n\nCode\n\nif \"bachelors\" in tracts_acs_edu.columns and \"pct_bachelors\" not in tracts_acs_edu.columns:\n tracts_acs_edu[\"pct_bachelors\"] = (\n tracts_acs_edu[\"bachelors\"]\n / tracts_acs_edu[\"total_25plus\"] * 100\n )\n\n\n\n\nCode\ntracts_acs_inc = tracts_acs_inc.rename(columns={\n \"B19013_001E\": \"median_income\"\n})\n\n\n\n\nCode\ntracts_acs_edu[\"GEOID\"] = tracts_acs_edu[\"index\"].apply(\n lambda x: \"\".join([part[1] for part in x.geo])\n)\n\n\n\n\nCode\ntracts_acs_inc[\"GEOID\"] = tracts_acs_inc[\"index\"].apply(\n lambda x: \"\".join([part[1] for part in x.geo])\n)\n\n\n\n\nCode\ntracts_acs[\"GEOID\"] = tracts_acs.index.map(\n lambda x: (\n x.geo[0][1] + # state\n x.geo[1][1] + # county\n x.geo[2][1] # tract\n )\n)\n\n\n\n\nCode\ntracts_acs[[\"total_pop\", \"under_18\", \"pct_under_18\"]].head()\n\n\n\n\n\n\n\n\n\ntotal_pop\nunder_18\npct_under_18\n\n\n\n\nCensus Tract 1.01; Philadelphia County; Pennsylvania: Summary level: 140, state:42> county:101> tract:000101\n1947\n40\n2.054443\n\n\nCensus Tract 1.02; Philadelphia County; Pennsylvania: Summary level: 140, state:42> county:101> tract:000102\n2897\n162\n5.591992\n\n\nCensus Tract 2; Philadelphia County; Pennsylvania: Summary level: 140, state:42> county:101> tract:000200\n3486\n414\n11.876076\n\n\nCensus Tract 3; Philadelphia County; Pennsylvania: Summary level: 140, state:42> county:101> tract:000300\n3914\n280\n7.153807\n\n\nCensus Tract 4.01; Philadelphia County; Pennsylvania: Summary level: 140, state:42> county:101> tract:000401\n2675\n127\n4.747664\n\n\n\n\n\n\n\n\n\nCode\nacs_full = (\n tracts_acs[[\"GEOID\", \"pct_under_18\"]]\n .merge(\n tracts_acs_edu[[\"GEOID\", \"pct_bachelors\"]],\n on=\"GEOID\",\n how=\"left\"\n )\n .merge(\n tracts_acs_inc[[\"GEOID\", \"median_income\"]],\n on=\"GEOID\",\n how=\"left\"\n )\n)\n\n\n\n\nCode\ntracts = tracts_geom.merge(\n acs_full,\n on=\"GEOID\",\n how=\"left\"\n)\n\ntracts_web = tracts.to_crs(\"EPSG:4326\")\n\n\n\n\nCode\nimport folium\n\nm_acs = folium.Map(\n location=[39.9526, -75.1652],\n zoom_start=11,\n tiles=\"CartoDB positron\"\n)\n\n\n\n\nCode\nimport numpy as np\n\nbins_income = tracts_web[\"median_income\"].quantile(\n [0, 0.2, 0.4, 0.6, 0.8, 1]\n).values\n\n\n\n\nCode\nimport branca.colormap as cm\n\ncmap_income = cm.StepColormap(\n colors=cm.linear.YlOrRd_06.colors,\n vmin=bins_income[0],\n vmax=bins_income[-1],\n index=bins_income\n)\n\n\n\n\nCode\nbins_bach = tracts_access_web[\"pct_bachelors_plus\"].quantile(\n [0, .2, .4, .6, .8, 1]\n).values\n\n\n\n\nCode\nimport branca.colormap as cm\nimport numpy as np\n\ncmap_bach = cm.StepColormap(\n colors=cm.linear.Purples_06.colors,\n index=bins_bach,\n vmin=bins_bach[0],\n vmax=bins_bach[-1]\n)\ncmap_bach.caption = \"% Bachelor's Degree or Higher\"\n\n\n\n\n\nCode\ndef style_bachelors(feature):\n v = feature[\"properties\"].get(\"pct_bachelors_plus\")\n if v is None or np.isnan(v):\n return {\n \"fillColor\": \"#A9A9A9\",\n \"color\": \"white\",\n \"weight\": 0.4,\n \"fillOpacity\": 0.85\n }\n return {\n \"fillColor\": cmap_bach(v),\n \"color\": \"white\",\n \"weight\": 0.4,\n \"fillOpacity\": 0.85\n }\n\n\n\n\nCode\nfolium.GeoJson(\n tracts_web,\n name=\"% Bachelor’s Degree or Higher\",\n style_function=style_bachelors\n).add_to(m_acs)\n\n\n<folium.features.GeoJson at 0x14ee4e5d0>\n\n\n\n\nCode\ncmap_income = cm.linear.YlOrRd_09.scale(\n tracts_web[\"median_income\"].min(),\n tracts_web[\"median_income\"].max()\n)\n\n\n\n\nCode\nimport numpy as np\n\nbins_income = tracts_web[\"median_income\"].quantile(\n [0, 0.2, 0.4, 0.6, 0.8, 1]\n).values\n\n\n\n\nCode\nimport branca.colormap as cm\n\ncmap_income = cm.StepColormap(\n colors=cm.linear.YlOrRd_06.colors,\n vmin=bins_income[0],\n vmax=bins_income[-1],\n index=bins_income\n)\n\n\n\n\nCode\ndef build_acs_layer(name, field, palette):\n values = tracts_access_web[field]\n bins = values.quantile([0, 0.2, 0.4, 0.6, 0.8, 1]).values\n cmap = cm.StepColormap(\n colors=palette,\n index=bins,\n vmin=bins[0],\n vmax=bins[-1]\n )\n cmap.caption = name\n def style_fn(feature, field=field, cmap=cmap):\n val = feature[\"properties\"].get(field)\n if val is None or (isinstance(val, float) and np.isnan(val)):\n return {\"fillColor\": \"#d9d9d9\", \"color\": \"white\", \"weight\": 0.3, \"fillOpacity\": 0.4}\n return {\"fillColor\": cmap(val), \"color\": \"white\", \"weight\": 0.3, \"fillOpacity\": 0.85}\n return {\"name\": name, \"field\": field, \"style\": style_fn, \"cmap\": cmap}\n\nacs_layers = [\n build_acs_layer(\"% Bachelor's Degree or Higher\", \"pct_bachelors_plus\", cm.linear.Purples_06.colors),\n build_acs_layer(\"% Under Age 18\", \"pct_under_18\", cm.linear.Greens_06.colors),\n build_acs_layer(\"Median Household Income\", \"median_income\", cm.linear.YlOrRd_06.colors),\n]\n\n\nFINAL MAP\n\n\nCode\nimport folium\nfrom folium.plugins import DualMap\nfrom folium.features import GeoJsonTooltip\nimport branca.colormap as cm\nimport numpy as np\n\n\n\n\nCode\n#Dual Map Setup\n\nfrom folium.plugins import DualMap\nimport folium\nfrom folium.features import GeoJsonTooltip\n\ndual_map_edu = DualMap(\n location=[39.9526, -75.1652],\n zoom_start=11,\n tiles=\"CartoDB positron\"\n)\n\n\n\n\nCode\nfolium.GeoJson(\n tracts_access_web,\n style_function=style_facilities,\n tooltip=GeoJsonTooltip(\n fields=tooltip_fields,\n aliases=tooltip_aliases,\n localize=True,\n sticky=True\n )\n).add_to(dual_map_edu.m1)\n\n# Legend (optional but fine here)\ncmap_facilities.add_to(dual_map_edu.m1)\n\n\n0.02.24.36.58.710.813.0\n\n\n\n\nCode\nfor layer in acs_layers:\n fg = folium.FeatureGroup(name=layer[\"name\"], show=(layer[\"field\"] == \"pct_bachelors_plus\"))\n folium.GeoJson(\n tracts_access_web,\n style_function=layer[\"style\"],\n tooltip=GeoJsonTooltip(\n fields=[layer[\"field\"]],\n aliases=[f\"{layer['name']}:\"],\n localize=True,\n sticky=True\n )\n ).add_to(fg)\n fg.add_to(dual_map_edu.m2)\n layer[\"cmap\"].add_to(dual_map_edu.m2)\n\nfolium.LayerControl(collapsed=False).add_to(dual_map_edu.m2)\n\n\n0.529941706412294716.532.548.464.480.396.29629629629629% Bachelor's Degree or Higher\n\n\n\n\nCode\ntracts_access_web.head()\n\n\n\n\n\n\n\n\n\nSTATEFP\nCOUNTYFP\nTRACTCE\nGEOID\nNAME\nNAMELSAD\nMTFCC\nFUNCSTAT\nALAND\nAWATER\n...\nINTPTLON\ngeometry\npct_under_18\npct_bachelors_plus\nmedian_income\nfacility_count\nLibrary\nPark\nPlayground\nPool\n\n\n\n\n0\n42\n101\n026301\n42101026301\n263.01\nCensus Tract 263.01\nG5020\nS\n406340\n0\n...\n-075.1637161\nPOLYGON ((-75.16899 40.07147, -75.16864 40.071...\n22.435737\n28.359827\n57992\n0.0\n0.0\n0.0\n0.0\n0.0\n\n\n1\n42\n101\n029200\n42101029200\n292\nCensus Tract 292\nG5020\nS\n1745920\n28444\n...\n-075.1017831\nPOLYGON ((-75.11288 40.02746, -75.1128 40.0274...\n23.318995\n19.735431\n82784\n0.0\n0.0\n0.0\n0.0\n0.0\n\n\n2\n42\n101\n024400\n42101024400\n244\nCensus Tract 244\nG5020\nS\n421189\n0\n...\n-075.1638925\nPOLYGON ((-75.16912 40.02387, -75.16843 40.024...\n33.115265\n40.127077\n56912\n3.0\n0.0\n1.0\n2.0\n0.0\n\n\n3\n42\n101\n033200\n42101033200\n332\nCensus Tract 332\nG5020\nS\n842716\n0\n...\n-075.0449684\nPOLYGON ((-75.05464 40.04465, -75.05396 40.045...\n29.119272\n26.290400\n80409\n2.0\n0.0\n1.0\n0.0\n1.0\n\n\n4\n42\n101\n980200\n42101980200\n9802\nCensus Tract 9802\nG5020\nS\n4916641\n250846\n...\n-075.0443487\nPOLYGON ((-75.07448 40.08685, -75.07443 40.087...\n6.666667\n24.867725\n-666666666\n5.0\n0.0\n1.0\n4.0\n0.0\n\n\n\n\n5 rows × 21 columns\n\n\n\n\n\nCode\ndual_map_edu\n\n\nMake this Notebook Trusted to load map: File -> Trust Notebook\n\n\n\n\nCode\nfolium.GeoJson(\n tracts_access_web,\n style_function=style_facilities,\n tooltip=GeoJsonTooltip(\n fields=tooltip_fields,\n aliases=tooltip_aliases,\n localize=True,\n sticky=True\n )\n).add_to(dual_map.m1)\n\n\n<folium.features.GeoJson at 0x16ba98150>\n\n\n\n\nCode\nfor layer in acs_layers:\n fg = folium.FeatureGroup(name=layer[\"name\"], show=(layer[\"field\"] == \"pct_bachelors_plus\"))\n folium.GeoJson(\n tracts_access_web,\n style_function=layer[\"style\"],\n tooltip=GeoJsonTooltip(\n fields=[layer[\"field\"]],\n aliases=[f\"{layer['name']}:\"],\n localize=True,\n sticky=True\n )\n ).add_to(fg)\n fg.add_to(dual_map.m2)\n layer[\"cmap\"].add_to(dual_map.m2)\n\nfolium.LayerControl(collapsed=False).add_to(dual_map.m2)\n\n\n<folium.features.GeoJson at 0x16b7a7d10>\n\n\n\n\nCode\n# Add aligned legends for both map panes\ncmap_facilities.add_to(dual_map.m1)\n\n\n0.529941706412294716.532.548.464.480.396.29629629629629% Bachelor's Degree or Higher\n\n\n\n\nCode\ndual_map\n\n\nMake this Notebook Trusted to load map: File -> Trust Notebook"
},
{
"objectID": "index.html",
"href": "index.html",
"title": "Social Infrastructure in Cecil B. Moore & Fairmount Park",
"section": "",
"text": "This website examines the role of two social infrastructure sites: Cecil B. Moore Library in North Philadelphia and Carousel House in Fairmount Park. I analyze two different Reddit threads and utilize text mining methods to uncover key themes, term frequency, and overall sentiment related to recent developments at these sites.\n\n\nReddit Post from March 2025\nCecil B. Moore Library is a neighborhood institution in North Central Philadelphia that has served as a vital public resource for decades. Situated near Temple University, the library exists at the intersection of long-standing residential communities and expanding institutional presence, making it a focal point for broader conversations about public investment, neighborhood change, and access to social infrastructure. For many residents, the Cecil B. Moore Library represents not only a place of learning, but also a third place for children and adults.\nThe Reddit post that I am text mining centers on community responses to the potential closure of the Cecil B. Moore Library to accommodate proposed affordable housing on top of the existing building. These comments reveal how residents frame concerns about institutional neglect, displacement, and tensions around maintaining public space.\n\n\n<img src=\"CecilReddit.png\" style=\"width:100%; height:auto;\" alt=\"Reddit discussion on Cecil B. Moore Library\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Reddit Discussion on the Cecil B. Moore Library Proposal\n</p>\n\n\n<img src=\"InsideCecil.png\" style=\"width:100%; height:auto;\" alt=\"Interior of Cecil B. Moore Library\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Interior of the Cecil B. Moore Library\n</p>\n\n\n\n\n\nCarousel House was a public recreation center located near Center City Philadelphia that served children and families from across the city, with a particular emphasis on accessible programming for youth with physical disabilities. The facility closed in 2020, and subsequent plans to rebuild or replace it have been marked by delays, uncertainty, and shifting public commitments.\nThe Reddit post that I am text mining captures the closure of Carousel House in 2020 and the initial public reactions to the story.\n\n\n<img src=\"CarouselHouseReddit.png\" style=\"width:100%; height:auto;\" alt=\"Reddit discussion on Carousel House closure\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Reddit Discussion on the Carousel House Closure\n</p>\n\n\n<img src=\"Carousel-House.jpg\" style=\"width:100%; height:auto;\" alt=\"Carousel House in Fairmount Park\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Carousel House in Fairmount Park\n</p>"
},
{
"objectID": "index.html#cecil-b.-moore-library",
"href": "index.html#cecil-b.-moore-library",
"title": "Social Infrastructure in Cecil B. Moore & Fairmount Park",
"section": "",
"text": "Reddit Post from March 2025\nCecil B. Moore Library is a neighborhood institution in North Central Philadelphia that has served as a vital public resource for decades. Situated near Temple University, the library exists at the intersection of long-standing residential communities and expanding institutional presence, making it a focal point for broader conversations about public investment, neighborhood change, and access to social infrastructure. For many residents, the Cecil B. Moore Library represents not only a place of learning, but also a third place for children and adults.\nThe Reddit post that I am text mining centers on community responses to the potential closure of the Cecil B. Moore Library to accommodate proposed affordable housing on top of the existing building. These comments reveal how residents frame concerns about institutional neglect, displacement, and tensions around maintaining public space.\n\n\n<img src=\"CecilReddit.png\" style=\"width:100%; height:auto;\" alt=\"Reddit discussion on Cecil B. Moore Library\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Reddit Discussion on the Cecil B. Moore Library Proposal\n</p>\n\n\n<img src=\"InsideCecil.png\" style=\"width:100%; height:auto;\" alt=\"Interior of Cecil B. Moore Library\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Interior of the Cecil B. Moore Library\n</p>"
},
{
"objectID": "index.html#carousel-house",
"href": "index.html#carousel-house",
"title": "Social Infrastructure in Cecil B. Moore & Fairmount Park",
"section": "",
"text": "Carousel House was a public recreation center located near Center City Philadelphia that served children and families from across the city, with a particular emphasis on accessible programming for youth with physical disabilities. The facility closed in 2020, and subsequent plans to rebuild or replace it have been marked by delays, uncertainty, and shifting public commitments.\nThe Reddit post that I am text mining captures the closure of Carousel House in 2020 and the initial public reactions to the story.\n\n\n<img src=\"CarouselHouseReddit.png\" style=\"width:100%; height:auto;\" alt=\"Reddit discussion on Carousel House closure\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Reddit Discussion on the Carousel House Closure\n</p>\n\n\n<img src=\"Carousel-House.jpg\" style=\"width:100%; height:auto;\" alt=\"Carousel House in Fairmount Park\">\n<p style=\"font-size: 13px; margin-top: 4px;\">\n Carousel House in Fairmount Park\n</p>"
},
{
"objectID": "map.html",
"href": "map.html",
"title": "Social Infrastructure in Philadelphia",
"section": "",
"text": "This page maps social infrastructure across the City of Philadelphia at the census tract level, showing how the concentration of facilities such as libraries, recreation centers, playgrounds, and community buildings varies alongside key demographic and socioeconomic indicators. These sites play an important role in supporting neighborhood stability and collective life. The interactive map allows users to compare social infrastructure counts by tract with median household income, the share of residents with a bachelor’s degree or higher, and the percentage of the population under age 18, offering insight into how access to social infrastructure aligns with community needs and resources"
},
{
"objectID": "map.html#social-infrastructure-map-count-by-census-tract-vs-median-income-percent-of-bachelors-degree-or-more-and-percentage-of-population-18-years-and-younger",
"href": "map.html#social-infrastructure-map-count-by-census-tract-vs-median-income-percent-of-bachelors-degree-or-more-and-percentage-of-population-18-years-and-younger",
"title": "Social Infrastructure in Philadelphia",
"section": "Social Infrastructure Map Count by Census Tract vs Median Income, Percent of Bachelor’s Degree or more, and Percentage of population 18 years and younger",
"text": "Social Infrastructure Map Count by Census Tract vs Median Income, Percent of Bachelor’s Degree or more, and Percentage of population 18 years and younger"
},
{
"objectID": "SocialInf_14.html",
"href": "SocialInf_14.html",
"title": "APIs and Sentiment Text Analysis",
"section": "",
"text": "API CALL FOR REDDIT ON CECIL B. MOORE LIBRARY"
},
{
"objectID": "SocialInf_14.html#reddit-post-data-cleaning",
"href": "SocialInf_14.html#reddit-post-data-cleaning",
"title": "APIs and Sentiment Text Analysis",
"section": "Reddit Post Data Cleaning",
"text": "Reddit Post Data Cleaning\n\n\nCode\n#Remove lowercase,line breaks, and unwanted spaces\ncecillibrary[\"clean_body\"] = (\n cecillibrary[\"body\"]\n .fillna(\"\")\n .str.lower()\n .str.replace(\"\\n\", \" \", regex=False)\n .str.strip()\n)\n\n\n\n\nCode\n#Remove deleted comments\n\ncecillibrary = cecillibrary[~cecillibrary[\"clean_body\"].isin([\"[deleted]\", \"[removed]\"])]\n\n\n\n\nCode\n#Remove Urls\nimport re\n\ncecillibrary[\"clean_body\"] = cecillibrary[\"clean_body\"].apply(\n lambda x: re.sub(r\"http\\S+|www\\.\\S+\", \"\", x)\n)\n\n\n\n\nCode\n#Remove punctuation\ncecillibrary[\"clean_body\"] = cecillibrary[\"clean_body\"].str.replace(r\"[^\\w\\s]\", \"\", regex=True)\n\n\n\n\nCode\n#Remove extra spaces\n\ncecillibrary[\"clean_body\"] = cecillibrary[\"clean_body\"].str.replace(r\"\\s+\", \" \", regex=True)"
},
{
"objectID": "analysis.html",
"href": "analysis.html",
"title": "Reddit Analysis Comparison of Text",
"section": "",
"text": "Sentiment Distribution\n\n\n\nDistribution of Scores\n\n\n\n\n\n\nWord Cloud\n\n\n\nMost Common Words\n\n\n\n\n\n\nComment Depth\n\n\n\nScores by Depth\n\n\n\n\n\n\nSentiment Score and Reddit Upvotes\n\n\n\nSentiment Scores vs Reddit Upvotes"
},
{
"objectID": "analysis.html#reddit-analysis-findings-for-cecil-b.-moore-library",
"href": "analysis.html#reddit-analysis-findings-for-cecil-b.-moore-library",
"title": "Reddit Analysis Comparison of Text",
"section": "",
"text": "Sentiment Distribution\n\n\n\nDistribution of Scores\n\n\n\n\n\n\nWord Cloud\n\n\n\nMost Common Words\n\n\n\n\n\n\nComment Depth\n\n\n\nScores by Depth\n\n\n\n\n\n\nSentiment Score and Reddit Upvotes\n\n\n\nSentiment Scores vs Reddit Upvotes"
},
{
"objectID": "analysis.html#top-ten-most-positive-and-negative-sentiments-on-cecil-b.-moore-reddit",
"href": "analysis.html#top-ten-most-positive-and-negative-sentiments-on-cecil-b.-moore-reddit",
"title": "Reddit Analysis Comparison of Text",
"section": "Top Ten Most Positive and Negative Sentiments on Cecil B. Moore Reddit",
"text": "Top Ten Most Positive and Negative Sentiments on Cecil B. Moore Reddit\n\n\n \n Top 10 Positive Comments\n \n \n\n \n Top 10 Negative Comments"
},
{
"objectID": "analysis.html#reddit-analysis-findings-for-carousel-house",
"href": "analysis.html#reddit-analysis-findings-for-carousel-house",
"title": "Reddit Analysis Comparison of Text",
"section": "Reddit Analysis Findings for Carousel House",
"text": "Reddit Analysis Findings for Carousel House\n\n\n\n\n\nSentiment Distribution\n\n\n\nDistribution of Scores\n\n\n\n\n\n\nWord Cloud\n\n\n\nMost Common Words\n\n\n\n\n\n\nComment Depth\n\n\n\nScores by Depth\n\n\n\n\n\n\nSentiment Score and Reddit Upvotes\n\n\n\nSentiment Scores vs Reddit Upvotes"
},
{
"objectID": "analysis.html#top-ten-most-positive-and-negative-sentiments-on-carousel-house-reddit",
"href": "analysis.html#top-ten-most-positive-and-negative-sentiments-on-carousel-house-reddit",
"title": "Reddit Analysis Comparison of Text",
"section": "Top Ten Most Positive and Negative Sentiments on Carousel House Reddit",
"text": "Top Ten Most Positive and Negative Sentiments on Carousel House Reddit\n\n\n \n Top 10 Positive Comments\n \n \n\n \n Top 10 Negative Comments\n \n \n\n\n\n Comparison between Carousel House Reddit and Cecil B. Moore Library Comments \n\n\n\n \n\n \n Major Themes by Reddit Threads"
}
]