gganimate如何订购有序的酒吧时间序列? [英] How does gganimate order an ordered bar time-series?

查看:84
本文介绍了gganimate如何订购有序的酒吧时间序列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个时间序列数据,其中我在y轴上绘制疾病的诊断率 DIAG_RATE_65_PLUS ,并在x上绘制地理区域以进行比较轴 NAME 作为简单的条形图。我的时间变量是 ACH_DATEyearmon ,如标题所示,动画在循环播放。

  df%>%ggplot(aes(reorder(NAME,DIAG_RATE_65_PLUS),DIAG_RATE_65_PLUS))+ 
geom_bar(stat = identity,alpha = 0.66)+
labs(title = '{closest_state}')+
主题(plot.title = element_text(正好= 1,大小= 22),
axis.text.x = element_blank())+
transition_states(ACH_DATEyearmon ,transition_length = 1,state_length = 1)+
ease_aes('linear')

I已对 NAME 进行了重新排序,因此按 DIAG_RATE_65_PLUS 进行排名。



gganimate产生的东西





我现在有两个问题:



1)gganimate如何对数据重新排序?总体上会进行一些重新排序,但是每个月都没有帧按照 DIAG_RATE_65_PLUS 从最小到最大的顺序对组进行完美排序。理想情况下,我希望完美订购最后一个月 2018年8月。前几个月所有的x轴都可以基于订购的 $ a $ 2018中的 NAME 的x轴。



2)在gganimate中是否可以选择使组在条形图中每个月转移到正确的位置?



我的评论查询的图:





更改以上内容 just = 1

的代码



@ eipi10

  df%&%;%
ggplot(aes(y = NAME,x = DIAG_RATE_65_PLUS))+
geom_barh(stat = identity,alpha = 0.66)+
geom_hline(yintercept =(2/3)* 25,线型= dotdash)+ #geom_vline(xintercept =(2/3)* 25)不兼容,但是geom_hline可以工作,但是对情节
labs(title ='{closest_state}')+ $ b $无效b主题(plot.title = element_text(正好= 1,大小= 22))+
transition_states(ACH_DATEyearmon,transition_length = 1,state_length = 50)+
view_follow(fixed_x = TRUE)+
ease_aes('linear')


解决方案

条形排序为由 ggplot 完成,不受 gganimate 的影响。根据每个 ACH_DATEyearmon 中的 DIAG_RATE_65_PLUS 的总和来订购这些小节。下面,我将说明这些条的排列方式,然后提供代码以创建动画图,并在每帧中按从低到高的顺序进行排序。



条是有序的,首先让我们创建一些假数据:

  library(tidyverse)
库(gganimate)
theme_set(theme_classic())

#伪数据
日期= paste(rep(month.abb,each = 10),2017)

set.seed (2)
df = data.frame(NAME = c(replicate(12,sample(LETTERS [1:10])))),
ACH_DATEyearmon = factor(dates,level = unique(dates)) ,
DIAG_RATE_65_PLUS = c(replicate(12,rnorm(10,30,5))))

现在让我们绘制一个条形图。条形是每个 NAME DIAG_RATE_65_PLUS 的总和。请注意x轴 NAME 值的顺序:

  df% >%
ggplot(aes(reorder(NAME,DIAG_RATE_65_PLUS),DIAG_RATE_65_PLUS))+
geom_bar(stat = identity,alpha = 0.66)+
labs(title ='{closest_state }')+
主题(plot.title = element_text(just = 1,size = 22))



您可以在下面看到,当我们显式加总时,顺序是相同的DIAG_RATE_65_PLUS NAME 排序,并按总和排序:

  df%>%group_by(NAME)%>%
summarise(DIAG_RATE_65_PLUS = sum(DIAG_RATE_65_PLUS))%>%
range(DIAG_RATE_65_PLUS)




 名称DIAG_RATE_65_PLUS 
1 A 336.1271
2高345.2369
3 B 346.7151
4 I 350.1480
5 E 356.4333
6 C 367.4768
7 D 368.2225
8 F 368.3765
9 J 368.9655
10 G 387.1523


现在,我们要创建一个动画,对<$ c $进行排序每个 ACH_DATEyearmon 分别按 DIAG_RATE_65_PLUS 的c> NAME 。为此,我们首先生成一个名为 order 的新列,该列设置所需的顺序:

  df = df%&%;%
安排(ACH_DATEyearmon,DIAG_RATE_65_PLUS)%>%
mutate(order = 1:n())

现在我们创建动画。 transition_states 为每个 ACH_DATEyearmon 生成框架。 view_follow(fixed_y = TRUE)仅显示当前 ACH_DATEyearmon 的x值,并保持相同的y轴范围所有帧。



请注意,我们使用 order 作为x变量,但随后运行 scale_x_continuous 将x标签更改为 NAME 值。我已将这些标签包括在图中,因此您可以看到它们随每个 ACH_DATEyearmon 而变化,但是您当然可以像在示例中所做的那样在实际图中删除它们

  p = df%>%
ggplot(aes(order,DIAG_RATE_65_PLUS))+
geom_bar(stat = identity,alpha = 0.66)+
labs(title ='{closest_state}')+
theme(plot.title = element_text(just = 1,size = 22))+
scale_x_continuous(breaks = df $ order,labels = df $ NAME)+
transition_states(ACH_DATEyearmon,transition_length = 1,state_length = 50)+
view_follow(fixed_y = TRUE)+
ease_aes('linear')

animate(p,nframes = 60)

anim_save( test.gif)



如果关闭 view_follow(),您可以看到整个图看起来((当然,您可以通过在 transition_states 行之前停止代码来查看完整的非动画图)。

  p = df%&%;%
ggplot(aes(order,DIAG_RATE_65_PLUS))+
geom_bar(stat = identity,alpha = 0.66)+
labs(title ='{closest_state}')+
主题(plot.title = element_text(just = 1,size = 22))+
scale_x_continuous(breaks = df $ order,labels = df $ NAME)+
transition_states(ACH_DATEyearmon,transition_length = 1,state_length = 50)+
#view_follow(fixed_y = TRUE)+
ease_aes('linear')



更新:要回答您的问题...



要按给定月份的值进行排序,请将数据转换为该月订购的水平。要绘制旋转图,我们将使用 geom_barh (水平条形图)代替 coord_flip c $ c> ggstance 软件包。请注意,我们必须在 aes view_follow()中切换y和x,并且y-轴 NAME 的值现在是恒定的:

 库(实例)

#根据2017年8月的值设置NAME订单
df = df%>%
range(DIAG_RATE_65_PLUS)%&%;%
mutate(NAME = factor(NAME, level = unique(NAME [ACH [DATEyearmon == Aug 2017]))))

p = df%>%
ggplot(aes(y = NAME,x = DIAG_RATE_65_PLUS))+
geom_barh(stat = identity,alpha = 0.66)+
labs(title ='{closest_state}')+
theme(plot.title = element_text(just = 1,size = 22 ))+
transition_states(ACH_DATEyearmon,transition_length = 1,state_length = 50)+
view_follow(fixed_x = TRUE)+
ease_aes('linear')

动画(p,nframes = 60)
anim_save( test3.gif)



对于平滑的过渡,@ JonSpring的答案似乎处理得很好。


I have a time-series of data, where I'm plotting diagnosis rates for a disease on the y-axis DIAG_RATE_65_PLUS, and geographical groups for comparison on the x-axis NAME as a simple bar graph. My time variable is ACH_DATEyearmon, which the animation is cycling through as seen in the title.

df %>% ggplot(aes(reorder(NAME, DIAG_RATE_65_PLUS), DIAG_RATE_65_PLUS)) +
  geom_bar(stat = "identity", alpha = 0.66) +
  labs(title='{closest_state}') +
  theme(plot.title = element_text(hjust = 1, size = 22),
        axis.text.x=element_blank()) +
  transition_states(ACH_DATEyearmon, transition_length = 1, state_length = 1) +
  ease_aes('linear')

I've reordered NAME so it gets ranked by DIAG_RATE_65_PLUS.

What gganimate produces:

I now have two questions:

1) How exactly does gganimate reorder the data? There is some overall general reordering, but each month has no frame where the groups are perfectly ordered by DIAG_RATE_65_PLUS from smallest to biggest. Ideally, I would like the final month "Aug 2018" to be ordered perfectly. All of the previous months can have their x-axis based on the ordered NAME for "Aug 2018`.

2) Is there an option in gganimate where the groups "shift" to their correct rank for each month in the bar chart?

Plots for my comment queries:

https://i.stack.imgur.com/s2UPw.gif https://i.stack.imgur.com/Z1wfd.gif

@JonSpring

    df %>%
  ggplot(aes(ordering, group = NAME)) +
  geom_tile(aes(y = DIAG_RATE_65_PLUS/2, 
                height = DIAG_RATE_65_PLUS,
                width = 0.9), alpha = 0.9, fill = "gray60") +
  geom_hline(yintercept = (2/3)*25, linetype="dotdash") +
  # text in x-axis (requires clip = "off" in coord_cartesian)
  geom_text(aes(y = 0, label = NAME), hjust = 2) + ## trying different hjust values
  theme(plot.title = element_text(hjust = 1, size = 22),
        axis.ticks.y = element_blank(), ## axis.ticks.y shows the ticks on the flipped x-axis (the now metric), and hides the ticks from the geog layer
        axis.text.y = element_blank()) + ## axis.text.y shows the scale on the flipped x-axis (the now metric), and hides the placeholder "ordered" numbers from the geog layer
  coord_cartesian(clip = "off", expand = FALSE) +
  coord_flip() +
  labs(title='{closest_state}', x = "") +
  transition_states(ACH_DATEyearmon, 
                    transition_length = 2, state_length = 1) +
  ease_aes('cubic-in-out')

With hjust=2, labels are not aligned and move around.

Changing the above code with hjust=1

@eipi10

df %>% 
  ggplot(aes(y=NAME, x=DIAG_RATE_65_PLUS)) +
  geom_barh(stat = "identity", alpha = 0.66) +
  geom_hline(yintercept=(2/3)*25, linetype = "dotdash") + #geom_vline(xintercept=(2/3)*25) is incompatible, but geom_hline works, but it's not useful for the plot
  labs(title='{closest_state}') +
  theme(plot.title = element_text(hjust = 1, size = 22)) +
  transition_states(ACH_DATEyearmon, transition_length = 1, state_length = 50) +
  view_follow(fixed_x=TRUE) +
  ease_aes('linear')

解决方案

The bar ordering is done by ggplot and is not affected by gganimate. The bars are being ordered based on the sum of DIAG_RATE_65_PLUS within each ACH_DATEyearmon. Below I'll show how the bars are ordered and then provide code for creating the animated plot with the desired sorting from low to high in each frame.

To see how the bars are ordered, first let's create some fake data:

library(tidyverse)
library(gganimate)
theme_set(theme_classic())

# Fake data
dates = paste(rep(month.abb, each=10), 2017)

set.seed(2)
df = data.frame(NAME=c(replicate(12, sample(LETTERS[1:10]))),
                ACH_DATEyearmon=factor(dates, levels=unique(dates)),
                DIAG_RATE_65_PLUS=c(replicate(12, rnorm(10, 30, 5))))

Now let's make a single bar plot. The bars are the sum of DIAG_RATE_65_PLUS for each NAME. Note the order of the x-axis NAME values:

df %>% 
  ggplot(aes(reorder(NAME, DIAG_RATE_65_PLUS), DIAG_RATE_65_PLUS)) +
  geom_bar(stat = "identity", alpha = 0.66) +
  labs(title='{closest_state}') +
  theme(plot.title = element_text(hjust = 1, size = 22)) 

You can see below that the ordering is the same when we explicitly sum DIAG_RATE_65_PLUS by NAME and sort by the sum:

df %>% group_by(NAME) %>% 
  summarise(DIAG_RATE_65_PLUS = sum(DIAG_RATE_65_PLUS)) %>% 
  arrange(DIAG_RATE_65_PLUS)

   NAME DIAG_RATE_65_PLUS
1     A          336.1271
2     H          345.2369
3     B          346.7151
4     I          350.1480
5     E          356.4333
6     C          367.4768
7     D          368.2225
8     F          368.3765
9     J          368.9655
10    G          387.1523

Now we want to create an animation that sorts NAME by DIAG_RATE_65_PLUS separately for each ACH_DATEyearmon. To do this, let's first generate a new column called order that sets the ordering we want:

df = df %>% 
  arrange(ACH_DATEyearmon, DIAG_RATE_65_PLUS) %>% 
  mutate(order = 1:n())

Now we create the animation. transition_states generates the frames for each ACH_DATEyearmon. view_follow(fixed_y=TRUE)shows x-values only for the current ACH_DATEyearmon and maintains the same y-axis range for all frames.

Note that we use order as the x variable, but then we run scale_x_continuous to change the x-labels to be the NAME values. I've included these labels in the plot so you can see that they change with each ACH_DATEyearmon, but you can of course remove them in your actual plot as you did in your example.

p = df %>% 
  ggplot(aes(order, DIAG_RATE_65_PLUS)) +
    geom_bar(stat = "identity", alpha = 0.66) +
    labs(title='{closest_state}') +
    theme(plot.title = element_text(hjust = 1, size = 22)) +
    scale_x_continuous(breaks=df$order, labels=df$NAME) +
    transition_states(ACH_DATEyearmon, transition_length = 1, state_length = 50) +
    view_follow(fixed_y=TRUE) +
    ease_aes('linear')

animate(p, nframes=60)

anim_save("test.gif")

If you turn off view_follow(), you can see what the "whole" plot looks like (and you can, of course, see the full, non-animated plot by stopping the code before the transition_states line).

p = df %>% 
  ggplot(aes(order, DIAG_RATE_65_PLUS)) +
    geom_bar(stat = "identity", alpha = 0.66) +
    labs(title='{closest_state}') +
    theme(plot.title = element_text(hjust = 1, size = 22)) +
    scale_x_continuous(breaks=df$order, labels=df$NAME) +
    transition_states(ACH_DATEyearmon, transition_length = 1, state_length = 50) +
    #view_follow(fixed_y=TRUE) +
    ease_aes('linear')

UPDATE: To answer your questions...

To order by a given month's values, turn the data into a factor with the levels ordered by that month. To plot a rotated graph, instead of coord_flip, we'll use geom_barh (horizontal bar plot) from the ggstance package. Note that we have to switch the y's and x's in aes and view_follow() and that the order of the y-axis NAME values is now constant:

library(ggstance)

# Set NAME order based on August 2017 values
df = df %>% 
  arrange(DIAG_RATE_65_PLUS) %>% 
  mutate(NAME = factor(NAME, levels=unique(NAME[ACH_DATEyearmon=="Aug 2017"])))

p = df %>% 
  ggplot(aes(y=NAME, x=DIAG_RATE_65_PLUS)) +
  geom_barh(stat = "identity", alpha = 0.66) +
  labs(title='{closest_state}') +
  theme(plot.title = element_text(hjust = 1, size = 22)) +
  transition_states(ACH_DATEyearmon, transition_length = 1, state_length = 50) +
  view_follow(fixed_x=TRUE) +
  ease_aes('linear')

animate(p, nframes=60)
anim_save("test3.gif")

For smooth transitions, it seems like @JonSpring's answer handles that well.

这篇关于gganimate如何订购有序的酒吧时间序列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆