【问题标题】:Possible to animate polygon fill using gganimate in R?可以在 R 中使用 gganimate 对多边形填充进行动画处理吗?
【发布时间】:2019-07-26 05:25:07
【问题描述】:

我的县级数据记录了 2002 年至 2018 年间在该县首次检测到入侵性害虫的年份。我使用 ggplot2 和地图包创建了一张地图,该地图包根据害虫的年份用颜色填充县多边形被检测到。

**有没有办法使用 gganimate 包为这个地图制作动画,第一帧只填充检测日期为 2002 年的多边形,第二帧填充检测日期为 2003 年或更早的多边形(所以 2002 年和2003),用于检测日期为 2004 年或更早(2002、2003、2004)等的第三帧? ** 说明:我希望所有县多边形始终可见并最初填充为白色,并且动画的每一帧都会根据检测年份添加县的填充。

我尝试将transition_reveal(data$detect_year) 与静态图一起使用,但收到错误消息“沿数据必须是整数、数字、POSIXct、日期、difftime 或欧姆”。

以下是可重现示例的一些代码:

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 做到这一点,我愿意,但如果有人有想法,我也愿意接受其他解决方案。

【问题讨论】:

    标签: r ggplot2 gganimate


    【解决方案1】:

    在从@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
    

    【讨论】:

      【解决方案2】:

      可能是这样,但我不确定这是预期的输出。

      我更改了你的代码,可能你不需要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,这里与分组(subregiongroup)和转换(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
      

      这对你有用吗?

      【讨论】:

      • 感谢您的回复 - 我实际上无法让您的代码正常工作。它说它找不到对象“detection_year”。当我添加数据框源 (map_df$detection_year) 时,它告诉我“沿”参数必须是整数、数字、POSIXct、日期、difftime 或 hms。仅运行 year(paste0(...)) 代码,它看起来像返回一个数字向量,所以我不确定为什么会出现该错误。除此之外,这并不是我所希望的。我将在上面的帖子中澄清,但我想最初将所有县多边形显示为白色,并按年填充每个帧
      • @Jake,我刚刚检查过,我的工作很顺利,你能尝试一个新的会话吗?如果它仍然不起作用,请更新软件包。
      • 我开始了一个新会话,但仍然遇到相同的错误。我更新了我所有的包,也继续得到同样的错误。
      • 很抱歉,您能检查一下detection_year 的拼写吗?在transition_reveal 中你不应该使用map_df$,只是变量的名称。
      • 我能够让它在另一台计算机上工作。不确定为什么它不能在我当前的计算机上运行。
      猜你喜欢
      • 2019-08-31
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-09
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多