Untappd Heat Map - Visualizing My Beer Drinking History

It’s a long story, but I ended up finding a roommate off of Craigslist who was very much into craft beer. He didn’t brew his own beer, but he made a hobby of trying new beers and traveling to breweries domestic and abroad; heck, we even went to a beer festival together. Any time he’d have a beer, he’d log it on Untappd. For those of you who don’t know, Untappd is a mobile application that allows users to keep track of what beers they’ve tried and what they thought of it by checking in beers and rating it. You can explore nearby popular bars, breweries, and beers, look up ratings for beers you’re interested in trying, and you can even see what your friends are drinking.

When I first moved in with him, I didn’t have Untappd, and at the time, my knowledge of beer, and my taste for it, certainly wasn’t as developed as his was. All of this soon changed. While I no longer live with that roommate, I do admire his love for beer and appreciate that he taught me a lot about it. Since downloading Untappd in June 2019, I’ve logged 133 unique beers (and counting) across 49 different breweries in 12 different states. Using an export of my Untappd profile, I generated a heat map to share with you some of my favorite breweries to date; Brix City (NJ), Burlington (VT), Other Half (NY), Finback (NY). Feel free to add me on Untappd and check out my Untapped profile here.

The interactive heatmap below was generated using folium - a powerful Python library that helps to create several types of Leaflet maps. If you scroll over a state, you’ll see the number of beers I’ve had from the state, my average ranking for those beers and how it compares to the Untappd average ranking for those same beers. Additionally, if you click on or within the blue circle marker in the middle of each state, you’ll see a pop-up containing a bar chart that shows the numbers of beers had from each brewery located in that state. The darker the shade of green a state is, the more beers I’ve had from that state. States that I have had fewer beers from are represented with darker shades of red and orange. States with no color fill means I haven’t checked-in a beer from that state yet. Continue reading on if you’re interested in how I generated this heat map.

How I Did It

  1. Obtain Untappd Data - Export Untappd Data From Profile

  2. Prepare Data For Visualization - Clean, refine, and transform Untappd data and geographic data

  3. Generate Folium Interactive Heat Map

  4. Host Visualization as a Heroku Web Application - Allowing my Folium heat map to become embeddable within my blog

You can view the full script here

Obtaining Untappd Data

If you have an Untappd profile, like I do, you can use this article to learn about how to export your data, if you’d like to follow along with this exercise. The Untappd export features 32 fields, with each row representing information about a check-in. Some fields included in this export, for example, are beer name, brewery name, beer type, beer ABV, your rating of the beer, brewery city and state, where the beer was purchased, the global Untappd rating for the beer, and how it was served (can, draft, bottle). While Untappd displays the number of check-ins and unique beers on each users’ profile page, I thought it would be cool to take this a step further and visualize some of these other data points from the export. From the web application of Untappd, I downloaded a csv of my profile, and then ingested the data and transformed using Python.

ezgif.com-gif-maker (1).gif

Prepare Data For Visualization

Before I started working with my data, I did some research on what tools and Python libraries are available for generating interactive maps. I used Plotly in a previous post for creating an interactive visualizations, which could have worked for this project, but I wanted to learn and show you something new. After researching for a few days, I landed on using Folium. Folium’s documentation states that Folium makes it easy to visualize data that’s been manipulated in Python on an interactive leaflet map. It enables both the binding of data to a map for choropleth visualizations as well as passing rich vector/raster/HTML visualizations as markers on the map. I saw a few examples of how Folium could be used and used this visualization from Folium’s GitHub Examples Repository. I also saw here that Folium allows you to add markers to your map, that when clicked, displays another data visualization within a pop-up.

I wanted to show a few different data points and provide users with an engaging experience by allowing them to click and hover over the map to display different data points. The attributes that I would end up showing are -

  • On Hover - State Name, Number of Beers Had From That State, My Average Untappd Rating For Those Beers (Sum of My Ratings/Number of Beers Had), Untappd Average Rating For Those Same Beers

  • On Click - Brewery Name, Number of Beers Had at Each Brewery

In the code blocks below, I’ll show you how I transformed and aggregated the raw Untappd csv export to work with Folium. First, I ingested the CSV and counted the number beers checked-in by state and brewery. In this step I am removing any check-ins where the state is Stockholms län. I’ve had a few beers from Omnipollo Brewery, which are based in Stockholm, Sweden, but for the purposes of this heat map, I’ve removed them to focus on domestic breweries. This data will be displayed when a user clicks on a circle marker on the map.

To get the information seen on hover, I aggregate by state and count the number of unique beer names to get a count of beers checked-in. Also used mean on my ratings and Untappd global ratings to determine what my average rating was for those beers by state versus the general Untappd population.

Later on, when generating the heat map, you’ll notice that I create a for loop to generate the circle markers; one for each state with at least one check-in. In order to this, I had to create a list of the distinct states so that I can tell the script, for each state in the list, display information for that state, and additionally, get the latitude and longitude for the centroid of the state (from another data frame I’ll mention soon).

This next line of code was something new that I learned that and is very powerful. Using the data frame beer_info_by_state, which contains the list of all breweries and beer counts by state, I am able to create a dictionary that stores the data for each state as a key. The output of this one line of code is seen in the screenshot that follows it. From it, you can see that there are multiple data frames stored within this dictionary. In order to get data about one state out of the dictionary, you can call beer_info_df['NJ'] for example, which would return a data frame of only New Jersey breweries from the dictionary. This will be important later on when I show you how I create a bar chart for each state when the circle marker is clicked on.

Screen Shot 2021-04-11 at 6.45.20 PM.png

A majority of this next geographic data section comes from the Folium example hosted on the Folium GitHub page (why reinvent the wheel). In this section, I gather perimeter data (coordinates) for each state as an input to the Folium heat map function so that it knows how to render each state’s outline on the map. Additionally, I’ll be reading in the latitude and longitude for each state’s mid-point, otherwise known as centroid. I’ll also be doing some joining of data frames to produce valuable data frames that contain both geographic data and Untappd data to be used when creating the heat map. If you view the example, you’ll see that I am just repurposing their code to meet my needs.

In this next block, I’m creating a data frame that has the state name, state abbreviation, and latitude/longitude for the state’s centroid. I found a csv of each state’s centroid hosted here. I saved the csv to the same directory as my script and named it states.csv. After reading the csv in as a data frame, I join the state name to the abbreviations data frame from the previous block to get state name, state abbreviation, latitude/longitude for all states. Next, I join to the states data frame, which contains the distinct states with a check-in, to get state name, state abbreviation, latitude/longitude for only states with a check-in.

This next block focuses on creating a data frame with information at a state level; state name, state abbreviation, coordinates representing the states perimeter, number of beers, my average Untappd rating for all beers I’ve checked-in from the state, global Untappd average rating for the beers I’ve checked-in for that state. Take a look at the screenshot that follows to get a better sense of the data frame this block creates.

Screen Shot 2021-04-17 at 12.36.06 PM.png

Now that we have all of the Untappd and geographic data in the correct format, it’s time to generate the heat map using Folium.

Generating Folium Heat Map

To me, the most important aspect of a heat map is the color scale that represents the heat. The color scale is tied to the values of a particular field in a data set; in my case, number of beers checked-in per state. Largely replicating what was done in the Folium example, and repurposing for my own use, I was able to set up the color scale. Branca is a utility module for dealing with colormaps and can be applied to Folium visualizations. You’ll see that I am using “num_beers” from statesmerge to set the min and max values for the color scale, where #red is the min and #darkgreen is the max. On the interactive heat map at the top of this post, you’ll see the color scale on the top right which has the caption of “Number of Beers By State”. That is set in this block.

This final code block below generates the Folium heat map. When run, the output of this block is an .html file called map.html that will be save to the directory in which you have this script saved. This .html file is one of the inputs needed to generate the heat map as a web application. This is summarized in the next section.

First, the necessary libraries are imported that will help produce the heat map. One important library is altair (import altair as alt). Altair is a declarative statistical visualization library for Python, based on Vega and Vega-Lite, that generates beautiful and effective visualizations with a minimal amount of code. I first saw an example of how Altair can be used with Folium to embed statistical plots in pop-up markers here. Check out the for loop in the code block below to understand more about how I effortlessly generated the Altair plots.

Next, the map view is defined in terms of starting coordinates and zoom. In this case, the heat map is centered over (35.3, -97.6) (Newcastle, Oklahoma) with a zoom starting position of 4. Then the tooltip is defined. The tooltip is what you see when hovering over a state. Note how what is displayed is configured with fields and aliases. The style of the tooltip is fittingly set using style.

g=folium.GeoJson takes state perimeter data and state color fill data from a combination of statesmerge and colormap.

The for loop gets the brewery information for each state by looping through beer_states_centroid. For each state in beer_states_centroid, the script will create a horizontal bar plot that has the number of beers had at each brewery. Additionally, the script will gather the latitude and longitude representing each the state’s centroid so that a circle marker can be created to access the bar plot when clicked.

If you do not want or need to generate an .html of the heatmap, you can view the interactive heat map in your Jupyter notebook by calling ‘m’.

Host as Heroku Web Application

What I sadly realized after finishing the heat map was that it was not embeddable on my blog. I was able to view and interact with the heat map within my Jupyter notebook but I didn’t think about the steps needed to take it out of my notebook and add it to this post. A quick Google search, and a few articles later, I found this article about to leverage Flask and Heroku to share your interactive maps. Flask is a popular Python library used for developing web applications, and Heroku is a cloud-based platform that leverages AWS which allows users to deploy, manage, and scale web applications. Used together, these two tools enabled me to create a web application that I could embed in this post. This is how I did it.

Again, I largely followed this Medium article titled Your Cool Folium Maps on the Web by Alberta Odamea Anim-Ayeko, but I’ll also break it down for you. If you want to follow along, I think it would be easiest to look at my GitHub repository for this project. You’ll need to have the four items (exclude README.md) seen in the screenshot below as Heroku needs specific files for the deployment process.

Screen Shot 2021-04-14 at 7.17.29 PM.png

Procfile tells heroku how to run our flask app. Note that the Procfile has no file extension.

Requirements.txt This is a text file, which contains the libraries needed for the python file to run i.e. Flask and gunicorn, with the specific versions used. Heroku needs this to be able to create the exact environment you used to produce your exact results.

App.py from Alberta Odamea Anim-Ayeko in her Medium article, she note that in this Python file the Flask class and render_template function are imported. The app object is created, and is the instance of the Flask class, which together with gunicorn will help heroku deploy our map as a web app. Additionally, the route decorator is created, and a function is defined for it. The decorator tells the application which URL should call the function (render_the_map()). The function returns the rendered template from the templates folder. Rendering a template means converting it into an HTML page. When if __name__ == __main__ is evaluated as true and then app is run.

Lastly, in your GitHub repository, you’ll need to create a folder called templates and store the heat map html file in it. In my case, I saved the output of the heat map as map.html.

Once these four items have been created in a GitHub repository, head on over to Heroku and complete the following steps in order to launch your web application using GitHub -

  • Log in or sign up on heroku.com

  • Click the create a new app button and enter an a name for it and click the create app button

  • Choose a deployment method — Connect to GitHub and sign-in

  • Choose a repository to connect to and connect to it

  • You can chose the automatic deploy option, which ensures that every change you make to your main branch affects the web app. This is what I did

  • Click the deploy branch and wait for Heroku to install and detect the files in your branch

If all goes according to plan, you’ll see in the build log that the build has finished and released. In my case, the Heroku web application was released to https://untappd-heatmap.herokuapp.com/

Screen Shot 2021-04-17 at 9.32.21 AM.png

The next step for me was to embed the Heroku map in this blog post. To do so, it needs to be embed in an iframe. The <iframe> tag specifies an inline frame. An inline frame is used to embed another document within the current HTML document. You can see in the screenshot below that, by using a Squarespace code block, you can embed the iframe straight into your site.

Screen Shot 2021-04-17 at 9.42.43 AM.png

I really hope you enjoyed this post and ultimately learned something new, since I certainly did during this project. If you’d like to view the whole script or download it, you can do so here. If you have any questions about what I wrote here or just want to leave some feedback about this post, feel free to do so in the comment section below. If you’ve read some of my previous posts, you’ll know that I am learning Python, and through blogging, I’m improving my skills with these personal projects and exercises that are in my areas of interest. If you’d like to work on a project together or want to recommend ways to improve this script, please don’t hesitate to reach out. Thanks for reading.

Previous
Previous

Automate Your Daily Reporting Using Python & Google APIs

Next
Next

Sports Betting With the Boys - NBA Prop Bets - Part 1