【问题标题】:Animated plot with a moving facet zoom via gganimate and ggforce?通过 gganimate 和 ggforce 移动平面缩放的动画情节?
【发布时间】:2019-03-22 09:28:39
【问题描述】:

目标

我想放大Europe 这些年来的 GDP。梦幻般的ggforce::facet_zoom 可以很容易地为静态图(即特定年份)提供此功能。

然而,事实证明,移动秤比预期的要难。 gganimate 似乎从第一帧 (year == 1952) 开始采用 x 轴限制,并一直持续到动画结束。 This related, but code-wise outdated question did not yield an answer, unfortunately+ coord_cartesian(xlim = c(from, to))facet_zoom(xlim = c(from, to)) 似乎都无法影响 facet_zoom 窗口超出静态限制。

  • 有什么方法可以让gganimate“重新计算”facet_zoom 每帧的比例?

理想结果

第一帧

最后一帧

当前代码
library(gapminder)
library(ggplot2)
library(gganimate)
library(ggforce)
p <- ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, color = continent)) +
    geom_point() + scale_x_log10() +
    facet_zoom(x = continent == "Europe") +
    labs(title = "{frame_time}") +
    transition_time(year) 

animate(p, nframes = 30)

【问题讨论】:

  • 我能想到的一种解决方法是导出单个 png,然后从中创建一个 gif 文件。但是每一步都改变 x 轴会使情节非常难以理解,而且 imo 的用处也减少了
  • 谢谢,感谢您的解决方法!我想使用tweenR 来计算中间位置,用ggplot() 循环它们以将每个图保存到磁盘并在最后一步将它们缝合在一起。但这是最后的手段。
  • 可能view_follow 应该能够强制执行此操作,但我无法使其工作。首先,您需要关闭对数刻度,不知道为什么。但即便如此,它似乎也完全打破了facet_zoom
  • 好的,无论你尝试如何使用构面(也是“正常”构面),使用view_follow 的那一刻,轴可以设置为跨构面相同。这意味着按照目前的情况,这不太可能奏效。但也许@ThomasP85 会看到这一点。

标签: r ggplot2 gganimate ggforce


【解决方案1】:

我认为截至 2018 年 12 月的当前开发版 gganimate 尚不可能;似乎有一些错误阻止facet_zoomgganimate 配合得很好。幸运的是,我认为解决方法不会太痛苦。

首先,我们可以补间填写中间年份:

# Here I tween by fractional years for more smooth movement
years_all <- seq(min(gapminder$year), 
                 max(gapminder$year), 
                 by = 0.5)

gapminder_tweened <- gapminder %>%
  tweenr::tween_components(time = year, 
                           id   = country, 
                           ease = "linear", 
                           nframes = length(years_all))

然后,将您的代码应用到一个需要一年作为输入的函数中:

render_frame <- function(yr) {
  p <- gapminder_tweened %>%
    filter(year == yr) %>%
    ggplot(aes(gdpPercap, lifeExp, size = pop, color = continent)) +
    geom_point() +
    scale_x_log10(labels = scales::dollar_format(largest_with_cents = 0)) +
    scale_size_area(breaks = 1E7*10^0:3, labels = scales::comma) +
    facet_zoom(x = continent == "Europe") +
    labs(title = round(yr + 0.01) %>% as.integer) 
    # + 0.01 above is a hack to override R's default "0.5 rounds to the
    #   closest even" behavior, which in this case gives more frames
    #   (5 vs. 3) to the even years than the odd years
  print(p) 
}  

最后,我们可以通过遍历年份(在本例中包括小数年份)来保存动画:

library(animation)
oopt = ani.options(interval = 1/10)
saveGIF({for (i in 1:length(years_all)) {
  render_frame(years_all[i])
  print(paste0(i, " out of ",length(years_all)))
  ani.pause()}
},movie.name="facet_zoom.gif",ani.width = 400, ani.height = 300) 

或者,或者,将gifski 用于较小的文件

gifski::save_gif({ for (i in 1:length(years_all) {
  render_frame(years_all[i])
  print(paste0(i, " out of ",length(years_all)))
}
},gif_file ="facet_zoom.gif", width = 400, height = 300, delay = 1/10, progress = TRUE) 

(当我有更多时间时,我会尝试使用手动指定的中断来消除图例中令人分心的变化。)

【讨论】:

    猜你喜欢
    • 2011-11-29
    • 1970-01-01
    • 2015-03-30
    • 2013-12-17
    • 2011-03-31
    • 2012-07-08
    • 2011-07-04
    • 2017-05-30
    • 2019-12-03
    相关资源
    最近更新 更多