The Burger King Pandemic

The Burger King Pandemic

Whilst I was rooting around for inspiration, my girlfriend suggested I should do a post about food, quickly followed up by “burgers!!!”. So a few google searches later and I decided to create an animated map, showing all the countries of the world that had at least one Burger King store.

I’m particularly chuffed that I’ve managed to combine a multitude of really cool packages in this post. We’ve got:

  • Data scraped off Wikipedia using the rvest package in conjunction with the purr package.
  • Some classic data manipulation using the wonders of the tidyverse
  • Using the glue package to format and interpolate strings.
  • Creating a geospatial visualisation using the new ggplot2 release, with the sf package and obtaining data from the rnaturalearth package.
  • Animating the visualisation using the gifski package

Ok so lets get started.

library(tidyverse)
## Warning: package 'tidyr' was built under R version 3.5.2
## Warning: package 'dplyr' was built under R version 3.5.2
library(rvest)
library(sf)
library(glue)
library(rnaturalearth)
library(gifski)

Firstly I’ve located the data I want, a Wikipedia page that lists the countries with Burger King franchises.

url <- "https://en.wikipedia.org/wiki/List_of_countries_with_Burger_King_franchises"

Now to scrape the data from each table we need to know the Xpath or CSS selector. Normally I would use the Selector Gadget chrome addin to get the selector, (à la this blog), but I couldn’t get it to work. So I inspected the element of the first table and got '//*[@id="mw-content-text"]/div/table[2]'). A quick scroll down and I figured out I want tables 2 - 8. So to iterate through these 7 tables, I constructed a function to extract the data.

extract_table_df <- function(table_no){
  table <- url %>%
    read_html() %>%
    html_nodes(xpath = glue('//*[@id="mw-content-text"]/div/table[{table_no}]')) %>%
    html_table()
  table_df <- table[[1]] %>%
    mutate(Yearentered = as.character(Yearentered))
}

Now we can use this function combined with the purrr function map_dfr to iterate through the 8 tables and bind them together.

data <- map_dfr(2:8, extract_table_df)
glimpse(data)
## Observations: 120
## Variables: 5
## $ `Country/territory` <chr> "Egypt", "Ghana", "Ivory Coast", "Kenya", ...
## $ Yearentered         <chr> "2007", "2018", "2015", "2016", "2011", "2...
## $ Masterfranchisee    <chr> "Olayan Group", "SIA QSR Ghana Ltd.[19]", ...
## $ Notes               <chr> "Olayan's food service subsidiary, Hana In...
## $ Country             <chr> NA, NA, NA, NA, NA, NA, "Afghanistan", "Ba...

A quick inspection of the data shows a few things. We have unexpectedly brought the reference numbers with us, which makes the year column wrong and some tables had country/territory, whilst others simply contained country. And some observations have no year at all.

So lets fix that!

tidy_data <- data %>%
  mutate(country = ifelse(is.na(Country), `Country/territory`, Country)) %>%
  mutate(year = as.numeric(str_sub(Yearentered, end=4))) %>%
  filter(!is.na(year)) %>%
  select(-Notes)

Now we have the data as we need it, right?

Lets now get the spatial data we need to plot the results. This comes from the very handy rnaturalearth package.

countries_sf <- ne_countries(scale = "medium", returnclass = "sf")

A quick glimpse at the data shows a name_en variable that should hopefully match with our country variable in our previous dataset. However what if some of the country names don’t match up?

mismatches <- tidy_data %>%
  anti_join(countries_sf, by  = c("country" = "name_en"))
mismatches
##   Country/territory Yearentered        Masterfranchisee     Country
## 1              <NA>        2005                               China
## 2              <NA>        2013     Fast Food Timor Lda Timor-Leste
## 3         Macedonia        2011                TAB Gida        <NA>
## 4     United States    19541957 Burger King Corporation        <NA>
##         country year
## 1         China 2005
## 2   Timor-Leste 2013
## 3     Macedonia 2011
## 4 United States 1954

Uh-oh, 4 countries don’t match up. As its a small amount it seemed appropriate to define a new dataset for these countries.

Ok so what are the names used within countries_sf dataframe?

unique(countries_sf$name_en)
##   [1] "Zimbabwe"                                    
##   [2] "Zambia"                                      
##   [3] "Yemen"                                       
##   [4] "Vietnam"                                     
##   [5] "Venezuela"                                   
##   [6] "Vatican City"                                
##   [7] "Vanuatu"                                     
##   [8] "Uzbekistan"                                  
##   [9] "Uruguay"                                     
##  [10] "Federated States of Micronesia"              
##  [11] "Marshall Islands"                            
##  [12] "Northern Mariana Islands"                    
##  [13] "United States Virgin Islands"                
##  [14] "Guam"                                        
##  [15] "American Samoa"                              
##  [16] "Puerto Rico"                                 
##  [17] "United States of America"                    
##  [18] "South Georgia and the South Sandwich Islands"
##  [19] "British Indian Ocean Territory"              
##  [20] "Saint Helena"                                
##  [21] "Pitcairn Islands"                            
##  [22] "Anguilla"                                    
##  [23] "Falkland Islands"                            
##  [24] "Cayman Islands"                              
##  [25] "Bermuda"                                     
##  [26] "British Virgin Islands"                      
##  [27] "Turks and Caicos Islands"                    
##  [28] "Montserrat"                                  
##  [29] "Jersey"                                      
##  [30] "Guernsey"                                    
##  [31] "Isle of Man"                                 
##  [32] "United Kingdom"                              
##  [33] "United Arab Emirates"                        
##  [34] "Ukraine"                                     
##  [35] "Uganda"                                      
##  [36] "Turkmenistan"                                
##  [37] "Turkey"                                      
##  [38] "Tunisia"                                     
##  [39] "Trinidad and Tobago"                         
##  [40] "Tonga"                                       
##  [41] "Togo"                                        
##  [42] "East Timor"                                  
##  [43] "Thailand"                                    
##  [44] "Tanzania"                                    
##  [45] "Tajikistan"                                  
##  [46] "Taiwan"                                      
##  [47] "Syria"                                       
##  [48] "Switzerland"                                 
##  [49] "Sweden"                                      
##  [50] "eSwatini"                                    
##  [51] "Suriname"                                    
##  [52] "South Sudan"                                 
##  [53] "Sudan"                                       
##  [54] "Sri Lanka"                                   
##  [55] "Spain"                                       
##  [56] "South Korea"                                 
##  [57] "South Africa"                                
##  [58] "Somalia"                                     
##  [59] "Somaliland"                                  
##  [60] "Solomon Islands"                             
##  [61] "Slovakia"                                    
##  [62] "Slovenia"                                    
##  [63] "Singapore"                                   
##  [64] "Sierra Leone"                                
##  [65] "Seychelles"                                  
##  [66] "Serbia"                                      
##  [67] "Senegal"                                     
##  [68] "Saudi Arabia"                                
##  [69] "São Tomé and Príncipe"                       
##  [70] "San Marino"                                  
##  [71] "Samoa"                                       
##  [72] "Saint Vincent and the Grenadines"            
##  [73] "Saint Lucia"                                 
##  [74] "Saint Kitts and Nevis"                       
##  [75] "Rwanda"                                      
##  [76] "Russia"                                      
##  [77] "Romania"                                     
##  [78] "Qatar"                                       
##  [79] "Portugal"                                    
##  [80] "Poland"                                      
##  [81] "Philippines"                                 
##  [82] "Peru"                                        
##  [83] "Paraguay"                                    
##  [84] "Papua New Guinea"                            
##  [85] "Panama"                                      
##  [86] "Palau"                                       
##  [87] "Pakistan"                                    
##  [88] "Oman"                                        
##  [89] "Norway"                                      
##  [90] "North Korea"                                 
##  [91] "Nigeria"                                     
##  [92] "Niger"                                       
##  [93] "Nicaragua"                                   
##  [94] "New Zealand"                                 
##  [95] "Niue"                                        
##  [96] "Cook Islands"                                
##  [97] "Netherlands"                                 
##  [98] "Aruba"                                       
##  [99] "Curaçao"                                     
## [100] "Nepal"                                       
## [101] "Nauru"                                       
## [102] "Namibia"                                     
## [103] "Mozambique"                                  
## [104] "Morocco"                                     
## [105] "Western Sahara"                              
## [106] "Montenegro"                                  
## [107] "Mongolia"                                    
## [108] "Moldova"                                     
## [109] "Monaco"                                      
## [110] "Mexico"                                      
## [111] "Mauritius"                                   
## [112] "Mauritania"                                  
## [113] "Malta"                                       
## [114] "Mali"                                        
## [115] "Maldives"                                    
## [116] "Malaysia"                                    
## [117] "Malawi"                                      
## [118] "Madagascar"                                  
## [119] "Republic of Macedonia"                       
## [120] "Luxembourg"                                  
## [121] "Lithuania"                                   
## [122] "Liechtenstein"                               
## [123] "Libya"                                       
## [124] "Liberia"                                     
## [125] "Lesotho"                                     
## [126] "Lebanon"                                     
## [127] "Latvia"                                      
## [128] "Laos"                                        
## [129] "Kyrgyzstan"                                  
## [130] "Kuwait"                                      
## [131] "Kosovo"                                      
## [132] "Kiribati"                                    
## [133] "Kenya"                                       
## [134] "Kazakhstan"                                  
## [135] "Jordan"                                      
## [136] "Japan"                                       
## [137] "Jamaica"                                     
## [138] "Italy"                                       
## [139] "Israel"                                      
## [140] "Palestine"                                   
## [141] "Ireland"                                     
## [142] "Iraq"                                        
## [143] "Iran"                                        
## [144] "Indonesia"                                   
## [145] "India"                                       
## [146] "Iceland"                                     
## [147] "Hungary"                                     
## [148] "Honduras"                                    
## [149] "Haiti"                                       
## [150] "Guyana"                                      
## [151] "Guinea-Bissau"                               
## [152] "Guinea"                                      
## [153] "Guatemala"                                   
## [154] "Grenada"                                     
## [155] "Greece"                                      
## [156] "Ghana"                                       
## [157] "Germany"                                     
## [158] "Georgia"                                     
## [159] "The Gambia"                                  
## [160] "Gabon"                                       
## [161] "France"                                      
## [162] "Saint Pierre and Miquelon"                   
## [163] "Wallis and Futuna"                           
## [164] "Saint Martin"                                
## [165] "Saint-Barthélemy"                            
## [166] "French Polynesia"                            
## [167] "New Caledonia"                               
## [168] "French Southern and Antarctic Lands"         
## [169] "Åland Islands"                               
## [170] "Finland"                                     
## [171] "Fiji"                                        
## [172] "Ethiopia"                                    
## [173] "Estonia"                                     
## [174] "Eritrea"                                     
## [175] "Equatorial Guinea"                           
## [176] "El Salvador"                                 
## [177] "Egypt"                                       
## [178] "Ecuador"                                     
## [179] "Dominican Republic"                          
## [180] "Dominica"                                    
## [181] "Djibouti"                                    
## [182] "Greenland"                                   
## [183] "Faroe Islands"                               
## [184] "Denmark"                                     
## [185] "Czech Republic"                              
## [186] "Turkish Republic of Northern Cyprus"         
## [187] "Cyprus"                                      
## [188] "Cuba"                                        
## [189] "Croatia"                                     
## [190] "Ivory Coast"                                 
## [191] "Costa Rica"                                  
## [192] "Democratic Republic of the Congo"            
## [193] "Republic of the Congo"                       
## [194] "Comoros"                                     
## [195] "Colombia"                                    
## [196] "People's Republic of China"                  
## [197] "Macau"                                       
## [198] "Hong Kong"                                   
## [199] "Chile"                                       
## [200] "Chad"                                        
## [201] "Central African Republic"                    
## [202] "Cape Verde"                                  
## [203] "Canada"                                      
## [204] "Cameroon"                                    
## [205] "Cambodia"                                    
## [206] "Myanmar"                                     
## [207] "Burundi"                                     
## [208] "Burkina Faso"                                
## [209] "Bulgaria"                                    
## [210] "Brunei"                                      
## [211] "Brazil"                                      
## [212] "Botswana"                                    
## [213] "Bosnia and Herzegovina"                      
## [214] "Bolivia"                                     
## [215] "Bhutan"                                      
## [216] "Benin"                                       
## [217] "Belize"                                      
## [218] "Belgium"                                     
## [219] "Belarus"                                     
## [220] "Barbados"                                    
## [221] "Bangladesh"                                  
## [222] "Bahrain"                                     
## [223] "The Bahamas"                                 
## [224] "Azerbaijan"                                  
## [225] "Austria"                                     
## [226] "Australia"                                   
## [227] "Australian Indian Ocean Territories"         
## [228] "Heard Island and McDonald Islands"           
## [229] "Norfolk Island"                              
## [230] "Ashmore and Cartier Islands"                 
## [231] "Armenia"                                     
## [232] "Argentina"                                   
## [233] "Antigua and Barbuda"                         
## [234] "Angola"                                      
## [235] "Andorra"                                     
## [236] "Algeria"                                     
## [237] "Albania"                                     
## [238] "Afghanistan"                                 
## [239] "Siachen Glacier"                             
## [240] "Antarctica"                                  
## [241] "Sint Maarten"

We can see from this that the countries do exist within the dataset, they just need renaming. So lets define this new dataset.

country_match <- tribble(
  ~country, ~sf_country,
  "United States", "United States of America",
  "Macedonia", "Republic of Macedonia",
  "Timor-Leste", "East Timor",
  "China", "People's Republic of China")
country_match
## # A tibble: 4 x 2
##   country       sf_country                
##   <chr>         <chr>                     
## 1 United States United States of America  
## 2 Macedonia     Republic of Macedonia     
## 3 Timor-Leste   East Timor                
## 4 China         People's Republic of China

We can now completely join the spatial data to the important data.

joined_data <- 
  tidy_data %>%
  left_join(country_match) %>%
  mutate(country = ifelse(is.na(sf_country), country, sf_country)) %>%
  left_join(countries_sf,  by  = c("country" = "name_en"))

Now we have all of data in one dataframe!

Firstly lets show a quick plot of the countries, using ggplot and sf.

ggplot() + geom_sf(data = countries_sf) 

And now lets pull all the pieces together.

plot_fun <- function(open_year){
p <- ggplot() + 
  ## Add the background countries, but filter away Antarctica because it is unecessary.
  geom_sf(data = filter(countries_sf, name_en != "Antarctica")) + 
  ## Add the countries data, filtering so countries only appear after the first burger king has opened
  geom_sf(data = filter(joined_data, year <= open_year), fill = rgb(236, 28, 36, maxColorValue = 255)) + 
  ## Change the theme so we don't get a background plot or axes. The coord_sf part is a workaround to a current bug that makes gridlines appear.
  theme_void() + coord_sf(datum=NA) + guides(fill=FALSE) + 
  ## Stitch the year to the title with glue
  labs(title = glue("    Countries with a Burger King, year: {open_year}"),
       subtitle = glue("      Count of countries: {nrow(filter(joined_data, year <= open_year))}"))
print(p)
}

Now to save the gif to our working directory.

save_gif(walk(min(joined_data$year):max(joined_data$year), plot_fun), delay = 0.5, gif_file = "animation.gif")

And we get the final output:

Burger King Animation

Burger King Animation

P.S. I did quickly briefly add in a transition_time(year) using gganimate, just to experiment and see what happenes. Surprisingly it did make something!

Tomas Westlake avatar
About Tomas Westlake
Data Scientist for the UK Government
comments powered by Disqus