<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/the-tweenr-is-all-grown-up/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/"> Data Imaginist</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img align="right" src="https://i2.wp.com/www.data-imaginist.com/assets/images/tweenr_logo_small.png?w=456&ssl=1" data-recalc-dims="1"></p>
<blockquote>
<p>NOTE: tweenr was released some time ago but a theft of my computer while<br>
writing the release post meant that I only just finished writing about it now.</p>
</blockquote>
<p>I’m very happy to once again announce a package update, as a new major version<br>
of <code>tweenr</code> is now on CRAN. This release, while significant in itself, is also<br>
an important part of getting <code>gganimate</code> on CRAN, so if you care about<br>
<code>gganimate</code> but have never heard of <code>tweenr</code> you should be happy nonetheless.</p>
<p><code>tweenr</code> was my first sort-of popular package and filled a gap in the gganimate<br>
version of yore, where smooth transitions were something you had to bring<br>
yourself. It has lived almost unchanged since its initial release, but as I<br>
began to develop the next iteration of <code>gganimate</code> it became clear that new<br>
functionality was needed. Some of it ended up in the<br>
<a rel="nofollow" href="https://github.com/thomasp85/transformr" target="_blank"><code>transformr</code></a> but a huge chunk has<br>
been added to tweenr itself. A description of everything new follows below.</p>
<div>
<h2>Something new, something old {new_old}</h2>
<p>The main API of the previous version of <code>tweenr</code> comprised of the<br>
<code>tween_states()</code>, <code>tween_elements()</code>, and <code>tween_appear()</code>. All of these needed<br>
serious change in both capabilities and API to the extend that all prior code<br>
would break, so instead I decided to keep the old functions unchanged and create<br>
new ones for a brighter future.</p>
<div>
<h3>tween_states ⇒ tween_state/keep_state</h3>
<p><code>tween_states()</code> was perhaps the most used of the old functions. It takes a list<br>
of data.frames and a specification of how long transitions between them should<br>
take and how long it should pause at each data.frame. This is perfect for<br>
situations where you have discrete states and want to have a smooth transition<br>
between them. Still it had certain shortcomings, such as requiring that each<br>
data.frame included the same number of rows etc. (meaning that each “element”<br>
should be present in each state). Further I have ended up finding it a bit<br>
clumsy to use. The new function(s) that should serve the same needs as<br>
<code>tween_states()</code> is <code>tween_state()</code> (and <code>keep_state()</code>) and they are much more<br>
powerful. The biggest difference, perhaps, is that <code>tween_state()</code> only takes a<br>
<em>from</em> and <em>to</em> state and not an arbitrarily long list of states. If transitions<br>
are needed between more states you’ll need to chain calls together (potentially<br>
with <code>keep_state()</code> if the state should pause between transitions). It will<br>
something like this:</p>
<pre><code>library(tweenr)
irises &lt;- split(iris, iris$Species)
iris_tween &lt;- irises$setosa %>% 
  tween_state(irises$versicolor, ease = 'cubic-in-out', nframes = 10) %>% 
  keep_state(5) %>% 
  tween_state(irises$virginica, ease = 'linear', nframes = 15) %>% 
  keep_state(5)</code></pre>
<p>As can be seen, if you like piping you’ll feel right at home. Apart from the<br>
seemingly superficial change in API, the <code>tween_state()</code> also packs some new<br>
tricks. One of these is per-column easing, so you can specify different easing<br>
functions for different variables. Another, more fundamental one, is the<br>
possibility of specifying an id to match rows by. Ultimately this means that<br>
rows no longer needs to be matched by position and that you can now tween<br>
between states with different numbers of elements. All of this is so important<br>
that it will get its own section later on in <a rel="nofollow" href="https://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/#enter-and-exit" target="_blank">Enter and Exit</a>.</p>
</div>
<div>
<h3>tween_elements ⇒ tween_components</h3>
<p>While <code>tween_states()</code> was probably the most used of the legacy functions it was<br>
by no means the only one. <code>tween_elements()</code> was a very powerful function that<br>
let you specify different individual states for each element in a single<br>
data.frame and then expand this to an arbitrary number of frames. The changes<br>
that its hier bring is less dramatic than what happened with <code>tween_states()</code>,<br>
and simply adds the same features that <code>tween_state()</code> introduced. This means<br>
per-column easing and the same features as described below in<br>
<a rel="nofollow" href="https://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/#enter-and-exit" target="_blank">Enter and Exit</a>. Further it changes the semantics of a couple of<br>
variables so they are now tidy evaluated. This means that state specifications<br>
can be calculated on the fly, rather than having to exist inside the data.frame<br>
to be tweened.</p>
</div>
<div>
<h3>tween_appear ⇒ tween_events</h3>
<p><code>tween_appear()</code> never really felt right. The purpose was to let each row appear<br>
in a specific frame while still allowing the user to define how it should<br>
appear. To this end it expanded the data.frame by giving each row an <em>age</em> in<br>
each frame (negative age meant that it had yet to appear) and then let the user<br>
do with this as they pleased. What was missing was the whole idea of<br>
<a rel="nofollow" href="https://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/#enter-and-exit" target="_blank">Enter and Exit</a> which I have already plugged multiple times.<br>
<code>tween_event()</code> is a pretty radical change in order to solve the problem that<br>
<code>tween_appear()</code> originally tried (but failed) to solve.</p>
</div>
</div>
<div>
<h2>Enter and Exit</h2>
<p>Before we go any further with other new tweening functions I think I owe it to<br>
you to describe what all this entering and exiting I’ve been talking about<br>
really is. If you have dabbled in D3.js the two words will be familiar but they<br>
have slightly different meaning in <code>tweenr</code>. In D3 enter and exit describe a<br>
selection of data that did not match in a data join between current and next<br>
state, while in tweenr it is a function that modifies data that is going to<br>
appear or disappear. If enter and/or exit is not given, the data will just pop<br>
into existence in the first frame it relates to and disappear without a trace<br>
after the last frame it relates to has ended. if you provide e.g. an enter<br>
function this will be applied to all elements when they first appear. The result<br>
of the function will then be inserted into the tweening prior to the original<br>
data so that any changes the function does will gradually change to the original<br>
data. This may sound quite confusing, but in essence it means that if you pass<br>
in an enter function that sets the transparancy variable to zero you’ll get a<br>
gradual fade-in effect. The exit function is just like it, but in reverse. But<br>
let’s see it in effect instead:</p>
<pre><code>df1 &lt;- data.frame(x = 1:2, y = 2, alpha = 1) # 2 rows
df2 &lt;- data.frame(x = 2:0, y = 1, alpha = 1) # 3 rows

fade &lt;- function(data) {
  data$alpha &lt;- 0
  data
}

tween &lt;- tween_state(df1, df2, ease = 'linear', nframes = 5, enter = fade)

tween$alpha[tween$.id == 3]</code></pre>
<pre><code>## [1] 0.25 0.50 0.75 1.00</code></pre>
<p>We can see that the alpha value of the third element (the one that doesn’t exist<br>
in the first state) gradually increase from zero to one. The reason why 0 isn’t<br>
included is that the enter and exit function return virtual states that doens’t<br>
remain in the data – only the transition to and from them does.</p>
</div>
<div>
<h2>New tweens on the block</h2>
<p>Appart from the new versions of the old functionality discussed <a rel="nofollow" href="https://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/#new_old" target="_blank">above</a><br>
this version also includes some brand new tweens, mainly implemented to serve<br>
needs in <code>gganimate</code> but of course also available for everyone else.</p>
<div>
<h3>tween_along</h3>
<p>This is the tweening function that powers <code>transition_reveal()</code> in <code>gganimate</code> –<br>
if you have played with that you are fairly well situated to understand what it<br>
does. In essence it allows you to specify time points for the different rows in<br>
your data.frame and then tween between these. You might think that this is<br>
exactly what <code>tween_components()</code> does and you’d partly be right. The big<br>
difference is that <code>tween_along()</code> ensures equidistant frames, whereas<br>
<code>tween_components()</code> assigns all rows in the data to the nearest frame and then<br>
use the frame as a time variable. The latter will always have the raw data<br>
appearing in one frame or another while the former will not. Further,<br>
<code>tween_along()</code> will optionally keep earlier rows in your data at each frame,<br>
which is useful if you e.g. want a line to gradually appear along an axis.</p>
</div>
<div>
<h3>tween_at</h3>
<p>This is a pretty low level tweening function intened to get an exact state<br>
between two data frames or vectors. It takes two states and a numeric vector<br>
giving the tween position for each row and then calculates the intermediary<br>
rows.</p>
<pre><code>tween_at(mtcars[1:3, ], mtcars[4:6, ], runif(3), 'linear')</code></pre>
<pre><code>##        mpg      cyl     disp       hp     drat       wt     qsec        vs
## 1 21.27039 6.000000 226.2455 110.0000 3.345701 3.022205 18.47440 0.6759747
## 2 20.51284 6.423621 202.3621 123.7677 3.741142 2.994673 17.02000 0.0000000
## 3 19.77526 5.287121 183.2966 100.7227 3.148519 3.053659 19.64613 1.0000000
##          am     gear     carb
## 1 0.3240253 3.324025 1.972076
## 2 0.7881894 3.788189 3.576379
## 3 0.3564393 3.356439 1.000000</code></pre>
<p>This is unlikely to be useful for directly creating animations (though I guess<br>
it is low-level enough to be able to be shoehorned into anything). It is being<br>
used in <code>gganimate</code> for calculating shadow falloff in <code>shadow_wake()</code>.</p>
</div>
<div>
<h3>tween_fill</h3>
<p>This tween takes a page out of <code>tidyr::fill</code> and simply fill out missing<br>
elements in a data frame or vector. Instead of being boring and repeating the<br>
prior or following data it doesn the <code>tweenr</code> thing and tweens between them:</p>
<pre><code>mtcars2 &lt;- mtcars[1:7, ]
mtcars2[2:6, ] &lt;- NA

tween_fill(mtcars2, 'cubic-in-out')</code></pre>
<pre><code>##        mpg      cyl     disp    hp     drat       wt     qsec vs
## 1 21.00000 6.000000 160.0000 110.0 3.900000 2.620000 16.46000  0
## 2 20.87593 6.037037 163.7037 112.5 3.887222 2.637593 16.44852  0
## 3 20.00741 6.296296 189.6296 130.0 3.797778 2.760741 16.36815  0
## 4 17.65000 7.000000 260.0000 177.5 3.555000 3.095000 16.15000  0
## 5 15.29259 7.703704 330.3704 225.0 3.312222 3.429259 15.93185  0
## 6 14.42407 7.962963 356.2963 242.5 3.222778 3.552407 15.85148  0
## 7 14.30000 8.000000 360.0000 245.0 3.210000 3.570000 15.84000  0
##           am     gear carb
## 1 1.00000000 4.000000    4
## 2 0.98148148 3.981481    4
## 3 0.85185185 3.851852    4
## 4 0.50000000 3.500000    4
## 5 0.14814815 3.148148    4
## 6 0.01851852 3.018519    4
## 7 0.00000000 3.000000    4</code></pre>
<p>Neat-o…</p>
</div>
</div>
<div>
<h2>Grab bag of niceties</h2>
<p>There are more subtle additions to <code>tweenr</code> as well, most of which has also been<br>
driven by <code>gganimate</code> needs. Here’s an unceremonious list:</p>
<ul>
<li><em>More information:</em> In olden days <code>tweenr</code> simply added a <code>.frame</code> column to<br>
the output to identify the frame the row belonged to. It still does, but that<br>
column is now accompagnied by a <code>.phase</code> column that tells if the data is raw,<br>
static, entering, exiting, or transitioning, and an <code>.id</code> column that identifies<br>
the same data across frames.</li>
<li><em>More support:</em> The supported data types has been expanded considerably. Most<br>
notably list columns are now accepted. If the list only contains numeric vectors<br>
these vectors will get tweened accordingly, and if not the list will be treated<br>
as constant.</li>
<li><em>Better colour support:</em> Colour has always been tweened in the LAB<br>
representation to get a more natural transition. In the old version the native<br>
<code>convertColor()</code> function was used, but this could lead to substantial slowdown<br>
when tweening lots of data. To address this <code>farver</code> was developed and released<br>
and this version of <code>tweenr</code> naturally uses this for colour space conversions<br>
now. In addition, <code>tweenr</code> now supports hex-colours with alpha.</li>
</ul>
<p>I think that is it, but frankly there has been so many additions that I may have<br>
missed a few… First to find something I missed gets a sticker!</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://www.data-imaginist.com/2018/the-tweenr-is-all-grown-up/"> Data Imaginist</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/l0evnVM-ArQ" height="1"></a></div>