我不确定这是否已按gganimate
原样准备就绪。截至 2019 年 5 月,这似乎是一个相关问题:https ://github.com/thomasp85/gganimate/issues/139
编辑我已经用一个可行的解决方案代替了。公平的警告,我是网络操作的新手,我希望有更多经验的人可以将代码重构得更短。
我的一般方法是创建布局,将节点放入 table long2
,然后创建另一个包含所有边的 table。gganimate
然后调用每个层需要的相应数据源。
1. 为三种布局创建节点表:
set.seed(1)
g <- erdos.renyi.game(10, .5, "gnp")
V(g)$name <- letters[1:vcount(g)]
layouts <- c("kk", "circle", "nicely")
long2 <- lapply(layouts, create_layout, graph = g) %>%
enframe(name = "frame") %>%
unnest()
> head(long2)
# A tibble: 6 x 7
frame x y name ggraph.orig_index circular ggraph.index
<int> <dbl> <dbl> <fct> <int> <lgl> <int>
1 1 -1.07 0.363 a 1 FALSE 1
2 1 1.06 0.160 b 2 FALSE 2
3 1 -1.69 -0.310 c 3 FALSE 3
4 1 -0.481 0.135 d 4 FALSE 4
5 1 -0.0603 -0.496 e 5 FALSE 5
6 1 0.0373 1.02 f 6 FALSE 6
2. 将原始布局的边缘转换为表格。
在这里,我从、、和的列中提取边缘并重塑为可以使用的g
格式。重构的时机已经成熟,但它确实有效。geom_segment
x
y
xend
yend
edges_df <- igraph::as_data_frame(g, "edges") %>%
tibble::rowid_to_column() %>%
gather(end, name, -rowid) %>%
# Here we get the coordinates for each node from `long2`.
left_join(long2 %>% select(frame, name, x, y)) %>%
gather(coord, val, x:y) %>%
# create xend and yend when at the "to" end, for geom_segment use later
mutate(col = paste0(coord, if_else(end == "to", "end", ""))) %>%
select(frame, rowid, col, val) %>%
arrange(frame, rowid) %>%
spread(col, val) %>%
# Get the node names for the coordinates we're using, so that we
# can name the edge from a to b as "a_b" and gganimate can tween
# correctly between frames.
left_join(long2 %>% select(frame, x, y, start_name = name)) %>%
left_join(long2 %>% select(frame, xend = x, yend = y, end_name = name)) %>%
unite(edge_name, c("start_name", "end_name"))
> head(edges_df)
frame rowid x xend y yend edge_name
1 1 1 -1.0709480 -1.69252646 0.3630563 -0.3095612 a_c
2 1 2 -1.0709480 -0.48086213 0.3630563 0.1353664 a_d
3 1 3 -1.6925265 -0.48086213 -0.3095612 0.1353664 c_d
4 1 4 -1.0709480 -0.06032354 0.3630563 -0.4957609 a_e
5 1 5 1.0571895 -0.06032354 0.1596417 -0.4957609 b_e
6 1 6 -0.4808621 -0.06032354 0.1353664 -0.4957609 d_e
3. 情节!
ggplot() +
geom_segment(data = edges_df,
aes(x = x, xend = xend, y = y, yend = yend, color = edge_name)) +
geom_point(data = long2, aes(x, y, color = name), size = 4) +
geom_text(data = long2, aes(x, y, label = name)) +
guides(color = F) +
ease_aes("quadratic-in-out") +
transition_states(frame, state_length = 0.5) -> a
animate(a, nframes = 400, fps = 30, width = 700, height = 300)