Getting administrative boundaries from Open Street Map (OSM) using PyOsmium
Country administrative boundaries play an important role for geospatial data analysis and visualisation. Lots of countries, like Australia, made this data available for download for free.
But what you can do if you need it for a country which doesn’t have this data available? Open Street Map (OSM) is an answer. This community maintained map covers the whole planet and allows you to download data and use it.
As described in my previous post, data could be loaded for a single country or whole continent from Geofabrik.de. I will use Ukraine, the country where I was born, as an example.
Administrative boundaries on OSM
Let’s have a look at the definition for OSM relation with ID 60199 for Ukraine at https://www.openstreetmap.org/relation/60199
Each relation on OSM has a unique ID and number of tags. Tags describe this object. For example it’s type “boundary” = “administrative” and “admin_level”=”2". 2 is the “country” level used in OSM. Within each country, the administrative level hierarchy could be different. In the case of Ukraine, the next admin_level, which contains its regions is level 4.
Kyiv Oblast (Kyiv region) is Level 4 admin area and has Relation ID 7122 https://www.openstreetmap.org/relation/71248
Processing data
We will process data from file ukraine-latest.osm.pbf downloaded from http://download.geofabrik.de/europe/ukraine.html
Install osmium using pip
pip install osmium
AdminAreaHandler adds all areas having the tag “admin_level” to an array of dict objects containing ID, geometry and all tags.
Next step is to create GeoDataFrame containing these areas
Result looks like this:
Geo column contains admin area geometry as MULTIPOLYGON.
As you can see results contain administrative areas not only from Ukraine, but also from neighbouring countries. So we can filter areas located within the Ukraine country boundary by using the GeoPandas within() method which checks if area geometry is located inside the country border.
in_ukraine = gdf.within(gdf[gdf.admin_level == "2"].geo.iloc[0])
Now we can plot Ukraine regions with their name in English
Plotting other administrative area levels, for example Level 7, is also possible with minor code changes:
Finally you can save administrative boundaries data as a CSV file:
gdf.to_csv("ukraine_admin_boundaries.csv")
Complete code example with OSM data file is available on Kaggle.
UPDATE: I’ve modified code example on Kaggle to remove coastal waters using areas with tag “place” = “sea”, so it matches coast line.
Check also:
Extracting Open Street Map (OSM) street data from data files using PyOsmium