Creating School Locations from Enrolment Data

Contents

Creating School Locations from Enrolment Data#

In this example, we show how to use Polaris-Studio to create school locations with appropriate enrolments data for the modelling area.

Imports#

sphinx_gallery_thumbnail_path = ‘../../examples/model_building/import_enrolments.png’

%load_ext autoreload %autoreload 2

from pathlib import Path

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import contextily as ctx

from polaris import Polaris
from polaris.utils.testing.temp_model import TempModel
from polaris.utils.plot_utils import get_marker_sizes

We need to provide some good enrolment data to the process. The following snippet was build by collection of data from various public sources

from polaris.utils.file_utils import get_caller_directory

enrolments_file = get_caller_directory() / "education_locations_bloomington.parquet"

gpd.read_parquet(enrolments_file).head()
school_type enrolments geometry
2734 num_prek 323.0 POINT (330915.599 4478768.108)
8356 num_prek 6.0 POINT (331164.249 4487973.822)
19814 num_prek 1.0 POINT (328496.841 4486412.003)
23530 num_prek 212.0 POINT (329276.115 4482512.085)
25502 num_prek 194.0 POINT (333992.292 4486534.083)


gpd.read_parquet(enrolments_file).school_type.value_counts()
school_type
num_k_8     30
num_prek    11
num_9_12    10
tertiary     6
Name: count, dtype: int64

Now lets actually pass that data into the school location importer

model = Polaris(TempModel("Bloomington"))
model.network.populate.add_school_locations(enrolments_file)
2025-10-01 17:00:14 UTC+0000 - Upgrading Freight database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Freight.sqlite
2025-10-01 17:00:14 UTC+0000 - No migrations to apply
2025-10-01 17:00:14 UTC+0000 - Upgrading Freight database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Freight.sqlite: Done in 0:00:00.007118 seconds
2025-10-01 17:00:14 UTC+0000 - Upgrading Demand database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Demand.sqlite
2025-10-01 17:00:14 UTC+0000 - No migrations to apply
2025-10-01 17:00:14 UTC+0000 - Upgrading Demand database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Demand.sqlite: Done in 0:00:00.001128 seconds
2025-10-01 17:00:14 UTC+0000 - Upgrading Supply database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Supply.sqlite
2025-10-01 17:00:14 UTC+0000 - No migrations to apply
2025-10-01 17:00:14 UTC+0000 - Upgrading Supply database at location /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Supply.sqlite: Done in 0:00:00.009787 seconds
2025-10-01 17:00:15 UTC+0000 - Working with file on /tmp/polaris_studio_testing/2025-10-01_17-00-12--565e/Bloomington-Supply.sqlite
2025-10-01 17:00:16 UTC+0000 - Adding school locations from /home/gitlab-runner/builds/polaris/code/polarislib/docs/examples/model_building/education_locations_bloomington.parquet
2025-10-01 17:00:26 UTC+0000 - Downloading places from Overture maps. Sit tight! This may take a while.
2025-10-01 17:00:30 UTC+0000 - places data downloaded. Basic geo-processing
2025-10-01 17:00:30 UTC+0000 - Found 25 childcare centres from Overture maps POI, adding these with an average enrolment of 105.0 students
2025-10-01 17:00:30 UTC+0000 - 82 out of 82 nation-wide education locations are in model area
2025-10-01 17:00:30 UTC+0000 - Inserting 82 new education locations
2025-10-01 17:00:30 UTC+0000 - Inserting enrolment data for 82 school locations
2025-10-01 17:00:31 UTC+0000 - Running consistency checks on the supply database
2025-10-01 17:00:31 UTC+0000 - Updating Location geo-association throughout the database
2025-10-01 17:00:31 UTC+0000 -   location geo association for Ev_charging_Stations
2025-10-01 17:00:31 UTC+0000 - Updating Link geo-association throughout the database
2025-10-01 17:00:32 UTC+0000 -    link records corrected for 87 records on Location
2025-10-01 17:00:32 UTC+0000 -    link records corrected for 2663 records on Parking
2025-10-01 17:00:33 UTC+0000 -    bike_link records corrected for 2 records on Location
2025-10-01 17:00:33 UTC+0000 -    walk_link records corrected for 2 records on Location
2025-10-01 17:00:33 UTC+0000 -    bike_link records corrected for 24 records on Parking
2025-10-01 17:00:33 UTC+0000 -    walk_link records corrected for 24 records on Parking
2025-10-01 17:00:33 UTC+0000 - Searching for location link candidates
2025-10-01 17:00:33 UTC+0000 -       Rebuilding Location Links
2025-10-01 17:00:34 UTC+0000 -       Saving Location Links

# Lets look at the results

df_loc = model.network.tables.get("location")
df_loc = df_loc.merge(model.network.tables.get("location_attributes")[["location", "enrolments"]], on="location")
print(df_loc.groupby("land_use").agg({"enrolments": ["count", "sum"]}).round(0))
df_loc = df_loc[df_loc.land_use.str.contains("EDUCATION")].to_crs(epsg=3857)  # Web Mercator for contextily basemap

markers = get_marker_sizes(df_loc, "enrolments", min_size=50, max_size=1000)
ax = df_loc.plot(column="land_use", categorical=True, legend=True, figsize=(10, 10), markersize=markers, alpha=1.0)
ctx.add_basemap(ax, source=ctx.providers.CartoDB.Positron)

plt.tight_layout()
ax.set_axis_off()
plt.show()
plot import enrolments
                 enrolments
                      count       sum
land_use
ALL                    2833       0.0
EDUCATION_9_12          120   74572.0
EDUCATION_K_8           360  138194.0
EDUCATION_PREK          388   28280.0
HIGHER_EDUCATION         72  331296.0

Total running time of the script: (0 minutes 54.251 seconds)

Gallery generated by Sphinx-Gallery