--- title: From ACS Download to Gif keywords: fastai sidebar: home_sidebar summary: "In this tutorial, we run the full gambit, from downloading acs data to creating map gifs across several years of data" description: "In this tutorial, we run the full gambit, from downloading acs data to creating map gifs across several years of data" nb_path: "notebooks/05_ACS_From_Download_To_Gif.ipynb" ---
{% raw %}
{% endraw %}

This Coding Notebook is the fifth in a series.

An Interactive version can be found here Open In Colab.

This colab and more can be found on our webpage.

  • Content covered in previous tutorials will be used in later tutorials.

  • New code and or information should have explanations and or descriptions attached.

  • Concepts or code covered in previous tutorials will be used without being explaining in entirety.

  • The Dataplay Handbook development techniques covered in the Datalabs Guidebook

  • If content can not be found in the current tutorial and is not covered in previous tutorials, please let me know.

  • This notebook has been optimized for Google Colabs ran on a Chrome Browser.

  • Statements found in the index page on view expressed, responsibility, errors and ommissions, use at risk, and licensing extend throughout the tutorial.

Binder Binder Binder Open Source Love svg3

NPM License Active Python Versions GitHub last commit No Maintenance Intended

GitHub stars GitHub watchers GitHub forks GitHub followers

Tweet Twitter Follow

About this Tutorial:

Whats Inside?

In this colab

  1. We will programmatically download data from the American Community Survey (ACS)
    • ACS data are estimates come from survey respondents across 5 year
    • ACS data comes in at a tract level geographic granularity
    • Our examples will primarily use table B19001, Baltimore City 2017 estimates
  1. We will rework the datasets to be human friendly
  2. We will create Vital Signs Indicators from calculations using these datasets
  3. We will create convenience functions to wrap up everything we have learnt

Median Household Income is just one of the many operations that may perfrom on the data using publicly available code found in our github codebase.

This colab and more can be found at https://gist.github.com/bniajfi

Developers Resource: https://www.census.gov/developers/

ACS API: https://www.census.gov/data/developers/data-sets.html

*please note

  • A table of contents is provided in the menu to the left.
  • And, that this notebook has been optimized for Google Colabs ran on a Chrome Browser.
  • While still fully usable, non-critical section of code (eg. Python Magics and HTML) may break if used in a different enviornment.

Import Python Modules

You will need to run this next box first in order for any of the code after it to work

{% raw %}
%%capture
! pip install -U -q PyDrive
! pip install geopy
! pip install geopandas
! pip install geoplot
! pip install dexplot
! pip install dataplay
{% endraw %} {% raw %}
 
{% endraw %} {% raw %}
Requirement already satisfied: geopandas in /usr/local/lib/python3.7/dist-packages (0.9.0)
Requirement already satisfied: pyproj>=2.2.0 in /usr/local/lib/python3.7/dist-packages (from geopandas) (3.0.1)
Requirement already satisfied: pandas>=0.24.0 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.1.5)
Requirement already satisfied: fiona>=1.8 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.8.18)
Requirement already satisfied: shapely>=1.6 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.7.1)
Requirement already satisfied: certifi in /usr/local/lib/python3.7/dist-packages (from pyproj>=2.2.0->geopandas) (2020.12.5)
Requirement already satisfied: numpy>=1.15.4 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (1.19.5)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (2018.9)
Requirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (2.8.1)
Requirement already satisfied: attrs>=17 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (20.3.0)
Requirement already satisfied: cligj>=0.5 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (0.7.1)
Requirement already satisfied: munch in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (2.5.0)
Requirement already satisfied: click<8,>=4.0 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (7.1.2)
Requirement already satisfied: six>=1.7 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (1.15.0)
Requirement already satisfied: click-plugins>=1.0 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (1.1.1)
Enabling notebook extension jupyter-js-widgets/extension...
      - Validating: OK
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:27: FutureWarning: Passing a negative integer is deprecated in version 1.0 and will not be supported in future version. Instead, use None to not limit the column width.
/usr/local/lib/python3.7/dist-packages/dataplay/acsDownload.py:27: FutureWarning: Passing a negative integer is deprecated in version 1.0 and will not be supported in future version. Instead, use None to not limit the column width.
  pd.set_option('display.max_colwidth', -1)
/usr/local/lib/python3.7/dist-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
  """)
{% endraw %}

Get Table Data

Now use this function to Download the Data!

{% raw %}
# Change these values in the cell below using different geographic reference codes will change those parameters
tract = '*'
county = '510'
state = '24'

# Specify the download parameters the function will receieve here
tableId = 'B19001'
year = '17'
saveAcs = True
{% endraw %} {% raw %}
df = retrieve_acs_data(state, county, tract, tableId, year, saveAcs)
df.head()
Number of Columns 17
B19001_001E_Total B19001_002E_Total_Less_than_$10_000 B19001_003E_Total_$10_000_to_$14_999 B19001_004E_Total_$15_000_to_$19_999 B19001_005E_Total_$20_000_to_$24_999 B19001_006E_Total_$25_000_to_$29_999 B19001_007E_Total_$30_000_to_$34_999 B19001_008E_Total_$35_000_to_$39_999 B19001_009E_Total_$40_000_to_$44_999 B19001_010E_Total_$45_000_to_$49_999 B19001_011E_Total_$50_000_to_$59_999 B19001_012E_Total_$60_000_to_$74_999 B19001_013E_Total_$75_000_to_$99_999 B19001_014E_Total_$100_000_to_$124_999 B19001_015E_Total_$125_000_to_$149_999 B19001_016E_Total_$150_000_to_$199_999 B19001_017E_Total_$200_000_or_more state county tract
NAME
Census Tract 1901 796 237 76 85 38 79 43 36 35 15 43 45 39 5 0 6 14 24 510 190100
Census Tract 1902 695 63 87 93 6 58 30 14 29 23 38 113 70 6 32 11 22 24 510 190200
Census Tract 2201 2208 137 229 124 52 78 87 50 80 13 217 66 159 205 167 146 398 24 510 220100
Census Tract 2303 632 3 20 0 39 7 0 29 8 9 44 29 98 111 63 94 78 24 510 230300
Census Tract 2502.07 836 102 28 101 64 104 76 41 40 47 72 28 60 19 27 15 12 24 510 250207
{% endraw %}

CROSSWALK

{% raw %}
pd.set_option('max_colwidth', 20)
{% endraw %} {% raw %}
mapUrl = "https://opendata.arcgis.com/datasets/b738a8587b6d479a8824d937892701d8_0.geojson"
# mapUrl = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQ8xXdUaT17jkdK0MWTJpg3GOy6jMWeaXTlguXNjCSb8Vr_FanSZQRaTU-m811fQz4kyMFK5wcahMNY/pub?gid=886223646&single=true&output=csv"

csaMap = readInGeometryData(url=mapUrl, porg='g', geom='geometry', lat=False, lng=False, revgeocode=False, save=False, in_crs=2248, out_crs=2248)

csaMap.head()

csaMap.plot()

csaMap = pd.DataFrame(csaMap)
RECIEVED url: https://opendata.arcgis.com/datasets/b738a8587b6d479a8824d937892701d8_0.geojson, 
 porg: g, 
 geom: geometry, 
 lat: False, 
 lng: False, 
 revgeocode: False, 
 in_crs: 2248, 
 out_crs: 2248
OBJECTID CSA2010 tpop10 male10 female10 paa17 pwhite17 pasi17 p2more17 ppac17 phisp17 racdiv17 age5_17 age18_17 age24_17 age64_17 age65_17 hhs10 femhhs17 fam17 hhsize10 mhhi17 hh25inc17 hh40inc17 hh60inc17 hh75inc17 hhm7517 hhpov17 hhchpov17 Shape__Area Shape__Length geometry
0 1 Allendale/Irving... 16726 7657 9069 90.284587 6.534736 0.113596 1.004424 0.000000 2.062657 20.115274 6.612460 17.374148 9.003946 53.288294 13.721153 6098 71.129707 35.198822 2.64 39495.628472 32.989691 17.722140 19.914908 11.945672 17.427590 20.695061 32.770530 6.377046e+07 38770.165571 POLYGON ((-76.65...
1 2 Beechfield/Ten H... 13391 5985 7406 75.319244 18.855948 0.418191 3.308192 0.313643 1.784781 41.017612 7.930700 14.576955 9.708013 55.365544 12.418789 5076 55.187320 26.144283 2.40 57572.502747 20.418158 13.900923 18.176681 10.868337 36.635901 10.474907 23.916752 4.788253e+07 37524.950533 POLYGON ((-76.69...
2 3 Belair-Edison 17380 7297 10083 85.650173 10.028769 0.569620 1.697353 0.811277 1.242808 27.255998 5.420023 22.807825 8.406214 54.453395 8.912543 6174 77.529057 38.270181 2.90 39624.482085 34.102142 16.276771 20.065898 8.105437 21.449753 20.274577 34.555625 4.495003e+07 31307.314843 POLYGON ((-76.56...
3 4 Brooklyn/Curtis ... 12900 5746 7154 37.961240 39.682171 2.527132 3.612403 1.310078 14.906977 73.926734 10.906977 16.093023 8.248062 57.449612 7.302326 5204 43.393602 32.321870 2.61 40275.275330 31.400315 18.318723 18.521016 9.080692 22.679254 24.213606 46.409959 1.760777e+08 150987.703639 MULTIPOLYGON (((...
4 5 Canton 8326 4094 4232 3.939467 85.575306 4.383858 2.450156 0.564497 3.086716 26.305424 5.248619 3.122748 5.849147 75.246217 10.533269 4310 10.550459 11.029598 1.86 111891.251825 7.412092 7.816848 9.182899 6.425500 69.162661 3.661784 4.017217 1.540854e+07 23338.611948 POLYGON ((-76.57...
<matplotlib.axes._subplots.AxesSubplot at 0x7fec21ec7c18>
{% endraw %} {% raw %}
# Instructions to do this yoruself: https://support.google.com/docs/answer/183965?co=GENIE.Platform%3DDesktop&hl=en

# Primary Table
left_ds = df
left_col = 'tract'

# Crosswalk Table
# Table: Crosswalk Census Communities
# 'TRACT2010', 'GEOID2010', 'CSA2010'
crosswalk_ds = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE/pub?output=csv'

# Secondary Table
# Table: Baltimore Boundaries
# 'TRACTCE10', 'GEOID10', 'CSA', 'NAME10', 'Tract', 'geometry'

merge_how = 'geometry'
interactive = True
merge_how = 'outer'

merged = mergeDatasets( left_ds=df, left_col='tract', 
              use_crosswalk=True, crosswalk_ds=crosswalk_ds,
              crosswalk_left_col = 'TRACT2010', crosswalk_right_col = 'CSA2010',
              right_ds=csaMap, right_col='CSA2010', 
              merge_how=merge_how, interactive = False )
retrieveDatasetFromUrl                       B19001_001E_Total  ...    GEOID2010
NAME                                     ...             
Census Tract 1901                   796  ...  24510190100
Census Tract 1902                   695  ...  24510190200
Census Tract 2201                  2208  ...  24510220100
Census Tract 2303                   632  ...  24510230300
Census Tract 2502.07                836  ...  24510250207
...                                 ...  ...          ...
Census Tract 2720.05               1219  ...  24510272005
Census Tract 1202.01                883  ...  24510120201
Census Tract 2720.04               1835  ...  24510272004
Census Tract 2720.06               1679  ...  24510272006
Baltimore City                   239791  ...            0

[201 rows x 22 columns]
checkDataSetExists True
checkDataSetExists True
checkDataSetExists True
retrieveDatasetFromUrl     OBJECTID              CSA2010  ...  Shape__Length             geometry
0          1  Allendale/Irving...  ...   38770.165571  POLYGON ((-76.65...
1          2  Beechfield/Ten H...  ...   37524.950533  POLYGON ((-76.69...
2          3        Belair-Edison  ...   31307.314843  POLYGON ((-76.56...
3          4  Brooklyn/Curtis ...  ...  150987.703639  MULTIPOLYGON (((...
4          5               Canton  ...   23338.611948  POLYGON ((-76.57...
5          6    Cedonia/Frankford  ...   39962.549835  POLYGON ((-76.52...
6          7          Cherry Hill  ...   22305.302067  POLYGON ((-76.61...
7          8  Chinquapin Park/...  ...   21705.411630  POLYGON ((-76.59...
8          9  Claremont/Armistead  ...   40104.415980  POLYGON ((-76.52...
9         10        Clifton-Berea  ...   24022.764621  POLYGON ((-76.58...
10        11  Cross-Country/Ch...  ...   26788.301878  POLYGON ((-76.67...
11        12  Dickeyville/Fran...  ...   31637.817424  POLYGON ((-76.70...
12        13  Dorchester/Ashbu...  ...   27136.075712  POLYGON ((-76.67...
13        14  Downtown/Seton Hill  ...   21565.859395  POLYGON ((-76.61...
14        15    Edmondson Village  ...   21504.551358  POLYGON ((-76.67...
15        16          Fells Point  ...   27670.169916  POLYGON ((-76.58...
16        17  Forest Park/Walb...  ...   36886.899781  POLYGON ((-76.67...
17        18       Glen-Fallstaff  ...   48549.004618  POLYGON ((-76.67...
18        19  Greater Charles ...  ...   26454.269211  POLYGON ((-76.60...
19        20       Greater Govans  ...   22982.125715  POLYGON ((-76.59...
20        21    Greater Mondawmin  ...   31136.731890  POLYGON ((-76.65...
21        22  Greater Roland P...  ...   39862.749795  POLYGON ((-76.62...
22        23     Greater Rosemont  ...   32559.076221  POLYGON ((-76.65...
23        24             Hamilton  ...   27712.111092  POLYGON ((-76.52...
24        25     Harford/Echodale  ...   40019.185400  POLYGON ((-76.52...
25        26         Highlandtown  ...   14976.123851  POLYGON ((-76.56...
26        27  Howard Park/West...  ...   36034.498447  POLYGON ((-76.68...
27        28  Inner Harbor/Fed...  ...   43415.059548  POLYGON ((-76.60...
28        29           Lauraville  ...   34419.676528  POLYGON ((-76.56...
29        30           Loch Raven  ...   29314.334672  POLYGON ((-76.57...
30        31     Madison/East End  ...   13120.158719  POLYGON ((-76.58...
31        32  Medfield/Hampden...  ...   43152.625699  POLYGON ((-76.62...
32        33    Midway/Coldstream  ...   22767.827416  POLYGON ((-76.58...
33        34  Morrell Park/Vio...  ...   44412.745130  POLYGON ((-76.65...
34        35  Mount Washington...  ...   38539.766148  POLYGON ((-76.64...
35        36  North Baltimore/...  ...   42904.222144  POLYGON ((-76.60...
36        37            Northwood  ...   38889.894591  POLYGON ((-76.57...
37        38  Orangeville/East...  ...   47825.862927  POLYGON ((-76.52...
38        39  Patterson Park N...  ...   21786.374660  POLYGON ((-76.56...
39        40  Penn North/Reser...  ...   29078.838499  POLYGON ((-76.62...
40        41  Pimlico/Arlingto...  ...   24725.934069  POLYGON ((-76.65...
41        42  Poppleton/The Te...  ...   12334.027535  POLYGON ((-76.62...
42        43  Sandtown-Winches...  ...   20987.143307  POLYGON ((-76.63...
43        44      South Baltimore  ...   68440.025827  MULTIPOLYGON (((...
44        45         Southeastern  ...  102291.480548  POLYGON ((-76.52...
45        46  Southern Park He...  ...   24052.221372  POLYGON ((-76.65...
46        47  Southwest Baltimore  ...   28355.563581  POLYGON ((-76.65...
47        48        The Waverlies  ...   18733.826880  POLYGON ((-76.59...
48        49  Washington Villa...  ...   36962.260095  POLYGON ((-76.62...
49        50  Westport/Mount W...  ...   42573.124416  POLYGON ((-76.62...
50        51  Oldtown/Middle East  ...   23866.328179  POLYGON ((-76.58...
51        52  Harbor East/Litt...  ...   18552.407582  POLYGON ((-76.59...
52        53  Upton/Druid Heights  ...   19389.307821  POLYGON ((-76.63...
53        54              Midtown  ...   25020.096970  POLYGON ((-76.61...
54        55      Greenmount East  ...   20797.473458  POLYGON ((-76.59...

[55 rows x 32 columns]
checkDataSetExists True
checkDataSetExists True
checkDataSetExists True
checkDataSetExists False
retrieveDatasetFromUrl https://docs.google.com/spreadsheets/d/e/2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE/pub?output=csv
checkDataSetExists False
retrieveDatasetFromUrl https://docs.google.com/spreadsheets/d/e/2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE/pub?output=csv
checkDataSetExists True
checkDataSetExists True
checkDataSetExists True
retrieveDatasetFromUrl https://docs.google.com/spreadsheets/d/e/2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE/pub?output=csv
checkDataSetExists False
retrieveDatasetFromUrl https://docs.google.com/spreadsheets/d/e/2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE/pub?output=csv
checkDataSetExists True
checkDataSetExists True
checkDataSetExists True
{% endraw %} {% raw %}
merged.columns = merged.columns.str.replace("$", "")
{% endraw %} {% raw %}
merged.head()
B19001_001E_Total B19001_002E_Total_Less_than_10_000 B19001_003E_Total_10_000_to_14_999 B19001_004E_Total_15_000_to_19_999 B19001_005E_Total_20_000_to_24_999 B19001_006E_Total_25_000_to_29_999 B19001_007E_Total_30_000_to_34_999 B19001_008E_Total_35_000_to_39_999 B19001_009E_Total_40_000_to_44_999 B19001_010E_Total_45_000_to_49_999 B19001_011E_Total_50_000_to_59_999 B19001_012E_Total_60_000_to_74_999 B19001_013E_Total_75_000_to_99_999 B19001_014E_Total_100_000_to_124_999 B19001_015E_Total_125_000_to_149_999 B19001_016E_Total_150_000_to_199_999 B19001_017E_Total_200_000_or_more state county tract CSA2010 GEOID2010 OBJECTID tpop10 male10 female10 paa17 pwhite17 pasi17 p2more17 ppac17 phisp17 racdiv17 age5_17 age18_17 age24_17 age64_17 age65_17 hhs10 femhhs17 fam17 hhsize10 mhhi17 hh25inc17 hh40inc17 hh60inc17 hh75inc17 hhm7517 hhpov17 hhchpov17 Shape__Area Shape__Length geometry
0 796 237 76 85 38 79 43 36 35 15 43 45 39 5 0 6 14 24 510 190100 Southwest Baltimore 24510190100 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
1 695 63 87 93 6 58 30 14 29 23 38 113 70 6 32 11 22 24 510 190200 Southwest Baltimore 24510190200 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
2 567 186 25 17 24 29 46 14 46 35 9 61 47 0 0 15 13 24 510 200100 Southwest Baltimore 24510200100 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
3 861 204 154 68 90 31 31 47 4 19 32 93 53 12 6 5 12 24 510 190300 Southwest Baltimore 24510190300 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
4 502 148 50 22 41 30 30 22 23 30 9 34 19 36 0 8 0 24 510 200300 Southwest Baltimore 24510200300 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
{% endraw %} {% raw %}
gdf = gpd.GeoDataFrame(merged, geometry='geometry')
gdf.plot()
gdf.head()
<matplotlib.axes._subplots.AxesSubplot at 0x7fec21dc7908>
B19001_001E_Total B19001_002E_Total_Less_than_10_000 B19001_003E_Total_10_000_to_14_999 B19001_004E_Total_15_000_to_19_999 B19001_005E_Total_20_000_to_24_999 B19001_006E_Total_25_000_to_29_999 B19001_007E_Total_30_000_to_34_999 B19001_008E_Total_35_000_to_39_999 B19001_009E_Total_40_000_to_44_999 B19001_010E_Total_45_000_to_49_999 B19001_011E_Total_50_000_to_59_999 B19001_012E_Total_60_000_to_74_999 B19001_013E_Total_75_000_to_99_999 B19001_014E_Total_100_000_to_124_999 B19001_015E_Total_125_000_to_149_999 B19001_016E_Total_150_000_to_199_999 B19001_017E_Total_200_000_or_more state county tract CSA2010 GEOID2010 OBJECTID tpop10 male10 female10 paa17 pwhite17 pasi17 p2more17 ppac17 phisp17 racdiv17 age5_17 age18_17 age24_17 age64_17 age65_17 hhs10 femhhs17 fam17 hhsize10 mhhi17 hh25inc17 hh40inc17 hh60inc17 hh75inc17 hhm7517 hhpov17 hhchpov17 Shape__Area Shape__Length geometry
0 796 237 76 85 38 79 43 36 35 15 43 45 39 5 0 6 14 24 510 190100 Southwest Baltimore 24510190100 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
1 695 63 87 93 6 58 30 14 29 23 38 113 70 6 32 11 22 24 510 190200 Southwest Baltimore 24510190200 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
2 567 186 25 17 24 29 46 14 46 35 9 61 47 0 0 15 13 24 510 200100 Southwest Baltimore 24510200100 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
3 861 204 154 68 90 31 31 47 4 19 32 93 53 12 6 5 12 24 510 190300 Southwest Baltimore 24510190300 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
4 502 148 50 22 41 30 30 22 23 30 9 34 19 36 0 8 0 24 510 200300 Southwest Baltimore 24510200300 47.0 16843.0 8130.0 8713.0 73.573591 12.782758 2.873597 2.962655 1.07463 6.732767 49.751399 10.324764 18.250905 7.730214 52.80532 10.888797 6288.0 60.681115 33.396519 2.81 25427.842342 49.508875 17.404791 12.011029 9.581251 11.494055 35.783245 49.225293 3.776607e+07 28355.563581 POLYGON ((-76.65...
{% endraw %} {% raw %}
gdf['tempsCount'] = 1
temp = gdf.groupby('CSA2010').sum(numeric_only=True) 
temp = temp.reset_index()
temp
CSA2010 B19001_001E_Total B19001_002E_Total_Less_than_10_000 B19001_003E_Total_10_000_to_14_999 B19001_004E_Total_15_000_to_19_999 B19001_005E_Total_20_000_to_24_999 B19001_006E_Total_25_000_to_29_999 B19001_007E_Total_30_000_to_34_999 B19001_008E_Total_35_000_to_39_999 B19001_009E_Total_40_000_to_44_999 B19001_010E_Total_45_000_to_49_999 B19001_011E_Total_50_000_to_59_999 B19001_012E_Total_60_000_to_74_999 B19001_013E_Total_75_000_to_99_999 B19001_014E_Total_100_000_to_124_999 B19001_015E_Total_125_000_to_149_999 B19001_016E_Total_150_000_to_199_999 B19001_017E_Total_200_000_or_more state county tract GEOID2010 OBJECTID tpop10 male10 female10 paa17 pwhite17 pasi17 p2more17 ppac17 phisp17 racdiv17 age5_17 age18_17 age24_17 age64_17 age65_17 hhs10 femhhs17 fam17 hhsize10 mhhi17 hh25inc17 hh40inc17 hh60inc17 hh75inc17 hhm7517 hhpov17 hhchpov17 Shape__Area Shape__Length tempsCount
0 Allendale/Irving... 6111 739 507 410 360 341 310 432 361 263 593 730 573 228 115 88 61 144 3060 1333309 147061333309 6.0 100356.0 45942.0 54414.0 541.707521 39.208418 0.681574 6.026545 0.000000 12.375942 120.691643 39.674758 104.244888 54.023676 319.729762 82.326916 36588.0 426.778243 211.192931 15.84 236973.770833 197.938144 106.332842 119.489445 71.674030 104.565538 124.170368 196.623177 3.826228e+08 232620.993427 6
1 Baltimore City 239791 29106 15759 13992 11786 12818 12304 10610 10261 9641 18773 21563 25273 16094 10011 10712 11088 24 510 10000 0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000e+00 0.000000 1
2 Beechfield/Ten H... 5309 285 297 306 196 216 368 154 244 175 546 577 793 489 287 124 252 72 1530 810905 73530810905 6.0 40173.0 17955.0 22218.0 225.957733 56.567844 1.254574 9.924576 0.940930 5.354342 123.052836 23.792099 43.730864 29.124039 166.096632 37.256366 15228.0 165.561960 78.432850 7.20 172717.508242 61.254474 41.702769 54.530043 32.605010 109.907704 31.424722 71.750256 1.436476e+08 112574.851600 3
3 Belair-Edison 6070 877 422 445 326 363 318 307 260 361 597 492 618 281 174 117 112 96 2040 680806 98040680806 12.0 69520.0 29188.0 40332.0 342.600690 40.115075 2.278481 6.789413 3.245109 4.971231 109.023992 21.680092 91.231300 33.624856 217.813579 35.650173 24696.0 310.116229 153.080725 11.60 158497.928339 136.408567 65.107084 80.263591 32.421746 85.799012 81.098308 138.222498 1.798001e+08 125229.259374 4
4 Brooklyn/Curtis ... 4449 459 273 369 296 250 311 254 227 270 327 404 557 249 37 77 89 96 2040 1001903 98041001903 16.0 51600.0 22984.0 28616.0 151.844961 158.728682 10.108527 14.449612 5.240310 59.627907 295.706937 43.627907 64.372093 32.992248 229.798450 29.209302 20816.0 173.574409 129.287480 10.44 161101.101322 125.601259 73.274893 74.084064 36.322769 90.717015 96.854426 185.639838 7.043110e+08 603950.814555 4
5 Canton 3953 157 57 17 62 119 113 77 50 104 209 254 562 411 477 603 681 72 1530 30800 73530030800 15.0 24978.0 12282.0 12696.0 11.818400 256.725919 13.151573 7.350468 1.693490 9.260149 78.916271 15.745856 9.368244 17.547442 225.738650 31.599808 12930.0 31.651376 33.088793 5.58 335673.755474 22.236276 23.450544 27.548697 19.276499 207.487984 10.985353 12.051650 4.622561e+07 70015.835843 3
6 Cedonia/Frankford 9180 960 571 420 456 536 842 672 409 405 788 814 1048 575 320 260 104 120 2550 1300809 122551300809 30.0 117760.0 52400.0 65360.0 402.832031 58.572520 17.747962 3.885020 0.339674 16.622792 179.585940 31.186311 77.445652 44.794497 296.556556 50.016984 46740.0 218.577221 147.766885 12.70 208127.958435 131.100218 111.655773 87.254902 44.335512 125.653595 60.910704 99.819059 3.577067e+08 199812.749174 5
7 Cherry Hill 3001 732 307 345 137 166 245 126 117 147 157 113 190 112 59 15 33 72 1530 750614 73530750614 21.0 24204.0 10872.0 13332.0 262.407040 13.088746 2.788795 4.276153 0.000000 17.439266 90.831419 24.950421 81.581557 27.404561 136.725335 29.338126 9435.0 226.860565 116.861046 7.71 72752.923358 152.049317 53.682106 42.085971 11.296235 40.886371 118.011050 170.363891 8.743254e+07 66915.906200 3
8 Chinquapin Park/... 3327 337 97 197 158 175 166 135 132 122 340 267 526 254 125 191 105 48 1020 541609 49020541609 16.0 16900.0 7384.0 9516.0 137.656805 41.585799 3.644970 5.230769 0.000000 11.881657 102.063330 11.881657 29.893491 14.958580 117.491124 25.775148 6718.0 84.460261 50.676285 4.52 108499.150000 47.430117 28.614367 35.707845 16.050496 72.197175 20.251836 46.324387 4.204518e+07 43410.823261 2
9 Claremont/Armistead 3512 515 323 186 242 281 218 214 266 153 377 185 276 148 101 6 21 96 2040 1041509 98041041509 36.0 37276.0 17412.0 19864.0 222.856530 96.576886 0.772615 16.353686 2.446614 60.993669 269.129788 42.965983 81.725507 36.398755 205.043460 33.866295 13676.0 223.082881 147.038724 9.64 139170.477064 144.191344 81.207289 90.660592 21.070615 62.870159 96.000000 138.461538 2.449751e+08 160417.663921 4
10 Clifton-Berea 3210 589 308 187 187 258 166 212 224 113 221 216 237 155 17 87 33 120 2550 401703 122550401703 50.0 45455.0 20840.0 24615.0 468.320317 11.824882 2.089979 7.259927 0.329997 10.174898 72.890513 27.169728 92.399076 43.944561 260.697393 75.789242 17645.0 318.874560 132.866044 14.15 161443.493976 197.975078 99.065421 86.915888 33.644860 82.398754 138.247639 239.622642 1.164262e+08 120113.823104 5
11 Cross-Country/Ch... 4972 308 171 228 227 329 263 305 211 238 334 576 326 493 252 339 372 72 1530 816012 73530816012 33.0 38784.0 17739.0 21045.0 59.800433 220.219678 10.117574 0.371287 1.508354 7.982673 124.917777 29.447710 49.845297 28.705136 134.521968 57.479889 16023.0 55.200000 82.964602 7.32 168501.143713 56.355591 54.123089 47.244570 34.754626 107.522124 29.682366 39.076377 1.146661e+08 80364.905635 3
12 Dickeyville/Fran... 1740 352 99 130 82 93 31 47 123 114 98 152 206 142 12 26 33 24 510 280301 24510280301 12.0 3731.0 1563.0 2168.0 80.595015 9.541678 1.661753 5.601715 0.804074 1.795765 36.353799 14.848566 9.112838 10.024122 54.435808 11.578665 1877.0 68.837209 24.712644 2.18 41463.121951 38.103448 9.827586 19.252874 8.735632 24.080460 17.408907 34.451902 3.571911e+07 31637.817424 1
13 Dorchester/Ashbu... 4252 567 131 283 190 345 252 224 184 166 444 329 498 141 247 238 13 48 1020 302100 49020302100 26.0 23364.0 10708.0 12656.0 191.902072 2.140045 0.342407 2.944701 0.701935 1.968841 19.374210 12.720425 35.661702 13.456600 102.705016 35.456257 9130.0 129.220779 57.949200 5.16 87281.152174 55.079962 38.617121 37.347131 15.475071 53.480715 34.890220 86.985539 6.823655e+07 54272.151423 2
14 Downtown/Seton Hill 3529 547 219 145 108 75 176 61 187 140 283 527 462 271 84 120 124 72 1530 250400 73530250400 42.0 19599.0 10203.0 9396.0 87.065667 131.884280 48.767794 4.821675 12.582275 14.878310 207.967563 5.189040 10.607684 55.426297 213.806827 14.970152 11028.0 219.815668 18.447152 4.65 161288.623675 86.625106 26.523094 51.856050 44.800227 90.195523 20.454545 40.116279 6.220966e+07 64697.578184 3
15 Edmondson Village 2841 187 86 206 221 246 242 176 172 314 227 286 221 98 65 70 24 72 1530 602005 73530602005 45.0 24480.0 11382.0 13098.0 287.279412 4.044118 0.000000 2.389706 2.352941 3.933824 25.126788 22.352941 48.345588 27.316176 155.036765 46.948529 8625.0 186.638831 101.161563 8.16 124926.340116 73.917635 70.116156 75.290391 30.200634 50.475185 26.663202 75.841796 7.068918e+07 64513.654073 3
16 Fells Point 4482 264 111 80 113 92 152 88 108 101 251 516 563 453 337 589 664 96 2040 71100 98040071100 64.0 36856.0 18068.0 18788.0 22.313870 293.553288 21.879748 16.670284 1.432603 44.150206 184.723271 21.879748 16.800521 19.665726 311.829824 29.824181 18868.0 80.152672 46.764837 8.00 364828.667851 50.691656 29.629630 41.053101 46.050870 232.574743 13.054187 29.345372 5.048206e+07 110680.679663 4
17 Forest Park/Walb... 3964 508 251 202 214 250 238 233 172 139 416 372 444 204 104 151 66 72 1530 582002 73530582002 51.0 30468.0 13665.0 16803.0 285.171327 6.350926 0.177235 5.080740 0.147696 3.072076 32.501491 20.027570 47.794407 23.040567 163.942497 45.194959 11829.0 212.884044 76.362260 7.41 127498.500000 88.925328 54.566095 55.020182 28.153380 73.335015 57.788018 142.951252 1.116016e+08 110660.699343 3
18 Glen-Fallstaff 6401 862 472 490 352 380 274 327 250 269 511 578 675 304 190 276 191 96 2040 1096014 98041096014 72.0 63656.0 28860.0 34796.0 252.255875 114.012819 6.308910 6.283775 3.141888 17.996732 216.632170 28.452935 73.595576 25.713208 201.407566 70.830715 25656.0 171.109733 100.796751 9.28 163479.304000 135.978753 61.302921 64.364943 36.119356 102.234026 71.055753 109.602567 1.879819e+08 194196.018472 4
19 Greater Charles ... 6404 1136 516 354 285 268 434 255 274 403 424 393 564 341 166 248 343 120 2550 601703 122550601703 95.0 81795.0 42190.0 39605.0 167.216823 222.813130 60.394890 18.644171 4.981967 25.949019 335.374880 19.744483 31.542270 147.869674 260.926707 39.916865 35200.0 209.359606 63.397876 9.90 195486.098039 178.872580 74.718926 85.961899 30.683948 129.762648 94.957082 201.846154 1.352561e+08 132271.346057 5
20 Greater Govans 4012 478 245 204 208 315 240 261 220 172 328 467 330 223 93 171 57 72 1530 632103 73530632103 60.0 32175.0 14052.0 18123.0 270.041958 20.055944 0.279720 3.440559 0.335664 5.846154 61.596328 24.811189 48.671329 22.993007 156.727273 46.797203 12219.0 190.379747 88.609172 7.83 123749.250000 84.870389 61.016949 53.838485 34.920239 65.353938 58.596795 141.722114 6.809549e+07 68946.377145 3
21 Greater Mondawmin 3178 355 338 221 235 190 204 102 187 207 207 379 230 178 87 52 6 96 2040 602303 98040602303 84.0 36356.0 15632.0 20724.0 376.014963 5.985257 1.628342 10.562218 1.716360 4.092860 51.333053 15.271207 57.123996 68.654417 194.960942 63.989438 13864.0 297.549020 102.706104 9.96 149017.803922 144.619257 62.429201 75.645060 47.702958 69.603524 75.073314 149.876543 1.346538e+08 124546.927561 4
22 Greater Roland P... 3181 102 86 57 58 144 66 57 14 101 149 268 326 301 168 323 961 72 1530 814203 73530814203 66.0 22875.0 10896.0 11979.0 17.980328 233.311475 26.990164 9.049180 2.872131 9.796721 112.395325 16.603279 42.649180 30.295082 149.311475 61.140984 10194.0 27.725118 79.597611 5.97 340488.413621 28.575920 25.180761 24.897831 25.275071 196.070418 6.440678 11.377246 1.700644e+08 119588.249386 3
23 Greater Rosemont 5863 728 510 464 373 372 480 406 310 214 451 512 549 217 118 84 75 120 2550 782700 122550782700 115.0 86740.0 40465.0 46275.0 484.061563 7.810699 0.778188 2.968642 1.152871 3.228038 35.918758 35.249020 81.882638 53.752594 271.183998 57.931750 34465.0 323.467784 162.800614 13.95 175277.038177 176.957189 107.282961 83.148559 43.663653 88.947638 118.169399 216.233117 2.110219e+08 162795.381106 5
24 Greenmount East 2908 568 375 228 192 291 135 149 118 110 211 198 179 91 52 11 0 96 2040 352300 98040352300 220.0 31412.0 13548.0 17864.0 375.907297 13.141475 1.018719 1.222463 0.814975 7.895072 45.755196 29.237234 83.076531 31.325608 204.660639 51.699987 12460.0 323.178808 124.621733 10.68 106253.044674 187.482806 79.092160 60.385144 27.235213 45.804677 96.802508 145.790934 7.628915e+07 83189.893831 4
25 Hamilton 5158 433 253 185 118 274 269 152 155 224 333 535 895 596 407 171 158 72 1530 811305 73530811305 72.0 41598.0 19587.0 22011.0 185.028126 91.994807 4.651666 12.115967 1.298139 4.911294 157.276407 20.553873 56.901774 20.315881 174.967547 27.260926 15417.0 124.166211 106.378441 7.50 195391.497196 57.522295 40.422644 41.411400 31.116712 129.526948 26.992966 39.233371 1.355733e+08 83136.333275 3
26 Harbor East/Litt... 2230 294 188 230 38 70 91 31 156 51 58 156 221 216 151 109 170 48 1020 60300 49020060300 104.0 11364.0 5642.0 5722.0 104.188666 53.079901 10.665259 1.865540 0.809574 29.391059 135.468347 9.926082 29.813446 19.605773 123.970433 16.684266 4610.0 134.545455 59.192825 4.34 93332.666667 67.264574 17.219731 23.766816 13.991031 77.757848 53.716551 66.729147 2.043172e+07 37104.815163 2
27 Harford/Echodale 6726 371 320 313 298 404 267 200 379 348 797 772 938 545 244 307 223 120 2550 1353207 122551353207 125.0 80690.0 38210.0 42480.0 285.909035 186.237452 3.005329 8.582228 0.000000 16.265956 273.218312 41.764779 57.070269 34.638741 305.273268 61.252943 34570.0 207.584270 132.322331 12.10 279043.519448 96.788582 64.748736 113.291704 57.389236 167.781742 50.785482 91.153239 3.268002e+08 200095.927001 5
28 Highlandtown 3427 139 152 169 122 141 94 110 103 106 152 300 410 331 353 491 254 72 1530 782800 73530782800 78.0 22881.0 12081.0 10800.0 31.663826 205.598532 5.467418 6.686771 0.000000 50.583454 153.106986 27.691097 17.896945 21.279664 204.772519 28.359774 9588.0 38.006757 51.823753 6.87 247956.398780 50.948351 30.201342 31.601984 26.262037 160.986285 19.957537 43.832021 3.505257e+07 44928.371554 3
29 Howard Park/West... 4095 569 200 233 141 127 86 240 153 186 339 479 686 298 161 138 59 48 1020 560302 49020560302 54.0 22630.0 10826.0 11804.0 188.121962 6.168802 0.371189 3.464428 0.318162 1.555457 23.161252 8.342908 22.996023 16.721167 102.412726 49.527176 8408.0 80.286738 40.879121 5.08 106636.504425 55.824176 22.124542 33.113553 23.394383 65.543346 30.943739 43.289549 1.265249e+08 72068.996894 2
30 Inner Harbor/Fed... 6618 276 322 271 114 207 92 166 156 190 445 493 607 750 642 624 1263 120 2550 1160900 122551160900 140.0 67945.0 33315.0 34630.0 69.431158 359.592317 26.124071 13.577158 5.004047 26.271249 227.249386 21.340790 28.405328 50.813158 344.506586 54.934138 33620.0 114.158163 59.232396 9.80 493817.322900 74.267150 35.131460 59.761257 37.246902 293.593231 11.678543 41.064639 1.249792e+08 217075.297739 5
31 Lauraville 4465 293 81 131 135 168 157 178 195 199 389 628 671 450 254 376 160 120 2550 1351006 122551351006 145.0 61095.0 29785.0 31310.0 269.702922 183.116458 3.109911 13.544480 11.130207 19.396023 291.680070 28.807595 65.758245 44.316229 283.779360 77.338571 23430.0 160.000000 125.979843 12.90 336601.859076 71.668533 56.326988 87.681971 70.324748 213.997760 37.443400 82.808281 2.483287e+08 172098.382640 5
32 Loch Raven 6649 473 238 167 333 391 405 308 457 332 1060 807 784 303 380 90 121 72 1530 812406 73530812406 90.0 51198.0 23637.0 27561.0 261.062932 24.979491 2.759873 2.162194 2.953240 6.082269 77.228000 11.566858 53.615376 30.604711 159.756240 44.456815 19767.0 177.547853 87.216123 7.02 156239.941981 54.639795 49.812002 83.426079 36.411490 75.710633 16.155089 19.420923 1.324434e+08 87943.004015 3
33 Madison/East End 2111 416 198 214 120 108 110 56 203 76 129 152 147 74 22 71 15 72 1530 210600 73530210600 93.0 19773.0 9153.0 10620.0 263.677742 4.096495 0.409650 0.910332 4.096495 26.809285 86.371590 27.309968 60.081930 37.642239 150.432408 24.533455 6906.0 242.537313 114.258645 9.93 89927.569444 134.722880 38.938892 57.981999 21.601137 46.755092 101.226994 168.376963 2.669354e+07 39360.476158 3
34 Medfield/Hampden... 7626 350 337 279 319 473 274 340 211 355 600 809 880 936 514 611 338 144 3060 774413 147060774413 192.0 98076.0 47616.0 50460.0 64.456136 462.718708 32.264774 16.701334 1.872018 21.987030 234.233620 33.365961 42.615931 40.707207 398.446103 84.864799 49734.0 122.409639 97.954367 12.48 390591.285538 101.101495 85.523210 91.738788 63.650669 257.985838 35.882908 50.712531 3.746489e+08 258915.754195 6
35 Midtown 8834 1068 612 511 462 596 410 336 254 349 679 734 1140 521 243 384 535 96 2040 480900 98040480900 216.0 61412.0 29444.0 31968.0 123.597994 210.903407 25.141666 13.287305 2.735622 24.334006 255.064506 9.040578 14.329447 63.205888 254.308604 59.115482 36312.0 131.677019 21.870048 6.60 189625.581662 120.126783 60.765225 58.048449 33.235228 127.824315 21.677957 64.766249 9.529580e+07 100080.387879 4
36 Midway/Coldstream 2957 392 263 267 213 154 179 192 154 141 312 180 140 183 158 29 0 72 1530 272100 73530272100 99.0 27441.0 13170.0 14271.0 275.401771 13.119055 1.902263 4.460479 0.885536 4.230895 51.516545 18.891440 43.883240 25.975730 160.380453 50.869137 9636.0 209.142857 88.772404 8.94 105820.148438 115.150490 53.263443 61.582685 18.261752 51.741630 67.811634 148.008497 5.365341e+07 68303.482249 3
37 Morrell Park/Vio... 3266 409 350 207 111 182 66 273 184 122 271 307 293 203 176 63 49 72 1530 750612 73530750612 102.0 22986.0 10875.0 12111.0 66.170713 185.395458 11.119812 7.439311 1.644479 28.230227 182.542287 14.761159 35.512921 17.932655 176.664056 55.129209 11355.0 108.966565 60.440906 7.02 122852.690217 98.928353 47.856705 53.000612 28.199633 72.014697 38.425617 46.062053 2.024125e+08 133238.235391 3
38 Mount Washington... 2333 168 72 60 65 50 104 64 94 63 95 262 348 201 172 225 290 48 1020 402306 49020402306 70.0 9966.0 4430.0 5536.0 50.852900 129.319687 9.592615 1.766004 0.000000 8.468794 104.669160 21.071644 25.446518 6.060606 110.375276 37.045956 4932.0 33.739130 49.292756 3.86 159985.232759 31.290184 18.688384 21.603086 22.460351 105.957994 3.992740 7.592752 1.138861e+08 77079.532297 2
39 North Baltimore/... 6010 386 294 153 104 275 240 125 60 132 303 492 702 454 315 563 1412 96 2040 933503 98040933503 144.0 70980.0 32636.0 38344.0 64.491406 256.477881 39.267399 21.437025 2.907861 15.418428 223.112258 18.889828 43.189631 97.424627 180.896027 59.599887 25916.0 49.462366 99.034942 9.12 362818.000000 62.362729 42.595674 32.945092 32.745424 229.351082 13.931597 17.989031 2.996960e+08 171616.888577 4
40 Northwood 5488 228 257 344 362 194 315 263 406 128 456 728 640 537 220 249 161 96 2040 902906 98040902906 148.0 70168.0 32728.0 37440.0 337.977426 30.236005 3.146734 10.124273 2.166230 16.349333 125.712888 15.574051 43.735036 110.728537 169.444761 60.517615 22128.0 172.307692 104.227405 10.00 221664.500000 86.807580 56.268222 72.157434 53.061224 131.705539 26.436072 39.004149 2.109731e+08 155559.578364 4
41 Oldtown/Middle East 4042 1220 479 390 182 183 125 81 96 159 374 190 242 205 75 23 18 120 2550 592300 122550592300 255.0 47370.0 21340.0 26030.0 436.088242 43.592991 8.971923 2.374921 0.949968 8.021955 126.424289 18.471607 103.493772 58.528605 258.444163 61.061853 18960.0 433.547204 134.957942 11.25 95636.897436 280.925285 48.119743 77.808016 23.503216 69.643741 200.631458 275.975449 1.229298e+08 119331.640894 5
42 Orangeville/East... 3404 348 183 129 184 96 215 233 147 99 355 276 483 252 173 162 69 72 1530 781605 73530781605 114.0 32259.0 16653.0 15606.0 37.663908 128.503673 11.187576 10.127406 6.835302 105.682135 240.585487 34.092811 43.466939 19.417837 172.165907 30.856505 10071.0 107.179054 104.347826 8.49 155745.904225 74.383079 47.943596 52.967098 24.324324 100.381904 39.710145 67.459080 2.696831e+08 143477.588780 3
43 Patterson Park N... 5285 391 245 214 142 227 156 212 197 140 399 491 598 703 498 319 353 120 2550 451800 122550451800 195.0 70880.0 34245.0 36635.0 160.905756 243.898138 13.050226 10.828160 1.234481 70.083239 330.423559 42.501411 71.352991 37.246050 313.170147 35.729402 26445.0 137.366310 141.532640 13.80 348800.208758 93.850520 56.291391 69.631031 46.452223 233.774834 108.438335 204.517134 7.253822e+07 108931.873301 5
44 Penn North/Reser... 4309 827 455 194 276 228 179 188 207 251 343 209 334 184 179 138 117 96 2040 521000 98040521000 160.0 42276.0 20088.0 22188.0 335.963667 43.864131 2.497871 3.519728 2.649257 11.505346 126.524801 27.400889 67.896679 32.926483 227.760431 44.015517 16992.0 248.736097 91.807844 9.32 139493.307263 162.636343 55.233233 74.355999 19.401253 88.373172 103.858186 186.560000 1.642392e+08 116315.353994 4
45 Pimlico/Arlingto... 4016 710 308 335 339 292 206 163 121 206 288 258 292 213 102 147 36 72 1530 815303 73530815303 123.0 31707.0 14283.0 17424.0 285.637241 7.862617 0.624468 3.462958 0.709622 1.703094 30.900796 17.570253 29.094522 29.066137 157.933579 66.335510 13392.0 186.388584 68.052789 7.98 91747.223301 126.394422 49.377490 45.941235 19.272908 59.013944 57.357076 116.880734 9.120289e+07 74177.802208 3
46 Poppleton/The Te... 2091 656 191 185 165 171 79 59 33 30 97 143 114 88 25 10 45 72 1530 540600 73530540600 126.0 14502.0 6843.0 7659.0 244.766239 42.263136 3.351262 5.213074 0.310302 4.095987 97.539502 23.893256 64.046338 27.120397 159.743484 25.196525 6543.0 258.989599 96.556671 6.69 61227.027273 171.736011 44.332855 22.955524 20.516499 40.459110 134.917127 172.335921 2.790604e+07 37002.082604 3
47 Sandtown-Winches... 4660 992 576 374 374 335 249 128 266 115 254 411 241 152 59 110 24 144 3060 941300 147060941300 258.0 79224.0 36156.0 43068.0 576.461678 9.633444 1.454105 2.681006 7.770373 1.999394 47.584987 41.441987 111.602545 54.665253 308.406543 83.883672 33246.0 449.797023 190.300429 15.84 151253.480597 298.197425 91.673820 81.759657 52.918455 75.450644 210.270482 340.224992 1.420326e+08 125922.859840 6
48 South Baltimore 3266 103 60 30 54 34 21 118 58 90 207 219 478 433 294 539 528 72 1530 710800 73530710800 132.0 21822.0 11043.0 10779.0 6.887545 270.098983 8.331042 2.433324 0.329942 11.919164 63.335740 19.466593 15.218587 16.332142 229.144900 19.837778 9321.0 36.699029 47.305573 6.21 327885.720554 22.688304 15.890998 32.608696 20.116350 208.695652 2.479339 0.356718 1.390618e+08 205320.077480 3
49 Southeastern 2230 211 257 209 167 135 180 87 135 68 159 179 224 129 20 46 24 48 1020 521209 49020521209 90.0 12082.0 5680.0 6402.0 59.162390 82.502897 4.005959 2.052640 1.092534 51.183579 158.340034 21.652044 44.727694 10.395630 97.997020 25.227611 4904.0 83.208020 71.569507 5.28 67554.044444 75.695067 36.053812 32.466368 16.053812 39.730942 60.563380 105.793451 2.225030e+08 204582.961095 2
50 Southern Park He... 4810 1119 431 512 347 315 277 202 186 107 283 338 361 98 93 108 33 72 1530 574100 73530574100 138.0 41376.0 18690.0 22686.0 279.966647 8.896462 1.239849 4.132831 0.108759 5.655452 45.988466 20.055104 43.655742 23.839907 166.792343 45.656903 14217.0 200.413223 90.561331 8.16 74824.123919 150.249480 49.521830 35.925156 21.081081 43.222453 94.877268 145.470323 8.362868e+07 72156.664117 3
51 Southwest Baltimore 5803 1282 732 451 408 333 379 298 223 192 282 556 387 90 43 74 73 192 4080 1572100 196081572100 376.0 134744.0 65040.0 69704.0 588.588731 102.262067 22.988779 23.701241 8.597043 53.862139 398.011190 82.598112 146.007243 61.841715 422.442558 87.110372 50304.0 485.448916 267.172152 22.48 203422.738739 396.070998 139.238325 96.088230 76.650009 91.952438 286.265961 393.802345 3.021286e+08 226844.508651 8
52 The Waverlies 3274 444 215 261 195 144 237 172 162 110 219 253 380 303 76 61 42 72 1530 271200 73530271200 144.0 24813.0 10938.0 13875.0 215.487849 52.339499 4.497642 7.689518 8.813928 11.171563 141.847801 16.068190 46.100834 24.519405 168.552775 44.758796 9837.0 150.348837 78.802688 7.23 117294.052326 102.168601 50.671961 44.990837 23.182651 78.985950 61.543062 132.672112 6.115125e+07 56201.480639 3
53 Unassigned--Jail 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 510 100300 24510100300 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000e+00 0.000000 1
54 Upton/Druid Heights 4189 1151 445 468 326 197 279 221 117 155 205 201 152 69 120 59 24 96 2040 621000 98040621000 212.0 40840.0 18824.0 22016.0 366.542605 16.885406 7.443683 4.779628 1.802155 2.546523 65.851537 31.224290 90.734574 45.719882 189.108717 43.212537 17756.0 331.856379 124.994032 9.40 81870.791411 228.216758 66.555264 45.547863 19.193125 40.486990 171.929825 259.452496 6.790649e+07 77557.231285 4
55 Washington Villa... 2218 432 176 87 137 109 121 61 79 20 227 150 173 144 121 114 67 48 1020 420300 49020420300 98.0 10806.0 5326.0 5480.0 115.306311 67.481029 5.071257 6.848047 0.000000 5.293356 111.904225 14.843605 19.914862 18.138071 129.594670 17.508791 4546.0 141.920375 38.503156 4.72 77703.377049 75.022543 26.239856 29.395852 13.525699 55.816050 45.148515 68.484188 7.868652e+07 73924.520190 2
56 Westport/Mount W... 2352 343 97 245 157 110 198 79 94 96 174 250 359 74 34 35 7 48 1020 500506 49020500506 100.0 13490.0 6640.0 6850.0 132.424018 43.409933 7.412898 1.808747 0.000000 14.944403 111.143433 17.494440 46.375093 14.885100 108.465530 12.779837 4998.0 136.842105 84.013605 5.66 73290.481013 71.598639 32.908163 30.952381 21.258503 43.282313 43.645700 80.372960 9.098819e+07 85146.248832 2
{% endraw %} {% raw %}
# mergedGeom = readInGeometryData(url=merged, porg='g', geom='geometry', lat=False, lng=False, revgeocode=False, save=False, in_crs=2248, out_crs=2248)
{% endraw %}

Geographic data may be crosswalked as well. More information in the 'Maps' section.

Creating BNIA Indictors

Awesome!

By this point you should be able to download a dataset, and crosswalk new columns onto it by matching on 'tract'

What we are going to do now is perform calculations using these newly created datasets.

Run the next few cells to create our calculatory functions

{% raw %}
# These functions right here are used in the calculations below.
# Finds a column matchings a substring
def getColName  (df, col): return df.columns[df.columns.str.contains(pat = col)][0] 
def getColByName (df, col): return df[getColName(df, col)]

# Pulls a column from one dataset into a new dataset. 
# This is not a crosswalk. calls getColByName() 
def addKey(df, fi, col):
    key = getColName(df, col)
    val = getColByName(df, col)
    fi[key] = val
    return fi
# Return 0 if two specified columns are equal.
def nullIfEqual(df, c1, c2): 
    return df.apply(lambda x: 
        x[getColName(df, c1)]+x[getColName(df, c2)] if x[getColName(df, c1)]+x[getColName(df, c2)] != 0 else 0, axis=1)
# I'm thinking this doesnt need to be a function..
def sumInts(df): return df.sum(numeric_only=True)
{% endraw %} {% raw %}
#File: mhhi.py
#Author: Charles Karpati
#Date: 1/24/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B19001 - HOUSEHOLD INCOME IN THE PAST 12 MONTHS (IN 2016 INFLATION-ADJUSTED DOLLARS)
# Universe: Households
# Table Creates: hh25 hh40 hh60 hh75 hhm75, mhhi
#purpose: Produce Sustainability - Percent of Population that Walks to Work Indicator
#input:
#output:
import pandas as pd
import glob

def mhhi( df, columnsToInclude = [] ):
  #~~~~~~~~~~~~~~~
  # Step 2)
  # Prepare the columns
  #~~~~~~~~~~~~~~~ 
  info = pd.DataFrame(
      [
          ['B19001_002E', 0, 10000],
          ['B19001_003E', 10000, 4999 ],
          ['B19001_004E', 15000, 4999 ],
          ['B19001_005E', 20000, 4999 ],
          ['B19001_006E', 25000, 4999 ],
          ['B19001_007E', 30000, 4999],
          ['B19001_008E', 35000, 4999 ],
          ['B19001_009E', 40000, 4999 ],
          ['B19001_010E', 45000, 4999 ],
          ['B19001_011E', 50000, 9999 ],
          ['B19001_012E', 60000, 14999],
          ['B19001_013E', 75000, 24999 ],
          ['B19001_014E', 100000, 24999 ],
          ['B19001_015E', 125000, 24999 ],
          ['B19001_016E', 150000, 49000 ],
          ['B19001_017E', 200000, 1000000000000000000000000 ],

      ], 
      columns=['variable', 'lower', 'range']
  )

  # Final Dataframe  
  data_table = pd.DataFrame()
  for index, row in info.iterrows():
      data_table = addKey(df, data_table, row['variable'])

  # Accumulate totals accross the columns.
  # Midpoint: Divide column index 16 (the last column) of the cumulative totals
  temp_table = data_table.cumsum(axis=1)
  temp_table['midpoint'] = (temp_table.iloc[ : , -1 :] /2) # V3
  temp_table['midpoint_index'] = False
  temp_table['midpoint_index_value'] = False # Z3
  temp_table['midpoint_index_lower'] = False # W3 
  temp_table['midpoint_index_range'] = False # X3
  temp_table['midpoint_index_minus_one_cumulative_sum'] = False #Y3
  # step 3 - csa_agg3: get the midpoint index by "when midpoint > agg[1] and midpoint <= agg[2] then 2"

  # Get CSA Midpoint Index using the breakpoints in our info table.
  for index, row in temp_table.iterrows():
      # Get the index of the first column where our midpoint is greater than the columns value.
      midpoint = row['midpoint']
      midpoint_index = 0
      # For each column (except the 6 columns we just created)

      # The tracts midpoint was < than the first tracts value at column 'B19001_002E_Total_Less_than_$10,000'
      if( midpoint < int(row[0]) or row[-6] == False ):
        temp_table.loc[ index, 'midpoint_index' ] = 0
      else:
        for column in row.iloc[:-6]:
            # set midpoint index to the column with the highest value possible that is under midpoint          
            if( midpoint >= int(column) ):
                if midpoint==False: print (str(column) + ' - ' + str(midpoint))
                temp_table.loc[ index, 'midpoint_index' ] = midpoint_index +1
            midpoint_index += 1

  # temp_table = temp_table.drop('Unassigned--Jail')
  for index, row in temp_table.iterrows(): 
    temp_table.loc[ index, 'midpoint_index_value' ] = data_table.loc[ index, data_table.columns[row['midpoint_index']] ]
    temp_table.loc[ index, 'midpoint_index_lower' ] = info.loc[ row['midpoint_index'] ]['lower']     
    temp_table.loc[ index, 'midpoint_index_range' ] = info.loc[ row['midpoint_index'] ]['range']
    temp_table.loc[ index, 'midpoint_index_minus_one_cumulative_sum'] = row[ row['midpoint_index']-1 ]

  # This is our denominator, which cant be negative.
  for index, row in temp_table.iterrows():
    if row['midpoint_index_value']==False: 
      temp_table.at[index, 'midpoint_index_value']=1;
      
  #~~~~~~~~~~~~~~~
  # Step 3)
  # Run the Calculation 
  # Calculation = (midpoint_lower::numeric + (midpoint_range::numeric * ( (midpoint - midpoint_upto_agg) / nullif(midpoint_total,0)
  # Calculation = W3+X3*((V3-Y3)/Z3)

  # v3 -> 1 - midpoint of households  == sum / 2
  # w3 -> 2 - lower limit of the income range containing the midpoint of the housing total == row[lower]
  # x3 -> width of the interval containing the medium == row[range]
  # z3 -> number of hhs within the interval containing the median == row[total] 
  # y3 -> 4 - cumulative frequency up to, but no==NOT including the median interval
  #~~~~~~~~~~~~~~~

  def finalCalc(x):
    return ( x['midpoint_index_lower']+ x['midpoint_index_range']*(
      ( x['midpoint']-x['midpoint_index_minus_one_cumulative_sum'])/ x['midpoint_index_value'] ) 
    )

  temp_table['final'] = temp_table.apply(lambda x: finalCalc(x), axis=1)
  
  
  columnsToInclude.append('tract')
  print ('INCLUDING COLUMN(s):' + str(columnsToInclude))
  temp_table[columnsToInclude] = df[columnsToInclude]
  #~~~~~~~~~~~~~~~
  # Step 4)
  # Add Special Baltimore City Data
  #~~~~~~~~~~~~~~~  
  # url = 'https://api.census.gov/data/20'+str(year)+'/acs/acs5/subject?get=NAME,S1901_C01_012E&for=county%3A510&in=state%3A24&key=829bf6f2e037372acbba32ba5731647c5127fdb0'
  # table = pd.read_json(url, orient='records')
  # temp_table['final']['Baltimore City'] = float(table.loc[1, table.columns[1]])
    
  return temp_table
{% endraw %} {% raw %}
#File: trav45.py
#Author: Charles Karpati
#Date: 1/17/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B08303 - TRAVEL TIME TO WORK,
# (Universe: Workers 16 years and over who did not work at home) 
# Table Creates: trav14, trav29, trav44, trav45
#purpose: Produce Sustainability - Percent of Employed Population with Travel Time to Work of 45 Minutes and Over Indicator
#input: 
#output: 

import pandas as pd
import glob
def trav45(df, columnsToInclude = [] ):
    #~~~~~~~~~~~~~~~
    # Step 2)
    # Prepare the columns
    #~~~~~~~~~~~~~~~ 

    # Final Dataframe  
    fi = pd.DataFrame()
    columns = ['B08303_011E','B08303_012E','B08303_013E','B08303_001E', 'tract'] 
    columns.extend(columnsToInclude)
    for col in columns:
        fi = addKey(df, fi, col)

    # Numerators 
    numerators = pd.DataFrame()
    columns = ['B08303_011E','B08303_012E','B08303_013E']
    for col in columns:
        numerators = addKey(df, numerators, col)
    
    # Denominators
    denominators = pd.DataFrame()
    columns = ['B08303_001E']
    for col in columns:
        denominators = addKey(df, denominators, col)
    # construct the denominator, returns 0 iff the other two rows are equal.

    #~~~~~~~~~~~~~~~
    # Step 3)
    # Run the Calculation 
# ( (value[1] + value[2] + value[3] ) / nullif(value[4],0) )*100
    #~~~~~~~~~~~~~~~
    fi['numerator'] = numerators.sum(axis=1)
    fi['denominator'] = denominators.sum(axis=1)
    fi = fi[fi['denominator'] != 0] # Delete Rows where the 'denominator' column is 0
    fi['final'] = (fi['numerator'] / fi['denominator'] ) * 100
    
    return fi
{% endraw %} {% raw %}
#File: trav44.py
#Author: Charles Karpati
#Date: 1/17/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B08303 - TRAVEL TIME TO WORK,
# (Universe: Workers 16 years and over who did not work at home)
# Table Creates: trav14, trav29, trav44, trav45
#purpose: Produce Sustainability - Percent of Employed Population with Travel Time to Work of 30-44 Minutes Indicator
#input: 
#output: 

import pandas as pd
import glob
def trav44( df, columnsToInclude = [] ):
    #~~~~~~~~~~~~~~~
    # Step 2)
    # Prepare the columns
    #~~~~~~~~~~~~~~~ 

    # Final Dataframe  
    fi = pd.DataFrame()
    columns = ['B08303_008E','B08303_009E','B08303_010E','B08303_001E', 'tract'] 
    columns.extend(columnsToInclude) 
    for col in columns:
        fi = addKey(df, fi, col)

    # Numerators 
    numerators = pd.DataFrame()
    columns = ['B08303_008E','B08303_009E','B08303_010E']
    for col in columns:
        numerators = addKey(df, numerators, col)
    
    # Denominators
    denominators = pd.DataFrame()
    columns = ['B08303_001E']
    for col in columns:
        denominators = addKey(df, denominators, col)
    # construct the denominator, returns 0 iff the other two rows are equal.

    #~~~~~~~~~~~~~~~
    # Step 3)
    # Run the Calculation 
    # ( (value[1] + value[2] + value[3] ) / nullif(value[4],0) )*100
    #~~~~~~~~~~~~~~~
    fi['numerator'] = numerators.sum(axis=1)
    fi['denominator'] = denominators.sum(axis=1)
    fi = fi[fi['denominator'] != 0] # Delete Rows where the 'denominator' column is 0
    fi['final'] = (fi['numerator'] / fi['denominator'] ) * 100
    
    return fi
{% endraw %} {% raw %}
#File: affordr.py
#Author: Charles Karpati
#Date: 1/17/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B25070 - GROSS RENT AS A PERCENTAGE OF HOUSEHOLD INCOME IN THE PAST 12 MONTHS 
# Universe: Renter-occupied housing units
#purpose: Produce Housing and Community Development - Affordability Index - Rent Indicator
#input: 
#output: 

import pandas as pd
import glob
def affordr( df, columnsToInclude ):    
    #~~~~~~~~~~~~~~~
    # Step 2)
    # Prepare the columns
    #~~~~~~~~~~~~~~~ 

    # Final Dataframe  
    fi = pd.DataFrame()
    columns = ['B25070_007E','B25070_008E','B25070_009E','B25070_010E','B25070_001E', 'tract'] 
    columns.extend(columnsToInclude) 
    for col in columns:
        fi = addKey(df, fi, col)

    # Numerators 
    numerators = pd.DataFrame()
    columns = ['B25070_007E','B25070_008E','B25070_009E','B25070_010E']
    for col in columns:
        numerators = addKey(df, numerators, col)
    
    # Denominators
    denominators = pd.DataFrame()
    columns = ['B25070_001E']
    for col in columns:
        denominators = addKey(df, denominators, col)
    # construct the denominator, returns 0 iff the other two rows are equal.

    #~~~~~~~~~~~~~~~
    # Step 3)
    # Run the Calculation 
    # ( (value[1]+value[2]+value[3]+value[4]) / nullif(value[5],0) )*100
    #~~~~~~~~~~~~~~~
    fi['numerator'] = numerators.sum(axis=1)
    fi['denominator'] = denominators.sum(axis=1)
    fi = fi[fi['denominator'] != 0] # Delete Rows where the 'denominator' column is 0
    fi['final'] = (fi['numerator'] / fi['denominator'] ) * 100
    
    return fi
{% endraw %} {% raw %}
#File: affordm.py
#Author: Charles Karpati
#Date: 1/25/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B25091 - MORTGAGE STATUS BY SELECTED MONTHLY OWNER COSTS AS A PERCENTAGE OF HOUSEHOLD INCOME IN THE PAST 12 MONTHS
# Universe: Owner-occupied housing units
# Table Creates: 
#purpose: Produce Housing and Community Development - Affordability Index - Mortgage Indicator
#input: 
#output: 

import pandas as pd
import glob
def affordm( df, columnsToInclude ):  
    #~~~~~~~~~~~~~~~
    # Step 1)
    # Prepare the columns
    #~~~~~~~~~~~~~~~ 

    # Final Dataframe  
    fi = pd.DataFrame()
    columns = ['B25091_008E','B25091_009E','B25091_010E','B25091_011E','B25091_002E', 'tract'] 
    columns.extend(columnsToInclude) 
    for col in columns:
        fi = addKey(df, fi, col)

    # Numerators 
    numerators = pd.DataFrame()
    columns = ['B25091_008E','B25091_009E','B25091_010E','B25091_011E']
    for col in columns:
        numerators = addKey(df, numerators, col)
    
    # Denominators
    denominators = pd.DataFrame()
    columns = ['B25091_002E']
    for col in columns:
        denominators = addKey(df, denominators, col)
    # construct the denominator, returns 0 iff the other two rows are equal.

    #~~~~~~~~~~~~~~~
    # Step 3)
    # Run the Calculation 
    # ( (value[1]+value[2]+value[3]+value[4]) / nullif(value[5],0) )*100
    #~~~~~~~~~~~~~~~
    fi['numerator'] = numerators.sum(axis=1)
    fi['denominator'] = denominators.sum(axis=1)
    fi = fi[fi['denominator'] != 0] # Delete Rows where the 'denominator' column is 0
    fi['final'] = (fi['numerator'] / fi['denominator'] ) * 100
    
    return fi
{% endraw %} {% raw %}
#File: age5.py
#Author: Charles Karpati
#Date: 4/16/19
#Section: Bnia
#Email: karpati1@umbc.edu
#Description: 
# Uses ACS Table B01001 - SEX BY AGE
# Universe: Total population
# Table Creates: tpop, female, male, age5 age18 age24 age64 age65
#purpose: 
#input: #output: 

import pandas as pd
import glob
def age5( df, columnsToInclude ):

  #~~~~~~~~~~~~~~~
    # Step 1)
    # Prepare the columns
    #~~~~~~~~~~~~~~~
    # Final Dataframe  
    fi = pd.DataFrame()
    columns = ['B01001_027E_Total_Female_Under_5_years',
               'B01001_003E_Total_Male_Under_5_years', 
               'B01001_001E_Total' , 'tract'] 
    columns.extend(columnsToInclude) 
    for col in columns:
        fi = addKey(df, fi, col)

    # Under 5
    fi['final']  = ( df[ 'B01001_003E_Total_Male_Under_5_years' ] 
               + df[ 'B01001_027E_Total_Female_Under_5_years' ] 
    ) / df['B01001_001E_Total'] * 100

    return fi
{% endraw %}

Now that our calculations have been created, lets create a final function that will download our data, optionally crosswalk and optionally aggregate it to the community level, and then run/return the appropriate calculation.

{% raw %}
def createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                    local_match_col, foreign_match_col, foreign_wanted_col, 
                    saveCrosswalked, saveCrosswalkedFileName, groupBy, 
                    aggMethod, method, columnsToInclude, finalFileName):
  # Pull the data
  df = retrieve_acs_data(state, county, tract, tableId, year, saveAcs)
  print('Table: ' + tableId + ', Year: ' + year + ' imported.')
  
  # Get the crosswalk 
  if cwUrl:
    crosswalk = pd.read_csv( cwUrl )
    print('Crosswalk file imported')
    # Merge crosswalk with the data
    df = mergeDatasets( df, crosswalk, local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, saveCrosswalkedFileName )
    
    print('Table merged')

  # Group and Aggregate 
  if groupBy:
    df = df.groupby(groupBy)
    print('Grouped')
    if aggMethod == 'sum':
      df = sumInts(df)
    else:
      df = sumInts(df)
    print('Aggregated')
    
  print('Creating Indicator')
  # Create the indicator
  resp = method( df, columnsToInclude)
  print('Indicator Created')
  resp.to_csv(finalFileName, quoting=csv.QUOTE_ALL)
  print('File Saved')
  return resp
{% endraw %} {% raw %}
# Change these values in the cell below using different geographic reference codes will change those parameters
tract = '*'
county = '510'
state = '24'

# Specify the download parameters the acs download function will receieve here
year = '17'
saveAcs = True

# Specify the crosswalk parameters
baltimore = '2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE'
cwUrl = 'https://docs.google.com/spreadsheets/d/e/' + baltimore + '/pub?output=csv'
local_match_col = 'tract'
foreign_match_col= 'TRACT2010' 
foreign_wanted_col= 'CSA2010'
saveCrosswalked = True
crosswalkedFileName = False

groupBy = 'CSA2010'
aggMethod = 'sum'
columnsToInclude = []
# Alternatively
# groupBy = False
#columnsToInclude = ['CSA2010']
{% endraw %} {% raw %}
tableId = 'B19001'
finalFileName = './mhhi_12July2019_yes.csv'
# Group By Crosswalked column. Included automatically in final result
# groupBy = 'CSA2010'
# columnsToInclude = []
# Do Not Group, Include the Crosswalked Column in the final result
groupBy = False
columnsToInclude = ['CSA2010']
method = mhhi
ind1 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, 
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
ind1.head()
{% endraw %} {% raw %}
tableId = 'B08303'
finalFileName = './trav45_20'+year+'_tracts_26July2019.csv'
method = trav45
ind2 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, 
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
{% endraw %} {% raw %}
tableId = 'B08303'
finalFileName = './trav44_20'+year+'_tracts_26July2019.csv'
method = trav44
ind3 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked,
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
{% endraw %} {% raw %}
tableId = 'B25070'
finalFileName = './affordr_20'+year+'_tracts_26July2019.csv'
method = affordr
ind4 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, 
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
{% endraw %} {% raw %}
tableId = 'B25091'
finalFileName = './affordm_20'+year+'_tracts_26July2019.csv'
method = affordm
ind5 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, 
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
{% endraw %} {% raw %}
tableId = 'B01001'
finalFileName = './age5_20'+year+'_communities_9Sept2019.csv'
method = age5
groupBy = 'CSA2010'
columnsToInclude = []
ind5 = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                       local_match_col, foreign_match_col, foreign_wanted_col, saveCrosswalked, 
                       crosswalkedFileName, groupBy, aggMethod, method, columnsToInclude, finalFileName)
ind5.head()
Number of Columns 49
Table: B01001, Year: 17 imported.
Crosswalk file imported
df True cw True cs True
SavingCrosswalk
Table merged
Grouped
Aggregated
Creating Indicator
Indicator Created
File Saved
B01001_027E_Total_Female_Under_5_years B01001_003E_Total_Male_Under_5_years B01001_001E_Total tract final
CSA2010
Allendale/Irvington/S. Hilton 525 581 16726 1333309 6.612460
Baltimore City 20119 20660 619796 10000 6.579423
Beechfield/Ten Hills/West Hills 491 571 13391 810905 7.930700
Belair-Edison 436 506 17380 680806 5.420023
Brooklyn/Curtis Bay/Hawkins Point 908 499 12900 1001903 10.906977
{% endraw %}

MAPPING

Census Geographic Data:

{% raw %}
# pd.set_option('display.precision', 2)
# pd.reset_option('max_colwidth')
pd.set_option('max_colwidth', 20)
# pd.reset_option('max_colwidth')
{% endraw %}

Importing Point Data:

{% raw %}
tableId = 'B19001'
finalFileName = './mhhi_12July2019_yes.csv'

baltimore = '2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE'
cwUrl = 'https://docs.google.com/spreadsheets/d/e/' + baltimore + '/pub?output=csv'

method = mhhi
local_match_col = 'tract'
foreign_match_col= 'TRACT2010' 
foreign_wanted_col= 'CSA2010'

aggMethod = 'sum'
groupBy = False
columnsToInclude = ['CSA2010']

df = createIndicator(state, county, tract, year, tableId, saveAcs, cwUrl, 
                     local_match_col, foreign_match_col, foreign_wanted_col, 
                     saveCrosswalked, crosswalkedFileName, groupBy, aggMethod, 
                     method, columnsToInclude, finalFileName)

df.head()
Number of Columns 17
Table: B19001, Year: 17 imported.
Crosswalk file imported
df True cw True cs True
SavingCrosswalk
Table merged
Creating Indicator
INCLUDING COLUMN(s):['CSA2010', 'tract']
Indicator Created
File Saved
B19001_002E_Total_Less_than_$10_000 B19001_003E_Total_$10_000_to_$14_999 B19001_004E_Total_$15_000_to_$19_999 B19001_005E_Total_$20_000_to_$24_999 B19001_006E_Total_$25_000_to_$29_999 B19001_007E_Total_$30_000_to_$34_999 B19001_008E_Total_$35_000_to_$39_999 B19001_009E_Total_$40_000_to_$44_999 B19001_010E_Total_$45_000_to_$49_999 B19001_011E_Total_$50_000_to_$59_999 B19001_012E_Total_$60_000_to_$74_999 B19001_013E_Total_$75_000_to_$99_999 B19001_014E_Total_$100_000_to_$124_999 B19001_015E_Total_$125_000_to_$149_999 B19001_016E_Total_$150_000_to_$199_999 B19001_017E_Total_$200_000_or_more midpoint midpoint_index midpoint_index_value midpoint_index_lower midpoint_index_range midpoint_index_minus_one_cumulative_sum final CSA2010 tract
NAME
Census Tract 1901 237 313 398 436 515 558 594 629 644 687 732 771 776 776 782 796 398.0 3 38 20000 4999 398 20000.000000 Southwest Baltimore 190100
Census Tract 1902 63 150 243 249 307 337 351 380 403 441 554 624 630 662 673 695 347.5 6 14 35000 4999 337 38749.250000 Southwest Baltimore 190200
Census Tract 2201 137 366 490 542 620 707 757 837 850 1067 1133 1292 1497 1664 1810 2208 1104.0 10 66 60000 14999 1067 68408.530303 Inner Harbor/Fed... 220100
Census Tract 2303 3 23 23 62 69 69 98 106 115 159 188 286 397 460 554 632 316.0 12 111 100000 24999 286 106756.486486 South Baltimore 230300
Census Tract 2502.07 102 130 231 295 399 475 516 556 603 675 703 763 782 809 824 836 418.0 5 76 30000 4999 399 31249.750000 Cherry Hill 250207
{% endraw %}

Importing Geom Data

{% raw %}
# string = 'boundariesr-baltimore-tracts-NoWater-2010'
# string = 'boundaries-baltimore-communities-NoWater-2010'
# string = 'boundaries-baltimore-neighborhoods'
# string = 'boundaries-moco-census-tracts-2010'
# string = 'boundaries-maryland_census-tracts-2010'
# string = 'boundaries-maryland-counties'
# string = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vRWBYggh3LGJ3quU-PhGXT2NvAtUb3aiXdZVKAO5VWCreUWZpAGz1uTbLvq6rF1TrJNiE81o6R5AP8F/pub?output=csv' # GoogleSpreadsheet Baltimore Tracts
# string = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vSIJpLSmdQkvqJ3Wk6ONJmj_qHBgG_1naDxd0KcNyrT2LoJhqhoRSMtY1kyjy__xZ4Y8UN-tMNNAUa-/pub?output=csv' # GoogleSpreadsheet Evanston Tracts
# The file extension is used to determine the appropriate import method.
ext = '.csv'
# ext = '.geojson'
# ext = '.json'
# ext = '.kml'
# ext = 'googleSpreadSheet'
# This is where the findFile function comes in handy
url = findFile('../', string+ext)

geomData = ''
if ext == '.geojson' or ext == '.kml' or ext == '.json':
  print(url)
  geomData = gpd.read_file(url)  
if ext == '.csv' or ext == 'googleSpreadSheet':
  if ext == 'googleSpreadSheet':
    url = string
  geomData = pd.read_csv(url)
  geomData['geometry'] = geomData['geometry'].apply(lambda x: loads( str(x) ))
  geomData = GeoDataFrame(geomData, geometry='geometry')

geomData.plot()
geomData.head()
{% endraw %}

Save the Geom Dataset as geojson and csv form if not already

{% raw %}
if ext == '.csv':
  print('saving csv as geojson')
  geomData.to_file(string+".geojson", driver='GeoJSON')
  
if ext == '.geojson':
  print('saving geojson as csv')
  geomData.to_csv(string+'.csv', encoding="utf-8", index=False, quoting=csv.QUOTE_ALL)

if ext == '.json':
  print('saving json as csv and geojson')
  geomData.to_csv(string+'.csv', encoding="utf-8", index=False, quoting=csv.QUOTE_ALL)
  geomData.to_file(string+".geojson", driver='GeoJSON')

if ext == '.kml':
  print('saving kml as csv and geojson')
  geomData.to_csv(string+'.csv', encoding="utf-8", index=False, quoting=csv.QUOTE_ALL)
  geomData.to_file(string+".geojson", driver='GeoJSON')
saving geojson as csv
{% endraw %}

Crosswalking Boundarys:

We can use the Geometry Data as a crosswalk and pass over the geometries to our principal dataset.

The crosswalkIt function must have been previously ran for this option to work.

{% raw %}
local_match_col = 'tract'
foreign_match_col = 'TRACTCE10'

#local_match_col = 'CSA2010'
#foreign_match_col = 'CSA'
foreign_wanted_col = 'geometry'

gdf = crosswalkIt( geomData, df, local_match_col, foreign_match_col, foreign_wanted_col, True, False )

# After crosswalking our boundaries, we need to make sure they are being interpreted like that.
gdf = GeoDataFrame(gdf, geometry=foreign_wanted_col)
Local Column Values Not Matched 
[ 10000  10100  10200  10300  10400  10500  20100  20200  20300  30100
  30200  40100  40200  60100  60200  60300  60400  70100  70200  70300
  70400  80101  80102  80200  80301  80302  80400  80500  80600  80700
  80800  90100  90200  90300  90400  90500  90600  90700  90800  90900
 100100 100200 100300 110100 110200 120100 120201 120202 120300 120400
 120500 120600 120700 130100 130200 130300 130400 130600 130700 130803
 130804 130805 130806 140100 140200 140300 150100 150200 150300 150400
 150500 150600 150701 150702 150800 150900 151000 151100 151200 151300
 160100 160200 160300 160400 160500 160600 160700 160801 160802 170100
 170200 170300 180100 180200 180300 190100 190200 190300 200100 200200
 200300 200400 200500 200600 200701 200702 200800 210100 210200 220100
 230100 230200 230300 240100 240200 240300 240400 250101 250102 250103
 250203 250204 250205 250206 250207 250301 250303 250401 250402 250500
 250600 260101 260102 260201 260202 260203 260301 260302 260303 260401
 260402 260403 260404 260501 260604 260605 260700 260800 260900 261000
 261100 270101 270102 270200 270301 270302 270401 270402 270501 270502
 270600 270701 270702 270703 270801 270802 270803 270804 270805 270901
 270902 270903 271001 271002 271101 271102 271200 271300 271400 271501
 271503 271600 271700 271801 271802 271900 272003 272004 272005 272006
 272007 280101 280102 280200 280301 280302 280401 280402 280403 280404
 280500]
201

Crosswalk Unique Column Values
[809600 809700 809800 809900 810000 810100 810200 810301 810302 808702
 808800 808900 809000 809100 809200 809300 809400 809500]
SavingCrosswalk
{% endraw %} {% raw %}
gdf.crs
type(gdf)
gdf.columns
gdf.head()
gdf.plot()
# Ensure your aggregation is correctly set for the crosswalk to work.
geopandas.geodataframe.GeoDataFrame
Index(['B19001_002E_Total_Less_than_$10_000',
       'B19001_003E_Total_$10_000_to_$14_999',
       'B19001_004E_Total_$15_000_to_$19_999',
       'B19001_005E_Total_$20_000_to_$24_999',
       'B19001_006E_Total_$25_000_to_$29_999',
       'B19001_007E_Total_$30_000_to_$34_999',
       'B19001_008E_Total_$35_000_to_$39_999',
       'B19001_009E_Total_$40_000_to_$44_999',
       'B19001_010E_Total_$45_000_to_$49_999',
       'B19001_011E_Total_$50_000_to_$59_999',
       'B19001_012E_Total_$60_000_to_$74_999',
       'B19001_013E_Total_$75_000_to_$99_999',
       'B19001_014E_Total_$100_000_to_$124_999',
       'B19001_015E_Total_$125_000_to_$149_999',
       'B19001_016E_Total_$150_000_to_$199_999',
       'B19001_017E_Total_$200_000_or_more', 'midpoint', 'midpoint_index',
       'midpoint_index_value', 'midpoint_index_lower', 'midpoint_index_range',
       'midpoint_index_minus_one_cumulative_sum', 'final', 'CSA2010', 'tract',
       'geometry'],
      dtype='object')
B19001_002E_Total_Less_than_$10_000 B19001_003E_Total_$10_000_to_$14_999 B19001_004E_Total_$15_000_to_$19_999 B19001_005E_Total_$20_000_to_$24_999 B19001_006E_Total_$25_000_to_$29_999 B19001_007E_Total_$30_000_to_$34_999 B19001_008E_Total_$35_000_to_$39_999 B19001_009E_Total_$40_000_to_$44_999 B19001_010E_Total_$45_000_to_$49_999 B19001_011E_Total_$50_000_to_$59_999 B19001_012E_Total_$60_000_to_$74_999 B19001_013E_Total_$75_000_to_$99_999 B19001_014E_Total_$100_000_to_$124_999 B19001_015E_Total_$125_000_to_$149_999 B19001_016E_Total_$150_000_to_$199_999 B19001_017E_Total_$200_000_or_more midpoint midpoint_index midpoint_index_value midpoint_index_lower midpoint_index_range midpoint_index_minus_one_cumulative_sum final CSA2010 tract geometry
/usr/local/lib/python3.6/dist-packages/geopandas/plotting.py:418: UserWarning: The GeoDataFrame you are attempting to plot is empty. Nothing has been displayed.
  "empty. Nothing has been displayed.", UserWarning)
<matplotlib.axes._subplots.AxesSubplot at 0x7fe5dae52ac8>
{% endraw %}

Lets make a GIF

Reading in the Names Crosswalk with a URL.

We will Read in our Boundaries Crosswalk next.

{% raw %}
evanston = '2PACX-1vSIJpLSmdQkvqJ3Wk6ONJmj_qHBgG_1naDxd0KcNyrT2LoJhqhoRSMtY1kyjy__xZ4Y8UN-tMNNAUa-'
baltComm = '2PACX-1vREwwa_s8Ix39OYGnnS_wA8flOoEkU7reIV4o3ZhlwYhLXhpNEvnOia_uHUDBvnFptkLLHHlaQNvsQE'
url = 'https://docs.google.com/spreadsheets/d/e/' + evanston + '/pub?output=csv' 
namesCw = pd.read_csv( url )
namesCw.columns
namesCw.head()
Index(['OBJECTID', 'STATEFP10', 'COUNTYFP10', 'TRACTCE10', 'GEOID10', 'NAME10',
       'NAMELSAD10', 'MTFCC10', 'FUNCSTAT10', 'ALAND10', 'AWATER10',
       'INTPTLAT10', 'INTPTLON10', 'created_user', 'created_date',
       'last_edited_user', 'last_edited_date', 'GEOID10num', 'Tract10Num',
       'ShapeSTArea', 'ShapeSTLength', 'geometry'],
      dtype='object')
OBJECTID STATEFP10 COUNTYFP10 TRACTCE10 GEOID10 NAME10 NAMELSAD10 MTFCC10 FUNCSTAT10 ALAND10 AWATER10 INTPTLAT10 INTPTLON10 created_user created_date last_edited_user last_edited_date GEOID10num Tract10Num ShapeSTArea ShapeSTLength geometry
0 19 17 31 809600 17031809600 8096.0 Census Tract 8096 G5020 S 1300137 0 42.044745 -87.699904 NaN NaN MVARNER 2019-05-01T21:06:24 17031809600 809600 1.398329e+07 15853.66701 POLYGON ((-87.70...
1 20 17 31 809700 17031809700 8097.0 Census Tract 8097 G5020 S 1323073 0 42.037466 -87.699915 NaN NaN MVARNER 2019-05-01T21:06:24 17031809700 809700 1.422420e+07 16063.03870 POLYGON ((-87.70...
2 21 17 31 809800 17031809800 8098.0 Census Tract 8098 G5020 S 597774 0 42.037529 -87.685499 NaN NaN MVARNER 2019-05-01T21:06:24 17031809800 809800 6.388610e+06 10293.09649 POLYGON ((-87.69...
3 22 17 31 809900 17031809900 8099.0 Census Tract 8099 G5020 S 765553 0 42.037619 -87.675263 NaN NaN MVARNER 2019-05-01T21:06:24 17031809900 809900 8.357456e+06 12018.23198 POLYGON ((-87.67...
4 23 17 31 810000 17031810000 8100.0 Census Tract 8100 G5020 S 1108649 1422820 42.024770 -87.669119 NaN NaN MVARNER 2019-05-01T21:06:24 17031810000 810000 1.231487e+07 14882.37133 POLYGON ((-87.67...
{% endraw %}

Reading in the Boundary Data with a filePath. We specify the geometry on import this time.

{% raw %}
evanston = '2PACX-1vSIJpLSmdQkvqJ3Wk6ONJmj_qHBgG_1naDxd0KcNyrT2LoJhqhoRSMtY1kyjy__xZ4Y8UN-tMNNAUa-'
url = 'https://docs.google.com/spreadsheets/d/e/' + evanston + '/pub?output=csv' 
boundsCw = pd.read_csv(url)
boundsCw['geometry'] = boundsCw['geometry'].apply(lambda x: loads( str(x) ))
boundsCw = GeoDataFrame(boundsCw, geometry='geometry')

# file = findFile('../', 'boundaries-evanston-tracts-2010.geojson')
#boundsCw = gpd.read_file(file, geometry='geometry')
boundsCw.columns
boundsCw.plot()
Index(['OBJECTID', 'STATEFP10', 'COUNTYFP10', 'TRACTCE10', 'GEOID10', 'NAME10',
       'NAMELSAD10', 'MTFCC10', 'FUNCSTAT10', 'ALAND10', 'AWATER10',
       'INTPTLAT10', 'INTPTLON10', 'created_user', 'created_date',
       'last_edited_user', 'last_edited_date', 'GEOID10num', 'Tract10Num',
       'ShapeSTArea', 'ShapeSTLength', 'geometry'],
      dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7fe5dab86320>
{% endraw %}

Settings for the data we will pull

{% raw %}
state = '17'
county = '031' 
tract = '*'
tableId = 'B08303'
years = ['17','16', '15']
saveAcs = True
numer = ['001', '002', '003']
denom = ['001', '002', '003', '004', '005', '006', '007', '008', '009', '010', '011' ]

saveAcs = True
saveCw1 = True
cwlk1FileName = 'Example_NamedCrosswalk.csv'
saveCw2 = True
cwlk2FileName = 'Example_BoundaryCrosswalk.csv'

groupBy = False
#groupBy = 'CSA2010'
aggMethod = 'sum'

namesCw = namesCw
names_local_match_col = 'tract'
names_foreign_match_col = 'Tract10Num'
names_foreign_wanted_col = 'INTPTLAT10'

boundsCw = boundsCw
bounds_local_match_col = 'tract'
bounds_foreign_match_col = 'Tract10Num'
bounds_foreign_wanted_col = 'geometry'
{% endraw %} {% raw %}
def getAcsYears(state, county, tract, years, 
                tableId, numer, denom, 
                namesCw, lcw1Match, fcw1Match, fcw1Want, groupBy, aggMethod,
                boundsCw, lcw2Match, fcw2Match, fcw2Want, 
                saveAcs, saveCw1, cwlk1FileName, saveCw2, cwlk2FileName):
  # Get the data
  count = 0
  final = ''
  for year in years:
    df = retrieve_acs_data(state, county, tract, tableId, year, saveAcs)
    if numer and denom:
      # Numerators 
      numerators = pd.DataFrame()
      for colSubString in numer:
        colName = list(filter(lambda x: colSubString in x, df.columns))[0] 
        numerators = addKey(df, numerators, colName)
      # Denominators
      denominators = pd.DataFrame()
      for colSubString in denom:
        colName = list(filter(lambda x: colSubString in x, df.columns))[0] 
        denominators = addKey(df, denominators, colName)
      # Run the Calculation 
      fi = pd.DataFrame()
      df['numerator'] = numerators.sum(axis=1)
      df['denominator'] = denominators.sum(axis=1)
      df = df[df['denominator'] != 0] # Delete Rows where the 'denominator' column is 0
      df['final'] = (df['numerator'] / df['denominator'] ) * 100
    df = df.add_prefix('20'+year+'_')
    newTract = '20'+year+'_tract'
    df = df.rename(columns={newTract: 'tract'} )
    if count == 0: count = count+1; final = df
    else: final = final.merge(df, on='tract')
    print('Table: ' + tableId + ', Year: ' + year + ' recieved.')
  print('Download Complete')
  
  # Merge crosswalk with the Names data
  if isinstance(namesCw, pd.DataFrame):
    print('local boundary crosswalk matching on '+lcw2Match)
    print('foreign boundary crosswalk matching on '+fcw2Match)
    print('Pulling from foreign boundary crosswalk '+fcw2Want+' with Columns')
    final = crosswalkIt( namesCw, final, lcw1Match, fcw1Match, fcw1Want, saveCw1, cwlk1FileName )

  # Group and Aggregate 
  if groupBy:
    df = df.groupby(groupBy)
    print('Grouped')
    if aggMethod == 'sum':
      df = sumInts(df)
    else:
      df = sumInts(df)
    print('Aggregated')
    
  # Merge crosswalk with the Geom data
  print('local boundary crosswalk matching on '+lcw2Match)
  print('foreign boundary crosswalk matching on '+fcw2Match)
  print('Pulling from foreign boundary crosswalk '+fcw2Want+' with Columns')
  print(boundsCw.columns)
  final = crosswalkIt( boundsCw, final, lcw2Match, fcw2Match, fcw2Want, saveCw2, cwlk2FileName )
  final = GeoDataFrame(final, geometry=fcw2Want)
  
  return final
{% endraw %} {% raw %}
fnl = getAcsYears(state, county, tract, years, tableId, numer, denom, 
                  namesCw, names_local_match_col, names_foreign_match_col, names_foreign_wanted_col, groupBy, aggMethod,
                  boundsCw, bounds_local_match_col, bounds_foreign_match_col, bounds_foreign_wanted_col, 
                  saveAcs, saveCw1, cwlk1FileName, saveCw2, cwlk2FileName)
fnl.plot()
fnl.columns
fnl.head()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-77-3c2fe0e17d42> in <module>()
----> 1 fnl = getAcsYears(state, county, tract, years, tableId, numer, denom, 
      2                   namesCw, names_local_match_col, names_foreign_match_col, names_foreign_wanted_col, groupBy, aggMethod,
      3                   boundsCw, bounds_local_match_col, bounds_foreign_match_col, bounds_foreign_wanted_col,
      4                   saveAcs, saveCw1, cwlk1FileName, saveCw2, cwlk2FileName)
      5 fnl.plot()

NameError: name 'years' is not defined
{% endraw %}

Data was successfully merged across all years and geometry.

Now we want the tractname, geometry, and the specific column we want to make a gif from.

{% raw %}
td = fnl.filter(regex="final|tract|geometry")
td = td.reindex(sorted(td.columns), axis=1)
td.head()

# Get Min Max
mins = []
maxs = []
for col in td.columns:
  if col in ['NAME', 'state', 'county', 'tract', 'geometry'] :
    pass
  else: 
    mins.append(td[col].min())
    maxs.append(td[col].max())
print(mins, maxs)

# set the min and max range for the choropleth map
vmin, vmax = min(mins), max(maxs)
2015_final 2016_final 2017_final geometry tract
166 63.569354 64.098744 66.476311 POLYGON ((-87.69... 810200
428 59.920635 58.451503 59.096422 POLYGON ((-87.67... 809400
435 67.785805 71.089023 71.301498 POLYGON ((-87.67... 809900
565 62.725367 63.763353 64.749690 POLYGON ((-87.71... 809100
568 62.298308 64.258394 64.253206 POLYGON ((-87.72... 809000
[53.71589840075258, 53.786342123056116, 54.01844532279315] [67.78580535486613, 71.08902333621435, 71.30149812734082]
{% endraw %} {% raw %}
merged = td   
fileNames = []
annotation = 'Source: Baltimore Neighborhood Indicators Allianace - Jacob France Institute, 2019'
saveGifAs = './TESTGIF.gif'
labelBounds = True
specialLabelCol = False
# For each column
for indx, col in enumerate(merged.columns):
    if col in ['NAME', 'state', 'county', 'tract', 'geometry'] :
        pass
    else: 
        print('Col Index: ', indx)
        print('Col Name: '+str(col) )

        # create map, UDPATE: added plt.Normalize to keep the legend range the same for all maps
        fig = merged.plot(column=col, cmap='Blues', figsize=(10,10), 
           linewidth=0.8, edgecolor='0.8', vmin=vmin, vmax=vmax,
           legend=True, norm=plt.Normalize(vmin=vmin, vmax=vmax) 
        )
        print('Fig Created')
        
        # https://stackoverflow.com/questions/38899190/geopandas-label-polygons
        if labelBounds:
          labelColumn = col
          if specialLabelCol: labelColumn = specialLabelCol
          merged.apply(lambda x: fig.annotate(s=x[labelColumn], xy=x.geometry.centroid.coords[0], ha='center'),axis=1);
        
        # remove axis of chart and set title
        fig.axis('off')
        col = col.replace("_final", "").replace("_", " ")
        # str(col.replace("_", " ")[12:])
        fig.set_title(str(col), fontdict={'fontsize': '10', 'fontweight' : '3'})
        print('Fig Titled')
        
        # create an annotation for the  data source
        fig.annotate(annotation,
               xy=(0.1, .08), xycoords='figure fraction',
               horizontalalignment='left', verticalalignment='top',
               fontsize=10, color='#555555')
        print('Fig annotated')
        
        # this will save the figure as a high-res png in the output path. you can also save as svg if you prefer.
        # filepath = os.path.join(output_path, image_name)
        image_name = 'test_'+col+'.jpg'
        fileNames.append(image_name)
        chart = fig.get_figure()
        # fig.savefig(“map_export.png”, dpi=300)
        chart.savefig(image_name, dpi=300)
        plt.close(chart)
        
images = []
for filename in fileNames:
    images.append(imageio.imread(filename))
imageio.mimsave(saveGifAs, images, fps=.5)
{% endraw %}

Optional: Prepair Google Drive Data Folder/ Drive Import Operations

Access Google Drive directories:

{% raw %}
from google.colab import drive
drive.mount("/content/drive")
{% endraw %}

You can also import file directly into a temporary folder in a public folder

{% raw %}
from google.colab import files

# Just uncommment this line and run the cell
# uploaded = files.upload()
{% endraw %}

Now lets explore the file system using the built in terminal:

By default you are positioned in the ./content/ folder.

{% raw %}
cd ./drive/My Drive/colabs/DATA
/content/drive/My Drive/colabs/DATA
{% endraw %} {% raw %}
ls
 avocado.csv
 baltimore-births/
 boundaries-baltimore-communities-NoWater-2010.geojson
 boundaries-baltimore-neighborhoods.csv
 boundaries-baltimore-neighborhoods.geojson
 boundaries-baltimore-neighborhoods.json
 boundaries--baltimore-tracts-NoWater-2010.geojson
 boundaries-evanston-tracts-2010.csv
 boundaries-evanston-tracts-2010.geojson
 boundaries-evanston-tracts-2010.gsheet
 boundaries-maryland_census-tracts-2010.csv
 boundaries-maryland_census-tracts-2010.geojson
 boundaries-maryland-counties.csv
 boundaries-maryland-counties.geojson
 boundaries-moco-census-tracts-2010.csv
 boundaries-moco-census-tracts-2010.geojson
 crosswalk-census-communities-2010.gsheet
 crosswalk-matched-CSA2010-to-CSA-pulling-geometry.csv
 crosswalk-matched-tract-to-TRACT2010-pulling-CSA2010.csv
 crosswalk-matched-tract-to-TRACTCE10-pulling-geometry.csv
 dashboardDataColumnDescriptions.csv
 dashboardDataColumnDescriptions.gsheet
 dashboardData.csv
 dashboardData.gsheet
 exemptions/
'Grid view.csv'
 iw.csv
{% endraw %} {% raw %}
for file in os.listdir("./"):
    if file.endswith(".geojson"):
        print(file)
boundaries-evanston-tracts-2010.geojson
boundaries-moco-census-tracts-2010.geojson
boundaries-maryland-counties.geojson
boundaries-maryland_census-tracts-2010.geojson
boundaries-baltimore-neighborhoods.geojson
boundaries-baltimore-communities-NoWater-2010.geojson
boundaries--baltimore-tracts-NoWater-2010.geojson
{% endraw %}

The next two function will help navigating the file directories:

  • findFile(): Find a Relative Path to a File given its filename
  • addPath(): To 'import' a script you wrote, you must first map its filepath into the sys.
  • The addPath() function uses findFile() and accepts a filename as its parameter.
{% raw %}
    
# Find Relative Path to Files
def findFile(root, file):
    for d, subD, f in os.walk(root):
        if file in f:
            return "{1}/{0}".format(file, d)
            break 

# To 'import' a script you wrote, map its filepath into the sys
def addPath(root, file): sys.path.append(os.path.abspath( findFile( './', file) ))
{% endraw %}