通过gganimate和ggforce移动的facet缩放的动画情节?

Rom*_*man 17 r ggplot2 gganimate ggforce

在此输入图像描述

目标

我想放大这些年来的GDP Europe.幻象ggforce::facet_zoom允许非常容易地将其用于静态图(即,特定年份).

然而,移动尺度证明比预期更难.gganimate似乎从第一帧(year == 1952)获取x轴限制并一直持续到动画结束.不幸的是,这个相关但代码过时的问题没有得出答案.既不能+ coord_cartesian(xlim = c(from, to)),也facet_zoom(xlim = c(from, to))不能影响facet_zoom超出静态极限的窗口.

  • 有没有办法让gganimate'重新计算' facet_zoom每一帧的比例?

理想的结果

第一帧

2

最后一帧

3

目前的代码
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)
Run Code Online (Sandbox Code Playgroud)

Jon*_*ing 17

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

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

# 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))
Run Code Online (Sandbox Code Playgroud)

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

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) 
}  
Run Code Online (Sandbox Code Playgroud)

最后,我们可以通过循环遍历这些年来保存动画(在这种情况下包括分数年):

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) 
Run Code Online (Sandbox Code Playgroud)

或者,使用gifski较小的文件<2MB:

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) 
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述