gganimate:在标题表达式中包含状态级别变量或框架以外的其他变量

gganimate: include additional variable other than states level variable or frame in title expression

我想将我的数据的 另一个 列值插入到 gganimate 动画标题中。

例如,这里状态级别变量是 x,我想添加到标题变量 y:

df <- tibble(x = 1:10, y = c('a', 'a', 'b', 'd', 'c', letters[1:5]))
df

A tibble: 10 x 2
       x y    
   <int> <chr>
 1     1 a    
 2     2 a    
 3     3 b    
 4     4 d    
 5     5 c    
 6     6 a    
 7     7 b    
 8     8 c    
 9     9 d    
10    10 e 

这按预期工作:

ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = '{closest_state}') +
  transition_states(x,
                    transition_length = 0.1,
                    state_length = 0.1)

这失败了:

ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = '{closest_state}, another_var: {y}') +
  transition_states(x,
                    transition_length = 0.1,
                    state_length = 0.1)

Error in eval(parse(text = text, keep.source = FALSE), envir) :
object 'y' not found

也试过这个,但是y不会改变:

ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = str_c('{closest_state}, another_var: ', df$y)) +
  transition_states(x,
                    transition_length = 0.1,
                    state_length = 0.1)

另一种选择是将 y 映射为状态级别变量并使用 frame 变量而不是 x,但在我的应用程序中 y 是 not-necessarily-unique 字符变量,如上,或者它是一个数字变量,但又是 not-necessarily-unique 和 not-necessarily-ordered。在这种情况下,gganimate(或 ggplot?)将按照它认为合适的方式对其进行排序,从而使最终结果很奇怪,而不是按 x:

排序
ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = '{frame}, another_var: {closest_state}') +
  transition_states(y,
                    transition_length = 0.1,
                    state_length = 0.1)

那么如何简单地添加 un-ordered 的变化值,而不是数字,y 变量?

最后:有人问了这个问题here但是没有可重现的例子所以没有回答,希望这个更好。

一个肮脏的解决方案是 paste 将变量放在一起并制作一个新的变量以用于 transition_states:

df <- mutate(df, title_var = factor(paste(x, y, sep="-"), levels = paste(x, y, sep="-")))
# # A tibble: 6 x 3
# x y     title_var
# <int> <chr> <fct>    
# 1     1 a     1-a      
# 2     2 a     2-a      
# 3     3 b     3-b      
# 4     4 d     4-d      
# 5     5 c     5-c      
# 6     6 a     6-a  

然后我们可以使用 gsub() 来去除不需要的部分 closest_state,像这样:

gsub(pattern = "\d+-", replacement = "", "1-a") 
"a"

所以:

ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = '{gsub(pattern = "\d+-", replacement = "", closest_state)}') +
  transition_states(title_var, transition_length = 0.1, state_length = 0.1)

另一种可能性,稍微紧凑一些,来自 gganimate 的作者本人,在我打开的问题之后:

https://github.com/thomasp85/gganimate/issues/252#issuecomment-450846868

根据托马斯的说法:

There are multiple reasons why random columns from the input data cannot be accessed so it is unlikely to get any better than this...

这是一个使用 dplyr 的解决方案,基于 gganimate 开发人员 Thomas 的解决方案,由 Giora 提供。

library(tidyverse)
library(gganimate)

df <- tibble::tibble(x = 1:10, y = c('a', 'a', 'b', 'd', 'c', letters[1:5]))

a <- ggplot(df, aes(x, x)) +
  geom_point() +
  labs(title = "{closest_state}, another_var: {df %>% filter(x == closest_state) %>% pull(y)}") +
  transition_states(x,
                    transition_length = 0.1,
                    state_length = 0.1)
animate(a)

gganimate 标题对动画标题元素使用 glue 语法,您可以在其中包含整个 dplyr 数据操作管道。

您可以在 dplyr 调用中引用 gganimate::transition_states() 提供的 closest_state 变量。在这里,由于动画的帧由 x 的连续级别索引,我使用 filter() 根据 x 的值对给定帧的 df 进行子集化,然后参考y 列的相应行,其中包含我想在标题中显示的附加信息。使用 pull,您可以获取 x 对应的 y 的单个值,并将其显示在动画标题中。

这是一种简洁明了的方法,您可以通过添加 summarize() 和 [=28= 中的其他调用来计算摘要值以显示 on-the-fly ]管道。