Map Animation of UFC Events up to UFC 250 with MapBox

Technologies: D3.js, Javascript, MapBox API
GitHub: https://github.com/cinhui/ufc-map-event-locations

Motivation

Here I put together a map animation showing the various locations of UFC events that have taken place worldwide. From November 12, 1993 (UFC 1) to June 6, 2020 (UFC 250), there’s been a total of 518 events and UFC has visited 161 cities and 28 countries.

Data

The list of past and scheduled UFC events were previously obtained from the UFC events Wikipedia page. I read them into a Pandas data frame and excluded events that were cancelled or postponed. Only events from UFC 1 to UFC 250 were included in the dataset.

events_df = pd.read_csv("data/list_of_UFC_past_events.csv")
scheduled_df = pd.read_csv("data/list_of_UFC_scheduled_events.csv")
events_df = events_df.append(scheduled_df, sort=True)
# Remove cancelled events
events_df = events_df[events_df['Attendance']!='Cancelled']
# Removed postponed events
events_df = events_df[events_df['Attendance']!='Postponed']

The names of the venues and cities for each event were extracted from the data.

city_df = events_df["Venue"] + ", " + events_df["Location"]
print("Number of visits to cities: " + str(len(city_df)))
city_df = city_df.unique()
print("Number of unique cities: " + str(len(city_df)))

I used the Geocoder from MapBox to get the longitude and latitude coordinates for the event locations. This required first obtaining a MapBox API access token from their website.

# Geocode the event locations
from mapbox import Geocoder
mapbox_access_token = "YOUR_ACCESS_CODE"
geocoder = Geocoder(access_token=mapbox_access_token)
geo_city_df = []
extract_geo_city_df = pd.DataFrame(columns=('location', 'relevance', 'place_name','lat','lng'))
for venue in city_df:
     response = geocoder.forward(venue)
     features = response.geojson()['features'][0]
     geo_city_df.append(features)
     extract_geo_city_df = extract_geo_city_df.append({'location' : venue, 'relevance' : features['relevance'], 'place_name' : features['place_name'], 'lat' : features['geometry']['coordinates'][1], 'lng' : features['geometry']['coordinates'][0]} , ignore_index=True)

The Geocoder will try to search the location and return the coordinates along with a relevance score which provides an assessment of the accuracy of its search. The venue locations were mapped to its corresponding event.

     events_df['coords'] = events_df['Address'].map(geo_city_dict)
     events_df['lat'] = events_df['Address'].map(geo_city_dict_lat)
     events_df['lng'] = events_df['Address'].map(geo_city_dict_lng)

As an added feature, I decided to include the poster for each event. I gathered a list of links to each event’s poster image. The initial list consists of the poster images from the event Wikipedia page. For events that had missing posters or incorrect posters, I was able to locate the event poster from other sources via Google.

events_df = pd.concat([events_df, posters_df], axis=1)

Once all the data was compiled, I wrote the data frame to a csv file and used csv2geojson to convert the data to a geojson file.

csv2geojson events_with_posters_df.csv > events_df.geojson

Building the Animated Map

I used the following examples as references for constructing the animated map.

https://docs.mapbox.com/mapbox-gl-js/example/timeline-animation/
https://docs.mapbox.com/mapbox-gl-js/example/live-update-feature/
https://docs.mapbox.com/mapbox-gl-js/example/popup/

The timeline animation example served as a good starting point. It demonstrates how to load data from a geojson file and also how to update the map using a slider. The live update feature example utilizes the setInterval function which calls a reoccurring function every specified number of milliseconds. The popup example shows how to use the mapboxgl.Popup component to display information at specific coordinates on a map.

The resulting animated map can be found here and the full source code can be found in the project GitHub repository.

Here’s a video that uses the animated map.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.