Making Cool Maps with Geopy and Folium

Convert city names into point locations with Nominatim geocoder and make visualizations with Folium

Alberta Odamea Anim-Ayeko
Towards Data Science

--

Photo by T.H. Chia on Unsplash

This is a two-part series about visualizing cities and sharing your results with others. For the ‘just show me the code’ guys, this is the link. Here’s the order of topics to be covered:

Introduction
What you’ll need to reproduce the code
Scenario
The code
Plotting with Geopandas
Plotting with Folium
Doing more with Folium
Answer to question asked
Conclusion

Introduction

Take this article as a simple introduction to geocoding and plotting with geopy and folium respectively. There are lots of other ways you can do geocoding apart from geopy. There are many APIs available, some that do the normal geocoding and the reverse and others that help you get location information from IP addresses. Check them out here. For this article, I got the inspiration from reading this. I knew there was an all-python way to go about it, so here we are.

What you’ll need to reproduce the code

A computer(obviously? 🤷🏾‍♀️), the IDE of your choice, the geopy, shapely, geopandas, matplotlib and folium and random modules installed. You could use a virtual environment so that these new packages don’t conflict with the ones you already have installed in your base environment. The choice is yours.

Scenario

AYK Delivery company has 11 branches in African capital cities, employs from 10 to 30 people at each branch, which all have website addresses. We have to generate some data for the delivery company and visualize it. In which other countries should the company open new branches? Let’s see how we can answer this question while making our visualization.

The code

GIF via giphy

The modules used for the task are imported. A list is created, made up of the 11 cities where the company has branches. For the get_coordinates function, it takes the list of city names as the argument. Nominatim is the geocoder used, stored in the geolocator variable. The iteration is then done, for every city in our list and the geocoder converts them to coordinate values. At the end of every iteration, the coordinates are saved into the dictionary that was initialized at the start as values and the city names, the keys. The get_coordinates function is called on city_list and saved to the city_coords_dict.

Plotting with Geopandas

Since we’ll mainly be working in geopandas, which has a plot function, we can use that to visualize our cities before going on to plot in folium. One reason for using it is because it’s great for vector data and another is because we’re working with real world points(cities) in 3D and not just points in a 2D plane, so we’ll need that CRS attribute. Okay, let’s dive in!

We create the list of shapely points for all city points and store in a cities_geom. d, the dict is created with Cities as the key, city names, the values and for the geometry key, the shapely points of the cities are stored as values. The cities_gdf is created by passing the dict, d and crs to the GeoDataFrame(a pandas dataframe with a geometry column) method of geopandas and then plotted. But it doesn’t mean much, does it? It just a number of blue points plotted on 2D axes. Now, if these points are plotted on the African map, the visualization will be improved and you can see these points in relation to each other and also see countries which have no points(or representation, if you like).

Geopandas has a number of datasets that you can explore. The one we’ll be using is the naturalearth_lowres, which gives us access to the world map, but our cities are all African so we’ll extract all rows in the geodataframe which have continent value equal to Africa, and store it as africa_gdf. We then employ the plot function again and pass parameters color and edgecolor, just to customize our plot. plt.rcParams lets you control the size of the plot. To label the African countries(which are represented by polygons), we find, for every country, points which will definitely be found in their respective polygon(using representative point().x, representative point().y) and then place the labels there, using annotate. The final thing we do here is to assert that crs of the cities_gdf is equal to that of the africa_gdf because if it isn’t, our points would not fall at their right places.

Plotting with Folium

Let’s first do a simple map with folium.

The geometry column of the cities_gdf is converted to json(but it automatically becomes a GeoJson because it has a geospatial component). Folium.Map() creates the map object which has other functions used for plotting, like the add_child. The geojson is passed into it, and then you have the output.

Doing more with Folium

Remember when I said we had to generate data for the branches? Yeah, it’s time for that. We need to do that so that we can add folium popups to make the map more interactive.

New columns(Name, Coords, Number_of_Employees and Website) are created in addition to the already existing ones.

add_markers_to_the_map takes a folium map object, geodataframe, color and icon argument. The point variable is created. It stores the coordinates, names, employee count and website addresses of the points. These will be used for the popup. An iteration is done so that, for every point stored in the points variable, popup_text, popup and marker variables are created and added to the_map.

  • popup: Creates a popup object and stores the popup_text.
  • marker: Customizes the popup and displays it at some specific location. The prefix ‘fa’ stands for font awesome, which has lots of icons.

Then we call the function with the arguments of our choice and TA-DA! Go on and save your map by using:

the_map.save(‘the_map.html’)

Saving your map as an html file means it can be used on a webpage. We’ll get into that in the second part of this series.

Answer to question asked

In which other countries should the company open new branches?

For this question , you can consider two cities, calculate the distance between them, and create a shapely LineString. Then, you can use the centroid property of the LineString to know what that centre point is. It will fall in one country and there lies your answer. Pretty simple, huh?

Conclusion

It’s a wrap! Feel free to leave your thoughts in the comments. Happy learning and coding. Thanks for reading! 😃👋

Up Next:

--

--