How to create beautiful maps with Python

I’ve always loved city maps, and a few weeks ago I decided to create my own artistic version. Googling a little, I found cool leadershipwritten by By Frank Ceballos… It’s fun and useful, but I prefer more detailed / realistic schematic maps. Because of this, I decided to create my own version of the maps. So let’s see how we can create beautiful maps using Python and OpenStreetMap data.

Installing OSMnx

First of all, we need to install Python. I recommend using Conda and virtual environments (venv) to create a workspace. We are also going to use the Python OSMnx package, which will allow us to load spatial data from OpenStreetMap. To expand venv and install OSMnx, you need to run two Conda commands:

conda config --prepend channels conda-forge
conda create -n ox --strict-channel-priority osmnx

Downloading road and street networks

After successfully installing OSMnx, we can start programming. The first thing we need to do is load the data. This can be done in different ways, one of the simplest is to use the method graph_from_place()

graph_from_place() takes several parameters. place Is a request that will be used by OpenStreetMaps to fetch data from a specified location, retain_all will return us all streets, even if they are not linked to other elements, simplify will clear up the provided graph a bit, and network_type will indicate what type of street network you need to get.

I want to get all possible data (network_type=’all’)but you can only load driving roads using drive, or footpaths using walk

Another way to load data is to use graph_from_point()which allows us to provide GPS coordinates. In some cases, this option is more convenient, for example in places with similar names, and gives us greater accuracy. Using dist, we can save only those nodes that are within the specified limits from the center of the graph.

You need to consider that if you are downloading data from large locations such as Madrid or Berlin, you need to wait a bit to get all the information.

Unpacking and coloring our data

AND graph_from_place()and graph_from_point() will return MultiDiGraphwhich we can unpack and put in the list as shown in by Frank Ceballos

Now we just have to iterate over the data and color it, as well as adjust line width depending on the length streets.

It is even possible to identify certain roads and color only these roads in some other way.

In my example I use the following colors:


Feel free to change colors or conditions to create new cards to your liking.

Draw and save the map

Finally, we only need one thing – to form the map. First, we need to define the center of our map. Select the GPS coordinates for the location you want to center on the map. Then we will add borders and background color. bgcolor, north, south, east and west will be the new boundaries of our map. The generated map will be cropped according to the entered coordinates. If you need a bigger map, just increase the boundaries. Note that if you use the method graph_from_point(), you will need to increase the value dist according to your needs. For bgcolor I chose a dark blue color #061529to estimate the drawing, but again you can customize it to your liking.

After these steps, we just need to generate and save the map. I recommend using fig.tight_layout(pad = 0) to adjust map parameters to fit parts of the drawing well.


Using this code, we can create the maps below, but I recommend that you tweak parameters such as line widths or border limits for each city.

One difference to consider between graph_from_place() and graph_from_point(), thing is graph_from_point() retrieves street data from the neighborhood based on the distance you set (dist). Depending on whether you need a simple map or a more detailed one, you can use either of these methods. Madrid map was created with graph_from_place()and a map of Berlin with graph_from_point()

In addition to this, you may need a poster sized image. The easiest way to do this is to set the attribute figsize inside ox.plot_graph()figsize can adjust width and height in inches. I usually choose a larger size, for example figsize=(27,40)

Bonus: add water

OpenStreetMap also contains data on rivers and other natural water sources, such as lakes or water channels. Using OSmnx again, we can load this data.

As before, we can iterate over the data and color the map. In this case, I prefer blue colors, for example #72b1b1 or #5dc1b9

Finally, we need to save the drawing. In this case, I am not using borders with bbox inside plot_graph… This is another thing to experiment with.

After successfully loading the bodies of water, we need to connect the two images. A little GIMP or Photoshop will do the trick; do not forget that these two images must be the same fig_size or borders, bboxto simplify interpolation.

Final touches

I like to add text with city name, GPS coordinates and country name. GIMP or Photoshop do their job.

Also, if you add water, you will need to fill in some places or paint other bodies of water, such as the sea. The river line changes, but you can fill in the gaps with the Paint Bucket tool.

Conclusion and code

The code for creating these maps is available in my Github… Feel free to use it and show me your results! Hope you enjoyed this post. Thank you for reading, and I encourage you to share the knowledge that will lead us to the best, incredible results!

In response to the author’s call, we share our knowledge on our Python course, which will be even more profitable with a promo code HABRadding 10% to the banner discount.


Similar Posts

Leave a Reply