Presented by:
Travis Hathaway
For:
PyCon DE & PyData Darmstadt 2026
Travis Hathaway
(a.k.a. pretty chill guy)
"thath" Station
(definitely not a killer robot)
Today, I'll teach you to think like an urban geographer.
Lay the foundation
Ask meaningful questions
Analyze and present
Physical environment
Photo from Denys Nevozhai on Unsplash
Social & Cultural
By Utcursch - Own work, CC BY-SA 4.0, on wikimedia
Urban Processes
Photo from Point3D Commercial Imaging Ltd. on Unsplash
CSVs are fine but I prefer PostgreSQL!
That's why I created
| zpg list | List available datasets |
| zpg create | Download and imports dataset |
| zpg drop | Remove all census tables from database |
Table showing population in 5 age groups at 100m resolution
Table "zensus.alter_in_5_altersklassen_100m"
Column | Type
------------------------+----------------------
gitter_id_100m | text
insgesamt_bevoelkerung | integer
unter18 | integer
a18bis29 | integer
a30bis49 | integer
a50bis64 | integer
a65undaelter | integer
geom | geometry(Point,3035)
More tools and data will be needed...
OpenStreetMap
PgOSM Flex
Provides neatly organized tables
List of tables
Schema | Name | Type | Owner
-----------+--------------------------+-------+----------
osm | amenity_line | table | user
osm | amenity_point | table | user
osm | amenity_polygon | table | user
osm | building_point | table | user
osm | building_polygon | table | user
osm | poi_line | table | user
osm | poi_point | table | user
osm | poi_polygon | table | user
...
Columns are also easy to reason about
Table "osm_germany.amenity_polygon"
Column | Type
-----------------+-----------------------------
osm_id | bigint
osm_type | text
osm_subtype | text
name | text
housenumber | text
street | text
city | text
state | text
postcode | text
address | text
wheelchair | text
geom | geometry(MultiPolygon,3035)
How many REWEs
does Germany have?
WITH rewes AS (
SELECT
ST_Centroid(poly.geom) as geom
FROM osm.poi_polygon poly
WHERE
name ~* '^rewe'
AND name !~* '(to go|express|getränke|abhol)'
AND osm_type = 'shop'
AND osm_subtype = 'supermarket'
UNION ALL
SELECT geom
FROM osm.poi_point pt
WHERE
name ~* '^rewe'
AND name !~* '(to go|express|getränke|abhol)'
AND osm_type = 'shop'
AND osm_subtype = 'supermarket'
)
SELECT COUNT(*) FROM rewes;
So, how many REWEs are there?
3,750
Compared to official numbers...
~3.800
source: www.rewe-group.com
Germany 🇩🇪: Health Expenditure as % of GDP (2015-2024)
Source: OECD Health Statistics
Health Expenditure as % of GDP — Top 10 OECD Countries (2024)
Source: OECD Health Statistics
Hospital beds per 1,000 inhabitants in Europe
Source: OECD Health Statistics
RQ1 How does travel time to emergency medical services vary across age groups in Germany, and do older age cohorts experience systematically greater or lesser access to higher-lever facilities?
Almost ready for the analysis!
Just need to figure out where
these hospitals are...
WITH hospitals AS (
SELECT
ST_Centroid(poly.geom) as geom
FROM osm.poi_polygon poly
JOIN osm.tags t
ON abs(t.osm_id) = poly.osm_id
WHERE
t.tags ->> 'emergency' = 'yes'
AND
osm_subtype = 'hospital'
UNION ALL
SELECT geom
FROM osm.poi_point pt
JOIN osm.tags t
ON abs(t.osm_id) = pt.osm_id
WHERE
t.tags ->> 'emergency' = 'yes'
AND
osm_subtype = 'hospital'
)
SELECT count(*) FROM hospitals;
Table "public.hospitals"
Column | Type
--------------+----------------------
id | integer
name | text
address | text
care_level | text
geom | geometry(Point,3035)
| emsde analyze | Run analysis for travel cost calculation |
| emsde report | Generate a report that can be adapted for multiple output formats |
The last tool needed...
Straight line distance
Network distance
Now for the results... 🥁
Share of population within thresholds for any hospital
All age groups
Minimal difference
Insignificant difference
Age split for percent of pop within 15 mins
Share of population within thresholds by hospital care level
Coverage by hospital level and age group
RQ1 Based on this analysis, we can conclude there is no significant difference in access across ages groups when we consider Germany as a whole.
All of this would not be possible without these amazing open-source projects:
Plotly
OpenRouteService
PgOSM
Flex
https://blog.thath.net
Exploring Germany's Urban Geography with Census & OpenStreetMap Data | PyCon DE 2026 | Travis Hathaway