为什么 gganimate 无法按 transition_reveal 的日期正确排序行?
Why does gganimate fail to order lines correctly by date with transition_reveal?
我打算用 gganimate
重现 Ed Hawkins 在 R
中关于气候变化的动画人物。这个数字叫做climate spiral。虽然静态 ggplot
图按年份显示了正确的行顺序(最新数据在顶部),但带有 transition_reveal()
的动画图导致行的顺序错误。
这是一个带有合成数据的可重现示例代码:
library(tidyverse)
library(lubridate)
library(gganimate)
library(RColorBrewer)
# Create monthly data from 1950 to 2020 (and a component for rising values with time)
df <- tibble(year = rep(1950:2020, each = 12),
month = rep(month.abb, 2020-1950+1)) %>%
mutate(date = dmy(paste("01",month,year)),
value = rnorm(n(), 0, 2) + row_number()*0.005) %>%
with_groups(year, mutate, value_yr = mean(value))
temp <- df %>%
ggplot(aes(x = month(date, label=T), y = value, color = value_yr)) +
geom_line(size = 0.6, aes(group = year)) +
geom_hline(yintercept = 0, color = "white") +
geom_hline(yintercept = c(-4,4), color = c("skyblue3","red1"), size = 0.2) +
geom_vline(xintercept = 1:12, color = "white", size = 0.2) +
annotate("label", x = 12.5, y = c(-4,0,4), label = c("-4°C","0°C","+4°C"),
color = c("skyblue3","white","red1"), size = 2.5, fill = "#464950",
label.size = NA, label.padding = unit(0.1, "lines"),) +
geom_point(x = 1, y = -11, size = 15, color = "#464950") +
geom_label(aes(x = 1, y = -11, label = year),
color = "white", size = 4,
fill = "#464950", label.size = NA) +
coord_polar(start = 0) +
scale_color_gradientn(colors = rev(brewer.pal(n=11, name = "RdBu")),
limits = range(df$value_yr)) +
labs(x = "", y = "") +
theme_bw() +
theme(panel.background = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_blank(),
plot.background=element_rect(fill="#464950", color="#464950"),
axis.text.x = element_text(margin = margin(t = -20, unit = "pt"),
color = "white"),
axis.text.y = element_blank(),
axis.ticks = element_blank(),
legend.position = "none")
现在,我们可以将绘图保存为 PNG 或制作动画并保存为 GIF:
ggsave(temp, filename = "test.png", width = 5, height = 5, dpi = 320)
# Animate by date:
anim <- temp +
transition_reveal(date) +
ease_aes('linear')
output <- animate(anim, nframes = 100, end_pause = 30,
height = 5, width = 5, units = "in", res = 300)
anim_save("test.gif", output)
让我们看看结果!
静态 PNG:
GIF 动画:
乍一看,结果是一样的,但细节显示出差异(例如,标记的蓝线)。
在这个包含合成数据的示例代码中,差异很小。但是对于真实数据,这些数字看起来非常不同,因为许多红线(最近的高温数据点)在背景中消失了。那么,如何按日期保留 transition_reveal()
中的订单?感谢任何帮助,非常感谢!
这本身并不是答案。这就是为什么。鉴于此信息,您必须告诉我您喜欢什么,以便我为您提供解决方案。
我尝试了一些东西——我确信每一个都可以,但没有。所以,我想看看 ggplot
中发生了什么。我的直觉被证明是正确的。您的数据在 png
中的顺序是 value_yr
,而不是 year
。
我在最后重复这个问题:
Either you can put the animation in order of value_yr
or you can put the color in ggplot
in order by year. Which would you prefer?
我怎么知道?我提取了对象中指定的颜色。
tellMe <- ggplot_build(temp)$data[[1]]
head(tellMe)
# colour x y group PANEL flipped_aes size linetype alpha
# 1 #1E60A4 1 -1.75990067 1 1 FALSE 0.6 1 NA
# 2 #1E60A4 2 -0.08968196 1 1 FALSE 0.6 1 NA
# 3 #1E60A4 3 -0.69657130 1 1 FALSE 0.6 1 NA
# 4 #1E60A4 4 -0.10777727 1 1 FALSE 0.6 1 NA
# 5 #1E60A4 5 1.57710505 1 1 FALSE 0.6 1 NA
# 6 #1E60A4 6 1.63277369 1 1 FALSE 0.6 1 NA
gimme <- tellMe %>% group_by(group) %>%
summarise(color = unique(colour)) %>%
print(n = 100) # there are less than 100, I just want them all
head(gimme)
# # A tibble: 6 × 2
# group color
# <int> <chr>
# 1 1 #1E60A4
# 2 2 #114781
# 3 3 #175290
# 4 4 #053061
# 5 5 #1C5C9E
# 6 6 #3E8BBF
对我来说,这表明颜色不是按组顺序排列的,所以我想查看颜色以可视化顺序。
我用过这个功能。我知道它来自一个演示,但我不记得是哪一个。我只是为了把它包括在这里,但我没有找到它。
# this is from a demo (not sure which one anymore!
showCols <- function(cl=colors(), bg = "lightgrey",
cex = .75, rot = 20) {
m <- ceiling(sqrt(n <-length(cl)))
length(cl) <- m*m; cm <- matrix(cl, m)
require("grid")
grid.newpage(); vp <- viewport(w = .92, h = .92)
grid.rect(gp=gpar(fill=bg))
grid.text(cm, x = col(cm)/m, y = rev(row(cm))/m, rot = rot,
vp=vp, gp=gpar(cex = cex, col = cm))
}
showCols(gimme$color)
左上角的颜色是最早的年份,下面的数值是次年,依此类推。最近的年份是 right-most 列中的最低值。
df %>% group_by(yr) %>% summarise(value_yr = unique(value_yr))
# they are in 'value_yr' order in ggplot, not year
# # A tibble: 71 × 2
# yr value_yr
# <int> <dbl>
# 1 1950 0.0380
# 2 1951 -0.215
# 3 1952 -0.101
# 4 1953 -0.459
# 5 1954 -0.00130
# 6 1955 0.559
# 7 1956 -0.457
# 8 1957 -0.251
# 9 1958 1.10
# 10 1959 0.282
# # … with 61 more rows
Either you can put the animation in order of value_yr
or you can put the color in ggplot
in order by year. Which would you prefer?
更新
您不会使用 transition_reveal
对同一元素进行分组和 t运行sition。不幸的是,我不能告诉你为什么,但它似乎卡在了 1958!
要使左侧的 gif 与右侧的 ggplot
png 匹配:
首先,我修改了对 ggplot
和 geom_line
的调用
ggplot(aes(x = month(date, label = T), y = value,
group = yr, color = yr)) +
geom_line(size = .6)
然后我尝试使用 transition_reveal
,但注意到随后的年份被分层 在 其他年份之下。我无法解释这种奇怪的行为。当我 运行 showCol
更改 temp,
后,颜色是有序的。这排除了我最初认为的问题。
我修改了对象 anim
,使用 transition_manual
强制绘制图层的顺序。
anim <- temp +
transition_manual(yr, cumulative = T) +
ease_aes('linear')
就是这样。现在层匹配。
至于这在您更改颜色分配之前是否可行:原始图,左侧为年度手动 t运行 版本,右侧为 ggplot
png:
看起来那样也行得通。所以,我最初的 drawn-out 解释并没有我想象的那么有用,但至少你现在有了一个可行的解决方案。 (叹气。)
我打算用 gganimate
重现 Ed Hawkins 在 R
中关于气候变化的动画人物。这个数字叫做climate spiral。虽然静态 ggplot
图按年份显示了正确的行顺序(最新数据在顶部),但带有 transition_reveal()
的动画图导致行的顺序错误。
这是一个带有合成数据的可重现示例代码:
library(tidyverse)
library(lubridate)
library(gganimate)
library(RColorBrewer)
# Create monthly data from 1950 to 2020 (and a component for rising values with time)
df <- tibble(year = rep(1950:2020, each = 12),
month = rep(month.abb, 2020-1950+1)) %>%
mutate(date = dmy(paste("01",month,year)),
value = rnorm(n(), 0, 2) + row_number()*0.005) %>%
with_groups(year, mutate, value_yr = mean(value))
temp <- df %>%
ggplot(aes(x = month(date, label=T), y = value, color = value_yr)) +
geom_line(size = 0.6, aes(group = year)) +
geom_hline(yintercept = 0, color = "white") +
geom_hline(yintercept = c(-4,4), color = c("skyblue3","red1"), size = 0.2) +
geom_vline(xintercept = 1:12, color = "white", size = 0.2) +
annotate("label", x = 12.5, y = c(-4,0,4), label = c("-4°C","0°C","+4°C"),
color = c("skyblue3","white","red1"), size = 2.5, fill = "#464950",
label.size = NA, label.padding = unit(0.1, "lines"),) +
geom_point(x = 1, y = -11, size = 15, color = "#464950") +
geom_label(aes(x = 1, y = -11, label = year),
color = "white", size = 4,
fill = "#464950", label.size = NA) +
coord_polar(start = 0) +
scale_color_gradientn(colors = rev(brewer.pal(n=11, name = "RdBu")),
limits = range(df$value_yr)) +
labs(x = "", y = "") +
theme_bw() +
theme(panel.background = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_blank(),
plot.background=element_rect(fill="#464950", color="#464950"),
axis.text.x = element_text(margin = margin(t = -20, unit = "pt"),
color = "white"),
axis.text.y = element_blank(),
axis.ticks = element_blank(),
legend.position = "none")
现在,我们可以将绘图保存为 PNG 或制作动画并保存为 GIF:
ggsave(temp, filename = "test.png", width = 5, height = 5, dpi = 320)
# Animate by date:
anim <- temp +
transition_reveal(date) +
ease_aes('linear')
output <- animate(anim, nframes = 100, end_pause = 30,
height = 5, width = 5, units = "in", res = 300)
anim_save("test.gif", output)
让我们看看结果!
静态 PNG:
GIF 动画:
乍一看,结果是一样的,但细节显示出差异(例如,标记的蓝线)。
在这个包含合成数据的示例代码中,差异很小。但是对于真实数据,这些数字看起来非常不同,因为许多红线(最近的高温数据点)在背景中消失了。那么,如何按日期保留 transition_reveal()
中的订单?感谢任何帮助,非常感谢!
这本身并不是答案。这就是为什么。鉴于此信息,您必须告诉我您喜欢什么,以便我为您提供解决方案。
我尝试了一些东西——我确信每一个都可以,但没有。所以,我想看看 ggplot
中发生了什么。我的直觉被证明是正确的。您的数据在 png
中的顺序是 value_yr
,而不是 year
。
我在最后重复这个问题:
Either you can put the animation in order of
value_yr
or you can put the color inggplot
in order by year. Which would you prefer?
我怎么知道?我提取了对象中指定的颜色。
tellMe <- ggplot_build(temp)$data[[1]]
head(tellMe)
# colour x y group PANEL flipped_aes size linetype alpha
# 1 #1E60A4 1 -1.75990067 1 1 FALSE 0.6 1 NA
# 2 #1E60A4 2 -0.08968196 1 1 FALSE 0.6 1 NA
# 3 #1E60A4 3 -0.69657130 1 1 FALSE 0.6 1 NA
# 4 #1E60A4 4 -0.10777727 1 1 FALSE 0.6 1 NA
# 5 #1E60A4 5 1.57710505 1 1 FALSE 0.6 1 NA
# 6 #1E60A4 6 1.63277369 1 1 FALSE 0.6 1 NA
gimme <- tellMe %>% group_by(group) %>%
summarise(color = unique(colour)) %>%
print(n = 100) # there are less than 100, I just want them all
head(gimme)
# # A tibble: 6 × 2
# group color
# <int> <chr>
# 1 1 #1E60A4
# 2 2 #114781
# 3 3 #175290
# 4 4 #053061
# 5 5 #1C5C9E
# 6 6 #3E8BBF
对我来说,这表明颜色不是按组顺序排列的,所以我想查看颜色以可视化顺序。
我用过这个功能。我知道它来自一个演示,但我不记得是哪一个。我只是为了把它包括在这里,但我没有找到它。
# this is from a demo (not sure which one anymore!
showCols <- function(cl=colors(), bg = "lightgrey",
cex = .75, rot = 20) {
m <- ceiling(sqrt(n <-length(cl)))
length(cl) <- m*m; cm <- matrix(cl, m)
require("grid")
grid.newpage(); vp <- viewport(w = .92, h = .92)
grid.rect(gp=gpar(fill=bg))
grid.text(cm, x = col(cm)/m, y = rev(row(cm))/m, rot = rot,
vp=vp, gp=gpar(cex = cex, col = cm))
}
showCols(gimme$color)
左上角的颜色是最早的年份,下面的数值是次年,依此类推。最近的年份是 right-most 列中的最低值。
df %>% group_by(yr) %>% summarise(value_yr = unique(value_yr))
# they are in 'value_yr' order in ggplot, not year
# # A tibble: 71 × 2
# yr value_yr
# <int> <dbl>
# 1 1950 0.0380
# 2 1951 -0.215
# 3 1952 -0.101
# 4 1953 -0.459
# 5 1954 -0.00130
# 6 1955 0.559
# 7 1956 -0.457
# 8 1957 -0.251
# 9 1958 1.10
# 10 1959 0.282
# # … with 61 more rows
Either you can put the animation in order of
value_yr
or you can put the color inggplot
in order by year. Which would you prefer?
更新
您不会使用 transition_reveal
对同一元素进行分组和 t运行sition。不幸的是,我不能告诉你为什么,但它似乎卡在了 1958!
要使左侧的 gif 与右侧的 ggplot
png 匹配:
首先,我修改了对 ggplot
和 geom_line
ggplot(aes(x = month(date, label = T), y = value,
group = yr, color = yr)) +
geom_line(size = .6)
然后我尝试使用 transition_reveal
,但注意到随后的年份被分层 在 其他年份之下。我无法解释这种奇怪的行为。当我 运行 showCol
更改 temp,
后,颜色是有序的。这排除了我最初认为的问题。
我修改了对象 anim
,使用 transition_manual
强制绘制图层的顺序。
anim <- temp +
transition_manual(yr, cumulative = T) +
ease_aes('linear')
就是这样。现在层匹配。
至于这在您更改颜色分配之前是否可行:原始图,左侧为年度手动 t运行 版本,右侧为 ggplot
png:
看起来那样也行得通。所以,我最初的 drawn-out 解释并没有我想象的那么有用,但至少你现在有了一个可行的解决方案。 (叹气。)