[R] 製作梅西和C羅進球數的"追趕動畫" - plotly

動畫效果如下:

視頻封面

數據可視化 - 6大射手進球趨勢

<R動畫>系列文章列表:

老白Walt:[R] 製作梅西和C羅進球數的"追趕動畫" - ggplot2 + save_gif


plotly的優勢:

plotly無需轉換為GIF,可在網頁上直接顯示

plotly的劣勢:

plotly Animation要實現最後追加點和文字比較困難

因此可以藉助shiny做成互動式動畫,但shiny部分不在本文討論範圍內,僅討論如何製作

老規矩,上代碼:

accumulate_by <- function(dat, var) {
var <- lazyeval::f_eval(var, dat)
lvls <- plotly:::getLevels(var)
dats <- lapply(seq_along(lvls), function(x) {
cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
})
dplyr::bind_rows(dats)
}

animate <- function() {
ldf <- gen_df() %>%
dplyr::filter(date < as.Date(2012-07-01)) %>%
dplyr::mutate(dd = lubridate::decimal_date(date)) %>%
accumulate_by(~dd)
dds = unique(ldf$dd)
tv = dds[seq(1, length(dds), 5)]
tt = lubridate::date_decimal(tv) %>%
lubridate::as_date() %>%
as.character() %>%
sub((\d+-\d+)-\d+, \1, .)

plot_ly(
data = ldf,
width = 1280,
height = 720
) %>%
add_lines(
x = ~dd,
y = ~value,
frame = ~frame,
linetype = ~var,
line = list(
width = 3
)
) %>%
layout(
autosize = T,
title = <b>六大射手進球趨勢動畫(2009~2012年)</b>,
margin = list(
t = 40
),
font = list(
family = 微軟雅黑,
size = 16
),
xaxis = list(
title = "",
tickvals = tv,
ticktext = tt,
tickangel = -30,
zeroline = F
),
yaxis = list(
title = "",
zeroline = F
)
) %>%
animation_opts(
frame = 10,
transition = 0,
redraw = FALSE
) %>%
animation_slider(
hide = T
) %>%
animation_button(
x = 1, xanchor = "right", y = 1, yanchor = "bottom"
)
}

有關gen_df()的實現請參考:

老白Walt:[R] 製作梅西和C羅進球數的"追趕動畫" - ggplot2 + save_gif

accumulate_by()顧名思義就是堆積函數,具體說就是:

  1. 原始數據描述的是時間和坐標
  2. 當原始數據引入幀(即時間)後,則每幀對應的數據是前面所有幀的坐標點

上面就是plotly動畫機制的原理,因此如果原始數據過大,堆積出來的數據會非常龐大,而且隨著index的增大,繪製速度也會變慢,所以不要嘗試大數據集,電腦吃不消

如視頻的例子中,gen_df()的行數為2286,堆積後為37296行,出圖用時12秒,所以如果用在shiny中,盡量減少數據集中的variable type,減少幀數,以達到快速響應

plotly、lubridate package在這裡就不詳細介紹了,有興趣的可以google


本專欄只生產乾貨,喜歡請關註:

數據及可視化?

zhuanlan.zhihu.com圖標
推薦閱讀:

TAG:數據可視化 | 足球 | R(編程語言) |