<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/some-fun-with-gganimate/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.brodrigues.co/blog/2018-12-27-fun_gganimate/"> Econometrics and Free Software</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<div>
<video width="450" controls><source type="video/webm" src="https://www.r-bloggers.com/some-fun-with-gganimate/img/wiid_gganimate.webm">Your browser does not support the video tag.</video>
</div>
<p>In this short blog post I show you how you can use the <code>{gganimate}</code> package to create animations<br>
from <code>{ggplot2}</code> graphs with data from UNU-WIDER.</p>
<div>
<h2>WIID data</h2>
<p>Just before Christmas, UNU-WIDER released a new edition of their World Income Inequality Database:</p>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">*NEW <a rel="nofollow" href="https://twitter.com/hashtag/DATA?src=hash&ref_src=twsrc%5Etfw" target="_blank">#DATA</a>*<br>We’ve just released a new version of the World Income Inequality Database.<br>WIID4 includes <a rel="nofollow" href="https://twitter.com/hashtag/data?src=hash&ref_src=twsrc%5Etfw" target="_blank">#data</a> from 7 new countries, now totalling 189, and reaches the year 2017. All data is freely available for download on our website: <a rel="nofollow" href="https://t.co/XFxuLvyKTC" target="_blank">https://t.co/XFxuLvyKTC</a> <a rel="nofollow" href="https://t.co/rCf9eXN8D5" target="_blank">pic.twitter.com/rCf9eXN8D5</a></p>
<p>— UNU-WIDER (@UNUWIDER) <a rel="nofollow" href="https://twitter.com/UNUWIDER/status/1076001879556005888?ref_src=twsrc%5Etfw" target="_blank">December 21, 2018</a></p></blockquote>
<p></p>
<p>The data is available in Excel and STATA formats, and I thought it was a great opportunity to<br>
release it as an R package. You can install it with:</p>
<pre><code>devtools::install_github(&quot;b-rodrigues/wiid4&quot;)</code></pre>
<p>Here a short description of the data, taken from UNU-WIDER’s website:</p>
<p><em>“The World Income Inequality Database (WIID) presents information on income inequality for<br>
developed, developing, and transition countries. It provides the most comprehensive set of income<br>
inequality statistics available and can be downloaded for free.</em></p>
<p><em>WIID4, released in December 2018, covers 189 countries (including historical entities), with over<br>
11,000 data points in total. With the current version, the latest observations now reach the year 2017.”</em></p>
<p>It was also a good opportunity to play around with the <code>{gganimate}</code> package. This package<br>
makes it possible to create animations and is an extension to <code>{ggplot2}</code>. Read more about it<br>
<a rel="nofollow" href="https://github.com/thomasp85/gganimate" target="_blank">here</a>.</p>
</div>
<div>
<h2>Preparing the data</h2>
<p>To create a smooth animation, I need to have a cylindrical panel data set; meaning that for each<br>
country in the data set, there are no missing years. I also chose to focus on certain variables<br>
only; net income, all the population of the country (instead of just focusing on the economically<br>
active for instance) as well as all the country itself (and not just the rural areas).<br>
On <a rel="nofollow" href="https://www.wider.unu.edu/sites/default/files/WIID/PDF/WIID4%20User%20Guide.pdf" target="_blank">this link</a> you<br>
can find a codebook (pdf warning), so you can understand the filters I defined below better.</p>
<p>Let’s first load the packages, data and perform the necessary transformations:</p>
<pre><code>library(wiid4)
library(tidyverse)
library(ggrepel)
library(gganimate)
library(brotools)

small_wiid4 &lt;- wiid4 %>%
    mutate(eu = as.character(eu)) %>%
    mutate(eu = case_when(eu == &quot;1&quot; ~ &quot;EU member state&quot;,
                          eu == &quot;0&quot; ~ &quot;Non-EU member state&quot;)) %>%
    filter(resource == 1, popcovr == 1, areacovr == 1, scale == 2) %>%
    group_by(country) %>%
    group_by(country, year) %>%
    filter(quality_score == max(quality_score)) %>%
    filter(source == min(source)) %>%
    filter(!is.na(bottom5)) %>%
    group_by(country) %>%
    mutate(flag = ifelse(all(seq(2004, 2016) %in% year), 1, 0)) %>%
    filter(flag == 1, year > 2003) %>%
    mutate(year = lubridate::ymd(paste0(year, &quot;-01-01&quot;)))</code></pre>
<p>For some country and some years, there are several sources of data with varying quality. I only<br>
keep the highest quality sources with:</p>
<pre><code>    group_by(country, year) %>%
    filter(quality_score == max(quality_score)) %>%</code></pre>
<p>If there are different sources of equal quality, I give priority to the sources that are the most<br>
comparable across country (Luxembourg Income Study, LIS data) to less comparable sources with<br>
(at least that’s my understanding of the <code>source</code> variable):</p>
<pre><code>    filter(source == min(source)) %>%</code></pre>
<p>I then remove missing data with:</p>
<pre><code>    filter(!is.na(bottom5)) %>%</code></pre>
<p><code>bottom5</code> and <code>top5</code> give the share of income that is controlled by the bottom 5% and top 5%<br>
respectively. These are the variables that I want to plot.</p>
<p>Finally I keep the years 2004 to 2016, without any interruption with the following line:</p>
<pre><code>    mutate(flag = ifelse(all(seq(2004, 2016) %in% year), 1, 0)) %>%
    filter(flag == 1, year > 2003) %>%</code></pre>
<p><code>ifelse(all(seq(2004, 2016) %in% year), 1, 0))</code> creates a flag that equals <code>1</code> only if the years<br>
2004 to 2016 are present in the data without any interruption. Then I only keep the data from 2004<br>
on and only where the flag variable equals 1.</p>
<p>In the end, I ended up only with European countries. It would have been interesting to have countries<br>
from other continents, but apparently only European countries provide data in an annual basis.</p>
</div>
<div>
<h2>Creating the animation</h2>
<p>To create the animation I first started by creating a static ggplot showing what I wanted;<br>
a scatter plot of the income by bottom and top 5%. The size of the bubbles should be proportional<br>
to the GDP of the country (another variable provided in the data). Once the plot looked how I wanted<br>
I added the lines that are specific to <code>{gganimate}</code>:</p>
<pre><code>    labs(title = 'Year: {frame_time}', x = 'Top 5', y = 'Bottom 5') +
    transition_time(year) +
    ease_aes('linear')</code></pre>
<p>I took this from <code>{gganimate}</code>’s README.</p>
<pre><code>animation &lt;- ggplot(small_wiid4) +
    geom_point(aes(y = bottom5, x = top5, colour = eu, size = log(gdp_ppp_pc_usd2011))) +
    xlim(c(10, 20)) +
    geom_label_repel(aes(y = bottom5, x = top5, label = country), hjust = 1, nudge_x = 20) +
    theme(legend.position = &quot;bottom&quot;) +
    theme_blog() +
    scale_color_blog() +
    labs(title = 'Year: {frame_time}', x = 'Top 5', y = 'Bottom 5') +
    transition_time(year) +
    ease_aes('linear')</code></pre>
<p>I use <code>geom_label_repel</code> to place the countries’ labels on the right of the plot. If I don’t do<br>
this, the labels of the countries would be floating around and the animation would be unreadable.</p>
<p>I then spent some time trying to render a nice webm instead of a gif. It took some trial and error<br>
and I am still not entirely satisfied with the result, but here is the code to render the animation:</p>
<pre><code>animate(animation, renderer = ffmpeg_renderer(options = list(s = &quot;864x480&quot;, 
                                                             vcodec = &quot;libvpx-vp9&quot;,
                                                             crf = &quot;15&quot;,
                                                             b = &quot;1600k&quot;, 
                                                             vf = &quot;setpts=5*PTS&quot;)))</code></pre>
<p>The option <code>vf = &quot;setpts=5*PTS&quot;</code> is important because it slows the video down, so we can actually<br>
see something. <code>crf = &quot;15&quot;</code> is the quality of the video (lower is better), <code>b = &quot;1600k&quot;</code> is the<br>
bitrate, and <code>vcodec = &quot;libvpx-vp9&quot;</code> is the codec I use. The video you saw at the top of this<br>
post is the result. You can also find the video <a rel="nofollow" href="https://raw.githubusercontent.com/rbind/b-rodrigues.github.com/master/static/img/wiid_gganimate.webm" target="_blank">here</a>,<br>
and here’s a gif if all else fails:</p>
<div>
<p><a rel="nofollow" href="https://www.youtube.com/watch?v=3zXx0ReqOOI" target="_blank"><br>
<img title="Click to listen to OST of this gif" src="https://i1.wp.com/www.brodrigues.co/blog/2018-12-27-fun_gganimate/img/wiid_gganimate_gif.gif?w=456" data-recalc-dims="1"></a></p>
</div>
<p>I would have preferred if the video was smoother, which should be possible by creating more frames.<br>
I did not find such an option in <code>{gganimate}</code>, and perhaps there is none, at least for now.</p>
<p>In any case <code>{gganimate}</code> is pretty nice to play with, and I’ll definitely use it more!</p>
<div>
<h3>Update</h3>
<p>Silly me! It turns out thate the <code>animate()</code> function has arguments that can control the number of frames<br>
and the duration, without needing to pass options to the renderer. I was looking at options for the<br>
renderer only, without having read the documentation of the <code>animate()</code> function. It turns out that<br>
you can pass several arguments to the <code>animate()</code> function; for example, here is how you<br>
can make a GIF that lasts for 20 seconds running and 20 frames per second, pausing for 5<br>
frames at the end and then restarting:</p>
<pre><code>animate(animation, nframes = 400, duration = 20, fps = 20, end_pause = 5, rewind = TRUE)</code></pre>
<p>I guess that you should only pass options to the renderer if you really need fine-grained control.</p>
<p>This took around 2 minutes to finish. You can use the same options with the ffmpeg renderer too.<br>
Here is what the gif looks like:</p>
<div>
<p><a rel="nofollow" href="https://www.youtube.com/watch?v=3zXx0ReqOOI" target="_blank"><br>
<img title="Click to listen to OST of this gif" src="https://i1.wp.com/www.brodrigues.co/blog/2018-12-27-fun_gganimate/img/wiid_gganimate_gif_smooth.gif?w=456" data-recalc-dims="1"></a></p>
</div>
<p>Much, much smoother!</p>
<p>Hope you enjoyed! If you found this blog post useful, you might want to follow<br>
me on <a rel="nofollow" href="https://www.twitter.com/brodriguesco" target="_blank">twitter</a> for blog post updates and<br>
<a rel="nofollow" href="https://www.buymeacoffee.com/brodriguesco" target="_blank">buy me an espresso</a> or <a rel="nofollow" href="http://www.brodrigues.co/blog/2018-12-27-fun_gganimate/paypal.me/brodriguesco" target="_blank">paypal.me</a>.</p>

<a rel="nofollow" href="https://www.buymeacoffee.com/brodriguesco" target="_blank"><img alt="Buy me an Espresso" src="https://www.buymeacoffee.com/assets/img/BMC-btn-logo.svg"><span>Buy me an Espresso</span></a>
</div>
</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="http://www.brodrigues.co/blog/2018-12-27-fun_gganimate/"> Econometrics and Free Software</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/8Ce-2hd5SiQ" height="1"></a></div>