How to create interactive map plots with Plotly | by Emma Grimaldi | Towards Data Science

One of my favorite part of working with data is without a doubt creating visualizations. Images are the best tool to convey information: they are immediate, the brain can in fact process them thousands of times faster than words. Images are also universal, and they tend to stick longer in our minds. Finally, we are lazy animals and for this reason we pay more attention to visuals, rather than words. How many times did you meet someone new and afterwards you struggled remembering their name, while their face was crystal clear in your head?
I realized how much I love creating visuals while working as a researcher in academia: as much as I liked running experiments and numerical simulations, I was really looking forward to the moment of the project when I would be able to process all my findings and create those pretty yet powerful graphs. Yes, I also had to write papers to describe all the process, the workflow and theoretical reasoning behind the research, but being able to communicate months of work with just few images was just incredible! All this intro was to convince you that images are important, in case you didn’t think so already. And especially for a Data Scientist, who needs to be efficient in conveying information to non-technical audiences, from time to time.
In the last week or so, I have been working on my capstone project regarding storm events in the US while dealing with a dataset of ~11,000 observations containing geospatial information. My first thought was to plot all this data on a map so I could see at a glance what are the areas that are mostly affected by such events. Since I work in Python, Geopandas would be the immediate library of choice, however, I wanted something more interactive. What if I want to change the style of the map? Or, what if I want to see only the thunderstorms or only the hails? I did a little bit of research and found out that plotly was what I needed. I could not find any nice tutorial to walk me through the process, so I looked at a number of examples online trying to deductively understand how this works, with a lot of trial and error. This is the reason why I decided to write this post, together with the fact that I am training and bunch of neural networks for the same project and I have idle time while all those epochs go back and forth.
Note: to do something like what I am about to describe, you will need an account with plotly as well as mapbox. Particularly because you will need an access token, that can be created here, and a username and API key that can be generated here. All this is free. I would also recommend that you are very well versed with Python dictionaries, since they are fundamental to create map plots like these, as you will notice.
I gathered data from the National Climatic Data Center about storm events in the US from year 2000 up to now. As usual I had to do a lot of cleaning, deal with missing data and engineer some features. At this link you can find the .csv file used for this purpose, and for my capstone project in general. The data has information about the latitude and longitude of the phenomenon, which is fundamental for us in order to plot on a map. It also indicates whether it was a thunderstorm, hail, flash flood, etc for a total of seven different categories. The magnitude of the storm event, in which State, and when it happened
Before working on the actual plot, we need to import and assign a few things. Here is where we need our access token from Mapbox, as well as username and api key from Plotly.
import plotly.plotly as pyimport plotly.graph_objs as goimport plotlyimport pandas as pd# setting user, api key and access tokenplotly.tools.set_credentials_file(username='your_username_here', api_key='your_api_key_here')mapbox_access_token = 'your_access_token_here'
In order to generate our figure, we will need two things: data and layout. Our variable data will be a list of seven dictionaries (one per event type), where each one contains the latitude and longitude values, as well as the name of the storm type and the marker characteristics for the plot. The variable layout is a dictionary containing everything concerning the image that is no directly connected with the data: the drop-down menus, the annotations, how we want to format them and where we want to place them.
After reading and assigning the dataframe to a df variable, I created a list containing the names of the seven different storm categories and named it event_types. I for-looped over this list and used it to filter the dataframe, creating a dictionary for each event type and appending it to the data list. This way I have my list of dictionaries, data.
The reason why I assigned an opacity value of 0.5 to the markers is because, most likely, there will be areas with more points than others. Giving some sort of transparency to the points, will allow us to see different shades of the same color on the map, corresponding to different frequencies of the same phenomenon in different areas.
We are done with data, and now it’s layout’s turn, which will definitively require more work.
Let’s set the basic settings of the map.
Now we can start adding things to the map to customize it and make interactive as we like.
Let’s say I want to put a black box with white text on it, that specifies that my points represent only storm events from year 2000 up to now, that caused more than $50k of economic damage. Some static prompt like this, will fall under the annotation key of the layout dictionary: the value corresponding to annotation will need to be a list of dictionaries and in this specific case, a list containing only one dictionary since I want to put only one annotation on my map. It seems cumbersome in words, but doing it is definitely easier than explaining it.
Now it’s time for the drop-down menus, which will need to be assigned to the updatemenus key of the layout dictionary.
I want to add two drop-down menus: one to select the type of storm event to visualize, in case we want to look at only of type instead of all of them, while the other drop-down will allow us to change the type of map on the background, which is dark by default. The name and the styles of the available maps can be found on Mapbox.
Every drop-down menu is defined again through a dictionary, and all these dictionaries will be contained into a list that we will assign to layout['updatemenus'].
If you want, you can easily assign a title to your plot. I did so just by doing layout['title'] = 'Storm Events'.
Once we have our data and layout in order, we can generate the plot just by running:
figure = dict(data = data, layout = layout)py.iplot(figure, filename = 'put_your_name_here')
Et voilà!
You can zoom in, zoom out, select what you want to visualize from the top menu, and change the map type from the menu on the bottom. Pretty cool! I look forward to work on some other plots like this, now that I learned how to do it. Hopefully you found this useful as well!
Feel free to check out:
the Github repository of this code
my other Medium posts.
my LinkedIn profile.
Thank you for reading!