可以在 R 中使用 gganimate 对多边形填充进行动画处理吗?
Possible to animate polygon fill using gganimate in R?
我有县级数据记录了 2002 年至 2018 年间该县首次检测到入侵性害虫的年份。我使用 ggplot2 和地图包创建了一张地图,该地图根据年份用颜色填充县多边形检测到有害生物。
** 有没有一种方法可以使用 gganimate 包来制作这张地图的动画,第一帧只填充检测日期为 2002 年的多边形,第二帧填充检测日期为 2003 年或更早的多边形(所以2002 年和 2003 年),检测日期为 2004 年或更早(2002 年、2003 年、2004 年)的第三帧,等等? **
澄清:我希望所有县多边形始终可见并最初用白色填充,并且动画的每一帧都会根据检测年份添加县填充。
我试过将 transition_reveal(data$detect_year)
与静态图一起使用,但出现 "along data must either be integer, numeric, POSIXct, Date, difftime, orhms".
错误
下面是一些可重现示例的代码:
library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df$detection_year <- NA
# Add random detection year to each county
years <- 2002:2006
map_list <- split(map_df, f = map_df$subregion)
map_list <- map(map_list, function(.x) {
.x$detection_years <- mutate(.x, detection_years = sample(years, 1))
})
# collapse list back to data frame
map_df <- bind_rows(map_list)
map_df$detection_years <- as.factor(map_df$detection_years)
# Make plot
static_plot <- ggplot(map_df,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(data = map_df, color = "black", aes(fill = detection_years)) +
scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_years))),
name = "Year EAB First Detected") +
theme_void() +
coord_fixed(1.3)
animate_plot <- static_plot +
transition_reveal(detection_years)
如果可以用 gganimate 做到这一点,我愿意,但如果有人有想法,我也愿意接受其他解决方案。
可能是这样,但我不确定这是预期的输出。
我更改了您的代码,可能您不需要 split
。我使用 group_by
为每个地区分配了年份。
set.seed(42)
years <- 2002:2006
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df <- map_df %>%
group_by(subregion) %>%
mutate(detection_year = sample(years,1))
对于转换,您需要定义 id
,此处与分组(subregion
或 group
)相同,并为转换定义正确的日期格式(along
) 变量(我用 lubridate::year()
)
# Make plot
static_plot <- ggplot(map_df,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(color = "black", aes(fill = as.factor(detection_year))) +
scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_year))),
name = "Year EAB First Detected") +
theme_void() +
coord_fixed(1.3)
animate_plot <- static_plot +
transition_reveal(subregion, # same as the group variable
lubridate::year(paste0(detection_year, "-01-01"))) # move along years
这个适合你吗?
在从@RLave 得到几乎可以满足我要求的答案并花一点时间阅读文档后,我找到了一种方法来满足我的要求。看起来不是很干净,但是可以用。
基本上,我为动画中需要帧的每一年都创建了数据帧的副本。然后,对于我想要制作动画的每一年的检测,我编辑了数据框副本中的 detection_year
变量,以便在感兴趣的年份或更早的年份进行检测的任何县都保留其值,并且任何县都有尚未检测到转换为我绘制为白色的值。这确保始终绘制所有县。然后我需要使用 transition_manual
以及我为原始数据帧的每个副本提供的唯一 ID 来确定动画的顺序。
library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
years <- 2002:2006
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df <- map_df %>%
group_by(subregion) %>%
mutate(detection_year = sample(years,1))
animate_data <- data.frame()
for(i in 2002:2006){
temp_dat <- map_df %>%
mutate(detection_year = as.numeric(as.character(detection_year))) %>%
mutate(detection_year = case_when(
detection_year <= i ~ detection_year,
detection_year > i ~ 2001
),
animate_id = i - 2001
)
animate_data <- bind_rows(animate_data, temp_dat)
}
animate_data$detection_year <- as.factor(as.character(animate_data$detection_year))
# Make plot
static_plot <- ggplot(animate_data,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(data = animate_data, color = "black", aes(fill = detection_year)) +
scale_fill_manual(values = c("white",
terrain.colors(n = 5)),
name = "Year First Detected") +
theme_void() +
coord_fixed(1.3) #+
facet_wrap(~animate_id)
animate_plot <- static_plot +
transition_manual(frames = animate_id)
animate_plot
我有县级数据记录了 2002 年至 2018 年间该县首次检测到入侵性害虫的年份。我使用 ggplot2 和地图包创建了一张地图,该地图根据年份用颜色填充县多边形检测到有害生物。
** 有没有一种方法可以使用 gganimate 包来制作这张地图的动画,第一帧只填充检测日期为 2002 年的多边形,第二帧填充检测日期为 2003 年或更早的多边形(所以2002 年和 2003 年),检测日期为 2004 年或更早(2002 年、2003 年、2004 年)的第三帧,等等? ** 澄清:我希望所有县多边形始终可见并最初用白色填充,并且动画的每一帧都会根据检测年份添加县填充。
我试过将 transition_reveal(data$detect_year)
与静态图一起使用,但出现 "along data must either be integer, numeric, POSIXct, Date, difftime, orhms".
下面是一些可重现示例的代码:
library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df$detection_year <- NA
# Add random detection year to each county
years <- 2002:2006
map_list <- split(map_df, f = map_df$subregion)
map_list <- map(map_list, function(.x) {
.x$detection_years <- mutate(.x, detection_years = sample(years, 1))
})
# collapse list back to data frame
map_df <- bind_rows(map_list)
map_df$detection_years <- as.factor(map_df$detection_years)
# Make plot
static_plot <- ggplot(map_df,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(data = map_df, color = "black", aes(fill = detection_years)) +
scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_years))),
name = "Year EAB First Detected") +
theme_void() +
coord_fixed(1.3)
animate_plot <- static_plot +
transition_reveal(detection_years)
如果可以用 gganimate 做到这一点,我愿意,但如果有人有想法,我也愿意接受其他解决方案。
可能是这样,但我不确定这是预期的输出。
我更改了您的代码,可能您不需要 split
。我使用 group_by
为每个地区分配了年份。
set.seed(42)
years <- 2002:2006
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df <- map_df %>%
group_by(subregion) %>%
mutate(detection_year = sample(years,1))
对于转换,您需要定义 id
,此处与分组(subregion
或 group
)相同,并为转换定义正确的日期格式(along
) 变量(我用 lubridate::year()
)
# Make plot
static_plot <- ggplot(map_df,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(color = "black", aes(fill = as.factor(detection_year))) +
scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_year))),
name = "Year EAB First Detected") +
theme_void() +
coord_fixed(1.3)
animate_plot <- static_plot +
transition_reveal(subregion, # same as the group variable
lubridate::year(paste0(detection_year, "-01-01"))) # move along years
这个适合你吗?
在从@RLave 得到几乎可以满足我要求的答案并花一点时间阅读文档后,我找到了一种方法来满足我的要求。看起来不是很干净,但是可以用。
基本上,我为动画中需要帧的每一年都创建了数据帧的副本。然后,对于我想要制作动画的每一年的检测,我编辑了数据框副本中的 detection_year
变量,以便在感兴趣的年份或更早的年份进行检测的任何县都保留其值,并且任何县都有尚未检测到转换为我绘制为白色的值。这确保始终绘制所有县。然后我需要使用 transition_manual
以及我为原始数据帧的每个副本提供的唯一 ID 来确定动画的顺序。
library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
years <- 2002:2006
map_df <- map_data("county") %>%
filter(region == "minnesota")
map_df <- map_df %>%
group_by(subregion) %>%
mutate(detection_year = sample(years,1))
animate_data <- data.frame()
for(i in 2002:2006){
temp_dat <- map_df %>%
mutate(detection_year = as.numeric(as.character(detection_year))) %>%
mutate(detection_year = case_when(
detection_year <= i ~ detection_year,
detection_year > i ~ 2001
),
animate_id = i - 2001
)
animate_data <- bind_rows(animate_data, temp_dat)
}
animate_data$detection_year <- as.factor(as.character(animate_data$detection_year))
# Make plot
static_plot <- ggplot(animate_data,
aes(x = long,
y = lat,
group = group)) +
geom_polygon(data = animate_data, color = "black", aes(fill = detection_year)) +
scale_fill_manual(values = c("white",
terrain.colors(n = 5)),
name = "Year First Detected") +
theme_void() +
coord_fixed(1.3) #+
facet_wrap(~animate_id)
animate_plot <- static_plot +
transition_manual(frames = animate_id)
animate_plot