Access to public libraries plays an important role in supporting community education and equal access to resources. Libraries offer books, internet access, programming, and community gathering spaces that are very importatn for society.
But access to these resources is not always evenly distributed across a city. Specifically, some wards might have multiple libraries within close proximity, while others might have none. Identifying these geographic disparities can help highlight where more investment in libraries might be most needed.
In this analysis, we use spatial data science methods to:
This provides a spatial understanding of library accessibility that can be used to make decisions related to public service planning and equal resource allocation.
We will use:
These datasets will help us visualize both point data (library locations) and polygon data (ward boundaries) on a single map.
# import the livraries
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
import matplotlib.pyplot as plt
# load the datasets
libraries_csv = pd.read_csv("library.csv")
# get logitude and latitude coordinates from the location column
def coords(location_str):
# Remove whitespace
location_str = location_str.strip()
# Remove parentheses
location_str = location_str.strip("()")
# Split by a comma
lat_str, lon_str = location_str.split(",")
# Convert to float
return float(lat_str.strip()), float(lon_str.strip())
libraries_csv["Latitude"], libraries_csv["Longitude"] = zip(*libraries_csv["LOCATION"].apply(coords))
# geometry colum in data, creating the geodataframe
geometry = [Point(xy) for xy in zip(libraries_csv["Longitude"], libraries_csv["Latitude"])]
libraries = gpd.GeoDataFrame(libraries_csv, geometry=geometry)
libraries.set_crs(epsg=4326, inplace=True)
# load the chicago wards
wards = gpd.read_file("ward.geojson")
# Check CRS
print("Wards CRS:", wards.crs)
print("Libraries CRS:", libraries.crs)
libraries = libraries.to_crs(wards.crs)
# assign each library to a ward
libraries_in_wards = gpd.sjoin(libraries, wards, how="inner", op='within')
print(libraries_in_wards.head())
# count the libraries per ward
library_counts = libraries_in_wards.groupby("ward").size()
wards["library_count"] = wards["ward"].map(library_counts).fillna(0)
# check the counts
print(wards[["ward", "library_count"]].head())
# choropleth map, shows libraires per ward
fig, ax = plt.subplots(1, 1, figsize=(12,12))
wards.plot(column="library_count", ax=ax, legend=True, cmap="OrRd",
legend_kwds={'label': "Number of Libraries", 'shrink': 0.6})
# plot library points on top
libraries.plot(ax=ax, markersize=25, label="Library")
plt.title("Chicago Library Accessibility by Ward")
plt.axis("off")
plt.show()
# Create buffer
buffer = libraries.copy()
buffer["geometry"] = buffer.geometry.buffer(1000)
fig, ax = plt.subplots(1, 1, figsize=(12, 12))
wards.plot(ax=ax,)
buffer.plot(ax=ax, alpha=0.5)
plt.title("Apprx 1 km Library Coverage")
plt.axis("off")
plt.show()
# find wards that dont have any libraries
underserved = wards[wards["library_count"] == 0]
print("Wards with zero libraries:")
print(underserved["ward"].tolist())
Our spatial analysis shows that public library access in Chicago is uneven across wards. Some wards have multiple libraries while others have none. The choropleth map clearly shows this variation, and the 1 km buffer visualization shows which parts of the city are well covered versus underserved.
Wards with low or zero library counts might face larger barriers to accessing library resources which could impact people’s access to books, technology, and community programs. This kind of spatial insight can help urban planning and city agencies target areas for future library investments.
This project provies good insight we could take it one step further by incorporating population data to understand library access compared to the population
Overall, this analysis demonstrates how geospatial data science can inform equal distribution of public resources and be useful for more inclusive urban planning decisions.