Creating beautiful maps with Python | by Carlos Cilleruelo | Towards Data Science

I always liked city maps and a few weeks ago I decided to build my own artistic versions of it. After googling a little bit I discovered this incredible tutorial written by Frank Ceballos. It is a fascinating and handy tutorial, but I prefer a more detailed/realistic blueprint maps. Because of that, I decided to build my own version. So let’s see how we can create beautiful maps with a little python code and OpenStreetMap data.
First of all, we need to have a Python installation. I recommend using Conda and virtual environments (venv) for achieving a tidy workspace. Moreover, we are going to use OSMnx Python package that will let us download spatial data from OpenStreetMap. We can accomplish the creation of a venv and installing OSMnx just writing two Conda commands:
conda config --prepend channels conda-forgeconda create -n ox --strict-channel-priority osmnx
After successfully install OSMnx, we can start coding. The first thing we need to do is to download the data. Downloading the data can be achieved in different ways, one of the easiest ways is to use graph_from_place().
graph_from_place()has several parameters. place is the query that is going to be used in OpenStreetMaps to retrieving the data, retain_allwill give us all the streets even if they are not connected to other elements, simplifyclean a little bit the returned graph and network_type specify what type of street network to get.
I am looking to retrieve allpossible data but you can also download only drive roads, using drive, or pedestrian pathways using walk.
Another possibility is to use graph_from_point() that allows us to specify a GPS coordinate. This option is more in handy in multiple cases, like places with common names, and gives us more precision. Using dist we can retain only those nodes within this many meters of the centre of the graph.
Also, it is necessary to take into account that if you are downloading data from bigger places like Madrid or Berlin, you will need to wait a little bit in order to retrieve all the information.
Both graph_from_place() and graph_from_point() will return a MultiDiGraph that we can unpack and store in the list as shown in Frank Ceballos tutorial.
Reaching this point we just need to iterate over data and colour it. We can colour it and adjust linewidths base on street lengths.
But there is also the possibility of identifying certain roads and only colour them differently.
In my example, I am only using colourMap.py Gist with the following colours.
color = “#a6a6a6”
color = “#676767”
color = “#454545”
color = “#bdbdbd”
color = “#d5d5d5”
color = “#ffff”
But feel free of changing the colours or conditions in order to create new maps that suit your taste.
Finally, we only need one thing left that is plotting the map. First, we need to identify the centre of our map. Choose the GPS coordinates where you want to be the centre. Then we will add some borders and background colour, bgcolor. north, south, eastand westwest will be new borders of our map. This coordinates will crop the image base on these boundaries, just increase the boundaries in you want a bigger map. Take into account that if you are using graph_from_point() method you will need to increase the dist value base on your needs. For bgcolor I am choosing a blue a dark blue #061529, to simulate a blueprint, but again you can adjust this to your liking.
After that, we just need to plot and save the map. I recommend use fig.tight_layout(pad=0) to adjust the plot params so that subplots are nicely fit.
Using this code we can build the following examples but I recommend that you tunning your settings like line widths or border limit for each city.
One difference to take into account between graph_from_place() and graph_from_point() it is that graph_from_point() will obtain street data from the surroundings, base on the dist that you set. Depending on if you want a simple map or a more detailed one you can exchange between them. The Madrid city map has been created using graph_from_place() and the Berlin city map has been created using graph_from_point() .
On top of that perhaps you want a poster size image. One easy way to accomplish that is to set figsizeattribute inside ox.plot_graph() .figsize can adjust the width, height in inches. I usually chose a bigger size like figsize=(27,40) .
OpenStreetMap has also data from rivers and other natural water sources, like lakes or water canals. Again using OSmnx we can download this data.
In the same way as before we can iterate over this data and colour it. In this case, I prefer blue colours like #72b1b1 or #5dc1b9.
Finally, we just need to save the figure. In this case, I am not using any borders with bbox inside plot_graph . That's another thing that you can play with.
After successfully downloading rivers and like we just need to join the two images. Just a little Gimp or Photoshop will do the trick, remember to create the two images with the same fig_size or limit borders, bbox , for easier interpolation.
One thing that I like to add is a text with the name of the city, GPS coordinates and the country name. Once more Gimp or Photoshop will do the trick.
Also if you add water you will need to fill some spaces or paint other water sources, like seawater. The line with of the rivers is not constant but using the paint bucket tool you can fill those gaps.
The code for creating these maps is available on my GitHub. Feel free to use it and show me your results!! Hope you liked this post and again thanks to Frank Ceballos and the Medium community. Additionally, if any of you want to print some posters I opened a little store on Etsy with my map creations.
Thanks for reading me and sharing knowledge will guide us to better and incredible results!!