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-09-05 05:57:50 UTC+0000 - Upgrading Freight database at location /tmp/polaris_studio_testing/2025-09-05_05-57-49--341c/Bloomington-Freight.sqlite
2025-09-05 05:57:50 UTC+0000 - Upgrading Demand database at location /tmp/polaris_studio_testing/2025-09-05_05-57-49--341c/Bloomington-Demand.sqlite
2025-09-05 05:57:50 UTC+0000 - Upgrading Supply database at location /tmp/polaris_studio_testing/2025-09-05_05-57-49--341c/Bloomington-Supply.sqlite
2025-09-05 05:57:50 UTC+0000 - Working with file on /tmp/polaris_studio_testing/2025-09-05_05-57-49--341c/Bloomington-Supply.sqlite
2025-09-05 05:57:51 UTC+0000 - Adding school locations from /home/gitlab-runner/builds/polaris/code/polarislib/docs/examples/model_building/education_locations_bloomington.parquet
2025-09-05 05:58:00 UTC+0000 - Downloading places from Overture maps. Sit tight! This may take a while.
2025-09-05 05:58:03 UTC+0000 - places data downloaded. Basic geo-processing
2025-09-05 05:58:03 UTC+0000 - Found 21 childcare centres from Overture maps POI, adding these with an average enrolment of 105.0 students
2025-09-05 05:58:03 UTC+0000 - 78 out of 78 nation-wide education locations are in model area
next_location_id=2834
2025-09-05 05:58:03 UTC+0000 - Inserting blank enrolment data for all non-school locations
2025-09-05 05:58:03 UTC+0000 - Inserting 78 new education locations
2025-09-05 05:58:04 UTC+0000 - Inserting enrolment data for 78 school locations
2025-09-05 05:58:04 UTC+0000 - Running consistency checks on the supply database
2025-09-05 05:58:04 UTC+0000 - Updating Location geo-association throughout the database
2025-09-05 05:58:04 UTC+0000 -   location geo association for Ev_charging_Stations
2025-09-05 05:58:04 UTC+0000 - Updating Link geo-association throughout the database
2025-09-05 05:58:05 UTC+0000 -    link records corrected for 29 records on Location
2025-09-05 05:58:05 UTC+0000 -    link records corrected for 2679 records on Parking
2025-09-05 05:58:06 UTC+0000 -    bike_link records corrected for 2910 records on Location
2025-09-05 05:58:06 UTC+0000 -    walk_link records corrected for 2910 records on Location
2025-09-05 05:58:06 UTC+0000 -    bike_link records corrected for 2832 records on Parking
2025-09-05 05:58:06 UTC+0000 -    walk_link records corrected for 2832 records on Parking
2025-09-05 05:58:06 UTC+0000 - Searching for location link candidates
2025-09-05 05:58:06 UTC+0000 -       Rebuilding Location Links
2025-09-05 05:58:07 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           10   6214.0
EDUCATION_K_8            30  11516.0
EDUCATION_PREK           32   3361.0
HIGHER_EDUCATION          6  27608.0

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

Gallery generated by Sphinx-Gallery