use*_*082 8 animation r ggplot2 dplyr 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}') +
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')
Run Code Online (Sandbox Code Playgroud)
我已经重新排序,NAME所以它排名靠前DIAG_RATE_65_PLUS.
gganimate产生的是什么:
我现在有两个问题:
1)gganimate如何重新排序数据?有一些整体的一般重新排序,但每个月没有框架,DIAG_RATE_65_PLUS从最小到最大的组完美排序.理想情况下,我希望最后一个月"2018年8月"完美订购.所有前几个月的x轴都可以根据NAME"2018年8月" 的订购而定.
2)在gganimate中是否有一个选项,其中组在条形图中每个月"转移"到正确的等级?
我的评论查询图:
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')
Run Code Online (Sandbox Code Playgroud)
使用时hjust=2,标签不会对齐并移动.
用上面的代码改变 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')
Run Code Online (Sandbox Code Playgroud)
为了增加@ eipi10的优秀答案,我认为这是一个值得更换geom_bar以获得更大灵活性的案例.geom_bar通常对于离散类别来说非常方便,但它不能让我们充分利用gganimate丝滑平滑的动画荣耀.
例如,使用geom_tile,我们可以重新创建与geom_bar相同的外观,但在x轴上具有流体移动.这有助于保持每个条的视觉轨迹,并查看哪些条最有效.我认为这很好地解决了你问题的第二部分.
为了使这项工作,我们可以向数据添加一个新列,显示每个月应该使用的顺序.我们将此订单保存为double,而不是整数(通过使用* 1.0).gganimate当它在位置1和2之间进行动画处理时,这将允许在位置1.25处放置一个条形.
df2 <- df %>%
group_by(ACH_DATEyearmon) %>%
mutate(ordering = min_rank(DIAG_RATE_65_PLUS) * 1.0) %>%
ungroup()
Run Code Online (Sandbox Code Playgroud)
现在我们可以以类似的方式绘制,但使用geom_tile而不是geom_bar.我想NAME在顶部和轴上显示两者,所以我使用了两个geom_text具有不同y值的调用,一个在零,一个在条的高度.vjust让我们使用文本行单位垂直对齐每个.
这里的另一个技巧是关闭剪切coord_cartesian,使底部文本低于绘图区域,进入x轴文本通常所在的位置.
p <- df2 %>%
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") +
# text on top of bars
geom_text(aes(y = DIAG_RATE_65_PLUS, label = NAME), vjust = -0.5) +
# text in x-axis (requires clip = "off" in coord_cartesian)
geom_text(aes(y = 0, label = NAME), vjust = 2) +
coord_cartesian(clip = "off", expand = FALSE) +
labs(title='{closest_state}', x = "") +
theme(plot.title = element_text(hjust = 1, size = 22),
axis.ticks.x = element_blank(),
axis.text.x = element_blank()) +
transition_states(ACH_DATEyearmon,
transition_length = 2, state_length = 1) +
ease_aes('cubic-in-out')
animate(p, nframes = 300, fps = 20, width = 400, height = 300)
Run Code Online (Sandbox Code Playgroud)
回到第一个问题,这里有一个颜色的版本,我通过删除发fill = "gray60"在geom_tile电话.我按照NAME2017年8月的顺序对类别进行了排序,因此如您所述,它们将按顺序排列.
可能有更好的方法来进行排序,但我是通过加入df22017年8月订购的表来实现的.
Aug_order <- df %>%
filter(ACH_DATEyearmon == "Aug 2017") %>%
mutate(Aug_order = min_rank(DIAG_RATE_65_PLUS) * 1.0) %>%
select(NAME, Aug_order)
df2 <- df %>%
group_by(ACH_DATEyearmon) %>%
mutate(ordering = min_rank(DIAG_RATE_65_PLUS) * 1.0) %>%
ungroup() %>%
left_join(Aug_order) %>%
mutate(NAME = fct_reorder(NAME, -Aug_order))
Run Code Online (Sandbox Code Playgroud)
条形码的排序由ggplot并且不受影响gganimate.这些酒吧是根据DIAG_RATE_65_PLUS每个酒吧的总和订购的ACH_DATEyearmon.下面我将展示如何排序条形图,然后提供用于创建动画图的代码,每帧中从低到高的所需排序.
要查看条形图的排序方式,首先让我们创建一些假数据:
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))))
Run Code Online (Sandbox Code Playgroud)
现在让我们制作一个单一的条形图.条形图是DIAG_RATE_65_PLUS每个条形图的总和NAME.请注意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}') +
theme(plot.title = element_text(hjust = 1, size = 22))
Run Code Online (Sandbox Code Playgroud)
你可以看到下面的顺序是一样的,当我们明确地总结DIAG_RATE_65_PLUS通过NAME和排序的总和:
df %>% group_by(NAME) %>%
summarise(DIAG_RATE_65_PLUS = sum(DIAG_RATE_65_PLUS)) %>%
arrange(DIAG_RATE_65_PLUS)
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)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
现在,我们要创建一个排序的动画NAME通过DIAG_RATE_65_PLUS分别为每ACH_DATEyearmon.为此,我们首先生成一个名为的新列order,用于设置我们想要的顺序:
df = df %>%
arrange(ACH_DATEyearmon, DIAG_RATE_65_PLUS) %>%
mutate(order = 1:n())
Run Code Online (Sandbox Code Playgroud)
现在我们创建动画.transition_states为每个生成帧ACH_DATEyearmon.view_follow(fixed_y=TRUE)仅显示当前的x值,ACH_DATEyearmon并为所有帧保持相同的y轴范围.
请注意,我们使用orderx变量,但随后我们运行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(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")
Run Code Online (Sandbox Code Playgroud)
如果你关闭view_follow(),你可以看到"整个"情节的样子(当然,你可以通过transition_states在行前停止代码来查看完整的非动画情节).
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')
Run Code Online (Sandbox Code Playgroud)
更新:回答你的问题......
要按给定月份的值进行排序,请将数据转换为具有该月份排序水平的因子.要绘制旋转的图形,而不是coord_flip,我们将使用包中的geom_barh(水平条形图)ggstance.请注意,我们必须切换y和x,aes并且view_follow()y轴NAME值的顺序现在是常量:
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")
Run Code Online (Sandbox Code Playgroud)
对于平滑过渡,似乎@ JonSpring的答案处理得很好.
| 归档时间: |
|
| 查看次数: |
2015 次 |
| 最近记录: |