I'd like to create an animation in beamer using the knitr package and the chunk option fig.show='animate'
with the figures being overlayed rather than replaced similar to how \multiinclude works by default.
A minimal non-working example would be the following (Rnw file) where I'd like each point to be added one-by-one to the existing plot in the animation.
\documentclass{beamer}
\usepackage{animate}
\begin{document}
\begin{frame}[fragile]
<<fig.show='animate', fig.width=5, fig.height=5, size='tiny', out.width='.8\\linewidth', fig.align='center', echo=FALSE>>=
x = 1:2
plot(x,x,type="n")
for (i in 1:length(x)) {
points(x[i],x[i])
}
@
\end{frame}
\end{document}
From looking at the knitr graphics manual, it states the two sources of plots are plot.new()
and grid.newpage()
, but has a footnote to see ?recordPlot
. So I tried putting recordPlot()
after the points
command (and also adding a transparent background via par(bg=NA)
, but this did not work as only a single plot is created.
A minimal working example is the following
\documentclass{beamer}
\usepackage{animate}
\begin{document}
\begin{frame}[fragile]
<<fig.show='animate', fig.width=5, fig.height=5, size='tiny', out.width='.8\\linewidth', fig.align='center', echo=FALSE, fig.keep='all'>>=
x = 1:2
plot(x,x,type="n")
for (i in 1:length(x)) {
for (j in 1:i) points(x[j],x[j])
}
@
\end{frame}
\end{document}
but this seems like overkill since each figure redraws the plot and all the preceding points.
Is there some way to get rid of the loop over j
? or some other way to overlay plots in beamer/knitr? If yes, how can my code above be modified to make that happen?
As explained the graphics manual, only plots from high-level plotting commands (e.g. plot.new()
) and complete expressions are recorded. That means if you have multiple low-level plot changes in a for-loop, these changes will not be recorded one by one, because the for-loop in only one R expression. That is what Figure 4 in the manual illustrates.
If you want to create an animation from a for-loop, there must be high-level plotting commands in the loop. Figure 7 in the manual is such an example.
In your case, you have to move the plot()
call into the loop:
x = 1:2
for (i in 1:length(x)) {
plot(x, x, type = "n")
points(x[1:i], x[1:i])
}
Yes, this looks like a serious waste of resource, and the "natural" way should be adding points one by one as you did, instead of opening a new plot and drawing points from 1
to i
, but there is no way to detect low-level graphical changes inside a single R expression.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With