<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/animating-changes-in-football-kits-using-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://guyabel.com/post/football-kits/"> R-bloggers on Guy Abel</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<div>
<h2>Background</h2>
<p>I am enjoying the <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/" target="_blank">magick</a> package at the moment. Reading through the <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/vignettes/intro.html" target="_blank">vignette</a> I spotted the <code>image_morph()</code> function. In this post I experiment with the function to build the GIF below that shows the changes in the England football first kit over time, using images from the excellent <a rel="nofollow" href="http://www.historicalkits.co.uk/" target="_blank">Historical Football Kits</a> website.</p>
<div>
<img src="https://i2.wp.com/guyabel.com/img/abel-england.gif?w=456&ssl=1" data-recalc-dims="1">
</div>
</div>
<div>
<h2>Scraping</h2>
<p>The Historical Football Kits website has a detailed section on England kits spread over six pages, starting from the first outfits used in <a rel="nofollow" href="http://www.historicalkits.co.uk/international/england/england-1872-1939.html" target="_blank">1872</a>. Each pages includes some interesting discussion – and importantly for this post – images of the kits.</p>
<p>We can use the <code>read_html()</code> from the <a rel="nofollow" href="https://cran.r-project.org/web/packages/xml2/" target="_blank">xml2</a> package and <code>map()</code> from <a rel="nofollow" href="https://cran.r-project.org/web/packages/purrr" target="_blank">purrr</a> to read and save the source code of each page.</p>
<pre><code>library(rvest)
library(tidyverse)

htmls &lt;- c( 
  &quot;http://www.historicalkits.co.uk/international/england/england-1872-1939.html&quot;,
  &quot;http://www.historicalkits.co.uk/international/england/england-1946-1960.html&quot;,
  &quot;http://www.historicalkits.co.uk/international/england/england-1960-1983.html&quot;,
  &quot;http://www.historicalkits.co.uk/international/england/england-1984-1997.html&quot;,
  &quot;http://www.historicalkits.co.uk/international/england/england-1997-2010.html&quot;,
  &quot;http://www.historicalkits.co.uk/international/england/england-2010-2019.html&quot;
) %>%
  map(read_html)</code></pre>
<p>From the source code we can then find the URLs of each kit image files using <code>html_nodes()</code> and <code>html_attr()</code> from <a rel="nofollow" href="https://cran.r-project.org/web/packages/rvest/" target="_blank">rvest</a>. I used purrr’s <code>map_dfr()</code> to store the links in a tibble and then dropped rows that do not contain kit image links or are images of away kits, kits used in single game or links to shops to buy replicas. This filtering was based on the image label or image URL and performed with the aid of the <code>str_detect()</code> function from <a rel="nofollow" href="https://cran.r-project.org/web/packages/stringr/" target="_blank">stringr</a>.</p>
<pre><code>library(stringr)

scrape_img_url &lt;- function(html){
  html %>%
    html_nodes(&quot;.float p , .float img&quot;) %>%
    html_attr(&quot;src&quot;) %>%
    tbl_df() %>%
    set_names(&quot;img_url&quot;) %>%
    mutate(label = html %>% 
             html_nodes(&quot;.float p , .float img&quot;) %>%
             html_text() %>%
             c(., NA) %>%
             .[-1])
}

d1 &lt;- htmls %>% 
  map_dfr(scrape_img_url) %>%
  filter(str_detect(string = img_url, pattern = &quot;/international/england&quot;),
         !str_detect(string = label, pattern = &quot;change|alternate|Alternate|Change&quot;),
         !str_detect(string = label, pattern = &quot; v |Third&quot;),
         !str_detect(string = img_url, pattern = &quot;lithuania|italy|yellow|red&quot;))</code></pre>
<pre><code>head(d1)</code></pre>
<pre><code>##                                               img_url     label
## 1      /international/england/images/england-1872.gif      1872
## 2      /international/england/images/england-1882.gif 1879-1900
## 3      /international/england/images/england-1900.gif 1900-1914
## 4 /international/england/images/england-1920-1932.gif 1920-1930
## 5      /international/england/images/england-1921.gif 1930-1934
## 6      /international/england/images/england-1934.gif      1934</code></pre>
<p>Given these URLs I then downloaded each of the images which are stored in a single R object <code>kits</code></p>
<pre><code>library(magick)

kits &lt;- d1 %>%
  mutate(img_url = paste0(&quot;http://www.historicalkits.co.uk&quot;, img_url),
         img_url = str_replace(string =img_url, pattern =&quot; &quot;, replacement = &quot;%20&quot;)) %>%
  select(img_url) %>%
  map(image_read) %>%
  set_names(&quot;img&quot;)</code></pre>
<p>Typing <code>kits</code> into R will display each kit in the RStudio viewer (it will quickly run through each image). The console displays summary information for each image in the <code>kits</code> object.</p>
<pre><code>> kits
$img
   format width height colorspace filesize
1     GIF   170    338       sRGB        0
2     GIF   170    338       sRGB        0
3     GIF   170    338       sRGB        0
4     GIF   170    338       sRGB        0
5     GIF   170    338       sRGB        0
6     GIF   170    338       sRGB        0
7     GIF   170    338       sRGB        0
8     GIF   170    338       sRGB        0
9     GIF   170    338       sRGB        0
10    GIF   170    338       sRGB        0</code></pre>
</div>
<div>
<h2>Annotating Images</h2>
<p>Before creating any GIF I wanted add annotations for the year and the copyright information. To do this I first created a border using <code>image_border()</code> in magick and then <code>image_annotate()</code> to add the text. I wrapped these edits into an <code>add_text()</code> function and then applied each to the kit images.</p>
<pre><code>add_text &lt;- function(img, label){
  img %>%
    image_border(geometry = &quot;10x60&quot;, color = &quot;white&quot;) %>%
    image_chop(&quot;0x45&quot;) %>%
    image_annotate(text = label, gravity = &quot;north&quot;) %>%
    image_annotate(
      text = &quot;Animation by @guyabelguyabel&quot;, gravity = &quot;south&quot;, location = &quot;+0+45&quot;
    ) %>%
    image_annotate(
      text = &quot;Images are Copyright of Historical\nFootball Kits and reproduced by\nkind permission.&quot;,
      gravity = &quot;south&quot;
    )
}

for(i in 1:length(kits$img)){
  kits$img[i] &lt;- add_text(img = kits$img[i], label = d1$label[i])
}</code></pre>
</div>
<div>
<h2>Creating a GIF</h2>
<p>The final step was to bind together the set of images in an animated GIF with smooth transition images between each frame. To do this I used the <code>image_morph()</code> twice. First to repeat the same image so that the GIF would remain stable for a few frames (<code>kits_morph1</code> below). Then again to create a set of morphing images between successive kits (<code>kits_morph0</code> below). The full set of frames were stored in <code>kits_ani</code></p>
<pre><code>kits_ani &lt;- image_morph(c(kits$img[1], kits$img[1]), frames = 5)
for(i in 2:length(kits$img)){
  kits_morph0 &lt;- image_morph(c(kits$img[i-1], kits$img[i]), frames = 5)
  kits_morph1 &lt;- image_morph(c(kits$img[i], kits$img[i]), frames = 5)
  kits_ani &lt;- c(kits_ani, kits_morph0)
  kits_ani &lt;- c(kits_ani, kits_morph1)
}</code></pre>
<p>To create an animation I passed the set of frames in the <code>kits_morph</code> object to the <code>image_animate()</code> and <code>image_write()</code> functions to give the image above.</p>
<pre><code>kits_ani %>%
  image_animate(fps = 10) %>%
  image_write(path = &quot;england.gif&quot;)</code></pre>
</div>
<div>
<h2>Club Teams</h2>
<p>Similar code as above can be used to create images for club teams. I tried this out for the mighty Reading. As the Reading kits on <a rel="nofollow" href="http://www.historicalkits.co.uk/Reading/Reading.htm" target="_blank">Historical Football Kits</a> are on only one page and includes only home kits, finding the image URLs was much easier…</p>
<pre><code>d1 &lt;- read_html(&quot;http://www.historicalkits.co.uk/Reading/Reading.htm&quot;) %>%
  scrape_img_url() %>%
  filter(str_detect(string = img_url, pattern = &quot;/Reading&quot;),
         !str_detect(string = img_url, pattern = &quot;unknown&quot;)) %>%
  mutate(
    label = str_replace_all(string = label,
                            pattern = &quot;[:alpha:]|\\s&quot;, 
                            replacement = &quot;&quot;)
  )</code></pre>
<p>I could then run the same code as above to scrape the images, annotate the year and copyright information and build the GIF.</p>
<div>
<img src="https://i0.wp.com/guyabel.com/img/abel-reading.gif?w=456&ssl=1" data-recalc-dims="1">
</div>
<p>Ian Holloway – <a rel="nofollow" href="https://www.getreading.co.uk/news/reading-berkshire-news/sky-sports-pundit-ian-holloway-12023342" target="_blank">we had hoops first</a>.</p>
<p>I did have trouble creating a GIF’s when I used more frames to morph images between successive kits, for example when using <code>frames = 10</code>. I could not consistently replicate the error, but I suspect it is something related to the memory size – my R session would freeze when passing <code>image_animate()</code> or <code>image_write()</code> on the <code>kits_ani</code> R object when it contained a large number of images.</p>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://guyabel.com/post/football-kits/"> R-bloggers on Guy Abel</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/nTdY-lq_YxI" height="1"></a></div>