使用knitr在beamer中叠加动画

时间:2021-02-03 19:27:36

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.

我想使用knitr包和chunk选项fig.show ='animate'在beamer中创建一个动画,其中数字被覆盖而不是替换类似于\ multiinclude默认情况下的工作方式。

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.

一个最小的非工作示例将是以下(Rnw文件),我希望每个点一个接一个地添加到动画中的现有绘图。

\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.

通过查看knitr图形手册,它说明了两个图的来源是plot.new()和grid.newpage(),但有一个脚注可以看到?recordPlot。所以我尝试在points命令之后放置recordPlot()(并且还通过par(bg = NA)添加透明背景,但这不起作用,因为只创建了一个绘图。

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?

有没有办法摆脱j的循环?或者其他一些在beamer / knitr中叠加图的方法?如果是,我的代码如何修改以实现这一目标?

1 个解决方案

#1


4  

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.

如图形手册所述,仅记录来自高级绘图命令(例如plot.new())和完整表达式的图。这意味着如果在for循环中有多个低级绘图更改,则不会逐个记录这些更改,因为for循环只在一个R表达式中。这就是手册中的图4所示。

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.

如果要从for循环创建动画,则循环中必须有高级绘图命令。手册中的图7就是这样一个例子。

In your case, you have to move the plot() call into the loop:

在您的情况下,您必须将plot()调用移动到循环中:

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.

是的,这看起来像是一种严重的资源浪费,而“自然”方式应该像你一样逐一添加点,而不是打开一个新的情节并从1到i绘制点,但是没有办法检测到低单个R表达式中的级别图形更改。

#1


4  

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.

如图形手册所述,仅记录来自高级绘图命令(例如plot.new())和完整表达式的图。这意味着如果在for循环中有多个低级绘图更改,则不会逐个记录这些更改,因为for循环只在一个R表达式中。这就是手册中的图4所示。

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.

如果要从for循环创建动画,则循环中必须有高级绘图命令。手册中的图7就是这样一个例子。

In your case, you have to move the plot() call into the loop:

在您的情况下,您必须将plot()调用移动到循环中:

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.

是的,这看起来像是一种严重的资源浪费,而“自然”方式应该像你一样逐一添加点,而不是打开一个新的情节并从1到i绘制点,但是没有办法检测到低单个R表达式中的级别图形更改。