如何停止Ggrepel标签在R / ggplot2中的gganimate帧之间移动?

时间:2019-04-17 08:51:22

标签: r ggplot2 gganimate ggrepel

我想在ggplot中的行尾添加标签,避免标签重叠,并避免在动画过程中标签四处移动。

到目前为止,我可以使用geom_text将标签放置在正确的位置并保持静态,但是标签会重叠,或者我可以使用geom_text_repel防止标签重叠,但是标签不会出现在我的位置希望他们跳舞,然后在情节动画后跳舞(后一个版本在下面的代码中)。

我认为一种解决方案可能涉及有效地在ggplot中创建静态层(下面的p1),然后添加动画层(下面的p2),但是似乎没有。

如何在动画ggplot中保持绘图常量的某些元素(即静态)? (在这种情况下,标签位于行尾。)

此外,使用geom_text时,标签会按照我想要的方式出现-在每行的结尾处,在绘图的外部-但是对于geom_text_repel,所有标签都在绘图区域内移动。为什么是这样?

以下是一些示例数据:

library(dplyr)
library(ggplot2)
library(gganimate)
library(ggrepel)

set.seed(99)

# data
static_data <- data.frame(
  hline_label = c("fixed_label_1", "fixed_label_2", "fixed_label_3", "fixed_label_4", 
                  "fixed_label_5", "fixed_label_6", "fixed_label_7", "fixed_label_8", 
                  "fixed_label_9", "fixed_label_10"), 
  fixed_score = c(2.63, 2.45, 2.13, 2.29, 2.26, 2.34, 2.34, 2.11, 2.26, 2.37))

animated_data <- data.frame(condition = c("a", "b")) %>% 
  slice(rep(1:n(), each = 10)) %>% 
  group_by(condition) %>% 
  mutate(time_point = row_number()) %>% 
  ungroup() %>% 
  mutate(score = runif(20, 2, 3))

这是我用于动画情节的代码:

# colours for use in plot
condition_colours <- c("red", "blue")

# plot static background layer 
p1 <- ggplot(static_data, aes(x = time_point)) +
  scale_x_continuous(breaks = seq(0, 10, by = 2), expand = c(0, 0)) + 
  scale_y_continuous(breaks = seq(2, 3, by = 0.10), limits = c(2, 3), expand = c(0, 0)) + 
  # add horizontal line to show existing scores
  geom_hline(aes(yintercept = fixed_score), alpha = 0.75) + 
  # add fixed labels to the end of lines (off plot)
  geom_text_repel(aes(x = 11, y = fixed_score, label = hline_label), 
                  hjust = 0, size = 4, direction = "y", box.padding = 1.0) +
  coord_cartesian(clip = 'off') +
  guides(col = F) +
  labs(title = "[Title Here]", x = "Time", y = "Mean score") + 
  theme_minimal() + 
  theme(panel.grid.minor = element_blank(),
        plot.margin = margin(5.5, 120, 5.5, 5.5))

# animated layer
p2 <- p1 + 
  geom_point(data = animated_data, 
             aes(x = time_point, y = score, colour = condition, group = condition)) +
  geom_line(data = animated_data, 
            aes(x = time_point, y = score, colour = condition, group = condition), 
            show.legend = FALSE) +
  scale_color_manual(values = condition_colours) + 
  geom_segment(data = animated_data, 
               aes(xend = time_point, yend = score, y = score, colour = condition),
               linetype = 2) + 
  geom_text(data = animated_data, 
            aes(x = max(time_point) + 1, y = score, label = condition, colour = condition), 
            hjust = 0, size = 4) + 
  transition_reveal(time_point) +
  ease_aes('linear') 

# render animation 
animate(p2, nframes = 50, end_pause = 5, height = 1000, width = 1250, res = 120)

1 个答案:

答案 0 :(得分:1)

建议:

  1. geom_text_repel中的特定排斥方向/数量等由随机种子确定。您可以seed设置为恒定值,以便在动画的每一帧中获得相同的排斥位置。

  2. 即使您关闭了剪切功能并在绘图限制之外指定了一些排斥范围,我也不认为被排斥的文字有可能超出绘图区域。该软件包的全部目的是使文本标签彼此远离,同时保留在打印区域内。但是,您可以扩展绘图区域,并使用geom_segment而不是geom_hline来绘制水平线,以使这些线在到达被排斥的文本标签之前停止。

  3. 由于有更多使用animated_data作为其数据源的geom图层,因此更容易将 animated_data和相关的常见美学贴图放在顶层{{1} }通话,而不是ggplot()

这是一个可能的实现。注释中的说明:

static_data

result