Rapidly Measuring Spatial Accessibility of COVID-19 Healthcare Resources: A Case Study of Illinois, USA

**Author**: Jeon-Young Kang 1,2, Alexander Michels 1,3, Fanzheng Lyu1,2, Shaohua Wang1,2 , Nelson Agbodo4, Vincent Freeman5, Shaowen Wang1,2,3,*

1 CyberGIS Center for Advanced Digital and Spatial Studies, University of Illinois at UrbanaChampaign, Urbana, Illinois
2 Department of Geography and Geographic Information Science, University of Illinois at Urbana-Champaign, Urbana, Illinois
3 Illinois Informatics Institute, University of Illinois at Urbana-Champaign, Urbana, Illinois
4 Division of Health Data and Policy, Illinois Department of Public Health, Springfield, Illinois
5 Division of Epidemiology and Biostatistics, School of Public Health, University of Illinois at Chicago, Chicago, Illinois

* Corresponding author: shaowen@illinois.edu

CyberGIS Center for Advanced Digital and Spatial Studies

CyberInfrastructure & Geospatial Information Laboratory

The accessibility measure calculated here is updated daily on https://wherecovid19.cigi.illinois.edu/

You can checkout the paper here: https://doi.org/10.1186/s12942-020-00229-x


Kang, J. Y., Michels, A. C., Lyu, F., Wang, S., Agbodo, N., Freeman, V. L., & Wang, S. (2020). Rapidly Measuring Spatial Accessibility of COVID-19 Healthcare Resources: A Case Study of Illinois, USA. medRxiv https://doi.org/10.1101/2020.05.06.20093534


This aims to measure spatial access for people to hospitals in Illinois. The spatial accessibiilty is measured by the use of an enhanced two-step floating catchment area (E2FCA) method (Luo & Qi, 2009), which is an outcome of interactions between demands (i.e, # of potential patients; people) and supply (i.e., # of beds or physicians). As a result, the map of spatial accessibility will be produced. It identifies which regions need more healthcare resources, such as the number of beds or physicians. This notebook would serve as a guideline of which regions need more beds for fighting against COVID-19.


To perform the ESFCA method, three types of data are required, as follows: (1) road network, (2) population, and (3) hospital information. The road network can be obtained from the OpenStreetMap Python Library, called OSMNX. The population data is available on the American Community Survey. Lastly, hosptial information is also publically available on the Homelanad Infrastructure Foundation-Level Data.

Method - An enhanced two-step floating catchment area (E2FCA)

The catchement area for each hospital will be delineated by travel times. People living in the overlappying regions by multiple hospitals' catchment area are more accessible to hospitals than people living in other places.


import necessary librareis to run this model.

In [1]:
import pandas as pd
import numpy as np
import geopandas as gpd
import networkx as nx
import osmnx as ox
from shapely.geometry import Point, LineString, Polygon
import matplotlib.pyplot as plt
from tqdm import tqdm
import multiprocessing as mp
import folium, itertools, os, time, warnings
from IPython.display import display, clear_output


Load and Visualize Data

Population and COVID-19 Cases Data by County

In [2]:
pop_data = gpd.read_file('./Data/PopData/Chicago_Tract.shp')
0 17031010400 17 031 010400 Census Tract 104 5153 1538 Census Tract 104, Cook County, Illinois 1103 5153 POLYGON ((-87.66125 42.01288, -87.66125 42.012...
1 17031010600 17 031 010600 Census Tract 106 6271 438 Census Tract 106, Cook County, Illinois 1469 6271 POLYGON ((-87.67059 42.00537, -87.67046 42.005...
2 17031030200 17 031 030200 Census Tract 302 5444 2075 Census Tract 302, Cook County, Illinois 2018 5444 POLYGON ((-87.67062 41.99808, -87.67045 41.998...
3 17031030300 17 031 030300 Census Tract 303 3464 516 Census Tract 303, Cook County, Illinois 1097 3464 POLYGON ((-87.67501 41.99799, -87.67473 41.998...
4 17031030400 17 031 030400 Census Tract 304 2582 1520 Census Tract 304, Cook County, Illinois 860 2582 POLYGON ((-87.67471 41.99076, -87.67440 41.990...

Hospital Data

Note that 999 is treated as a "NULL"/"NA" so these hospitals are filtered out. This data contains the number of ICU beds and ventilators at each hospital.

In [3]:
hospitals = gpd.read_file('./Data/HospitalData/Chicago_Hospital_Info.shp')
FID Hospital City ZIP_Code X Y Total_Bed Adult ICU Total Vent geometry
0 2 Methodist Hospital of Chicago Chicago 60640 -87.671079 41.972800 145 36 12 MULTIPOINT (-87.67108 41.97280)
1 4 Advocate Christ Medical Center Oak Lawn 60453 -87.732483 41.720281 785 196 64 MULTIPOINT (-87.73248 41.72028)
2 13 Evanston Hospital Evanston 60201 -87.683288 42.065393 354 89 29 MULTIPOINT (-87.68329 42.06539)
3 24 AMITA Health Adventist Medical Center Hinsdale Hinsdale 60521 -87.920116 41.805613 261 65 21 MULTIPOINT (-87.92012 41.80561)
4 25 Holy Cross Hospital Chicago 60629 -87.690841 41.770001 264 66 21 MULTIPOINT (-87.69084 41.77000)

Generate and Plot Map of Hospitals

In [4]:
m = folium.Map(location=[41.85, -87.65], tiles='cartodbpositron', zoom_start=10)
for i in range(0, len(hospitals)):
      location=[hospitals.iloc[i]['Y'], hospitals.iloc[i]['X']],
      popup="{}{}\n{}{}\n{}{}".format('Hospital Name: ',hospitals.iloc[i]['Hospital'],
                                      'ICU Beds: ',hospitals.iloc[i]['Adult ICU'],
                                      'Ventilators: ', hospitals.iloc[i]['Total Vent']),
      legend_name = 'Hospitals'
legend_html =   '''<div style="position: fixed; width: 20%; heigh: auto;
                            bottom: 10px; left: 10px;
                            solid grey; z-index:9999; font-size:14px;
                            ">&nbsp; Legend<br>'''


Load and Plot Hexagon Grids (500-meter resolution)

In [5]:
grid_file = gpd.read_file('./Data/GridFile/Chicago_Grid.shp')
<matplotlib.axes._subplots.AxesSubplot at 0x7ff6b106a750>

Load and Plot the Street Network

In [2]:
if not os.path.exists("Data/Chicago_Network.graphml"):
    G = ox.graph_from_place('Chicago', network_type='drive') # pulling the drive network the first time will take a while
    ox.save_graphml(G, 'Chicago_Network.graphml', folder="Data")
    G = ox.load_graphml('Chicago_Network.graphml', folder="Data", node_type=str)
ox.plot_graph(G, fig_height=10)