Note
Go to the end to download the full example code.
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()
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()

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)