gganimate 中有许多(> 50)状态的问题

Problem with many (>50) states in gganimate

我正在尝试使用 gganimate 为涵盖 90 年的数据集创建一个 GIF,即我想要一个 运行 到 90 states/years 的 GIF。但是,似乎 gganimate 只能处理不到 50 个状态。

下面是一个例子:

library(tidyverse)
# devtools::install_github('thomasp85/gganimate')
library(gganimate)

df = expand.grid(  x = 1,
                   y = c(2,3),
                year = 1670:1760) %>% mutate( z = 0.03* year,
                                              u = .2 * year)

49 年来一切正常:

ggplot(data=df %>% filter(., year %in% 1670:1719) , aes()) + 
  geom_point( aes(x = x, y = y, fill = z, size = u), shape = 21 ) + 
  labs( title = 'Year: {closest_state}') +
  enter_appear() +
  transition_states(year, transition_length = 1, state_length = 2) 

然而,当我包括 50(或更多)年时,它变得很奇怪:

ggplot(data=df %>% filter(., year %in% 1670:1720) , aes()) + 
  geom_point( aes(x = x, y = y, fill = z, size = u), shape = 21 ) + 
  labs( title = 'Year: {closest_state}') +
  enter_appear() +
  transition_states(year, transition_length = 1, state_length = 2) 

我怎样才能创建一个 90 年的 GIF?欢迎任何想法!
我还是 gganimate 的新手,我是不是用错了 transition_states

这与 gganmiate 使用固定数量的 100 帧动画有关。对于最多 50 年(请注意 1670:1719 的长度为 50,而不是 49),这没问题,但如果你想绘制更多年,则需要更多帧。您可以通过显式调用 animate() 来控制帧数。

对于您的示例,这意味着您应该首先将绘图存储在一个变量中:

p <- ggplot(df) + 
      geom_point(aes(x = x, y = y, fill = z, size = u), shape = 21) + 
      labs( title = 'Year: {closest_state}') +
      enter_appear() +
      transition_states(year, transition_length = 1, state_length = 2)

然后您可以通过键入以下任一命令来启动动画

p
animate(p)
animate(p, nframes = 100)

这三行是等价的。第一个是您在示例中所做的:这将隐式调用 animate() 来渲染动画。第二行显式调用 animate(),第三行还显式地将帧数设置为 100。由于 nframes = 100 是默认值,因此最后一行也与其他行相同。

为了使动画正常工作,您需要设置更高的帧数。 100 帧可以使用 50 年,因此 182 帧应该可以在您的完整数据框中使用 91 年。同样,以下两行是相同的:

animate(p, nframes = 182)
animate(p, nframes = 2 * length(unique(df$year)))

现在可以使用了:

我不确定为什么你需要两倍的帧数,但在阅读 transition_states()

文档中的以下声明后

It then tweens between the defined states and pauses at each state.

我猜一帧用来表示两年之间的过渡,一帧用来表示给定年份的日期。

这意味着您实际上需要的帧少于年数的两倍,因为去年之后的过渡不需要帧。实际上,gganimate()nframes = 100nframes = 182 的输出分别是:

Frame 99 (100%)
Finalizing encoding... done!

Frame 181 (100%)
Finalizing encoding... done!

所以如果我的猜测是正确的,它确实创建了预期的帧数。