Анимированный сюжет с движущейся гранью с помощью gganimate и ggforce? - PullRequest
0 голосов
/ 17 октября 2018

enter image description here

Цель

Я хотел бы увеличить ВВП на Europe за все годы.Phantastic ggforce::facet_zoom позволяет это для статических графиков (то есть, для одного конкретного года) очень легко.

Движущиеся весы оказываются сложнее, чем ожидалось.gganimate, кажется, берет пределы оси X от первого кадра (year == 1952) и продолжается до конца анимации. Этот связанный, но устаревший вопрос с кодом не дал ответа, к сожалению .Похоже, что ни + 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)

1 Ответ

0 голосов
/ 27 декабря 2018

Я не думаю, что это возможно пока с текущей версией dev для gganimate по состоянию на декабрь 2018 года;Кажется, есть некоторые ошибки, которые мешают 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))

Затем, приняв код в функцию, для которой вводится год:

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 для меньшего файла <2MB: </p>

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) 

(Когда у меня будет больше времени, я постараюсь убрать отвлекающие изменения в легендах с помощью заданных вручную разрывов.)

enter image description here

...