微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当使用 coord_sf 指定 xlim、ylim 时,geom_sf 填充失败在尝试使用 av 包创建动画时寻找解决方法

如何解决当使用 coord_sf 指定 xlim、ylim 时,geom_sf 填充失败在尝试使用 av 包创建动画时寻找解决方法

ggplot2 存在一个已知问题,即在使用 geom_sf 指定 xlimylim 时,coord_sf 函数并不总是能正常工作。这个问题似乎是 Windows 特有的,当前的解决方法是将绘图保存为 .png。 See GitHub link: geom_sf fill missing when xlim,ylim set in coord_sf

我遇到的问题是我不是要制作静态图,而是使用 av 包将数百个图拼接在一起的动画。

基本上,我正在寻求帮助实施合适的解决方法,并且不需要保存或调用单个 .png 文件

任何想法或建议将不胜感激。

下图显示了我解决这个问题的动机,绘制了跨时间的飓风轨迹图

Example of geom_sf fill not working in Windows when xlim and ylim are specified in coord_sf

Stackoverflow 不允许发布视频,因此如果您想查看我的可复制代码输出,可以在此处查看我的原始 GitHub 帖子,该帖子可在此处找到...geom_sf,fill missing when xlim,ylim set in coord_sf in windows (follow-up to #3283) #4306

library(tidyverse)
library(sf)
library(av)

tracts <- read_sf("https://opendata.arcgis.com/datasets/230f9d23f6874be983901876cd600c4e_0.geojson") %>% 
  select(
    geometry,ALAND10,GEOID10
    )
st_crs(tracts)

set.seed(264)

v1 <- runif(1:dim(tracts)[1],.7,1.25)

tracts2 <- cbind(tracts,v1)

tracts_2017 <- tracts2 %>%
  mutate(season=2017)

tracts_2018 <- tracts2 %>%
  mutate(
    season=2018,ALAND10 = ALAND10*v1
    )
tracts3 <- rbind(tracts_2017,tracts_2018) 
  st_crs(tracts3)

makeplot1 <- function(){
  datalist1 <- split(
    tracts3,tracts3$season
  )
  datalist2 <- split(
    tracts3,tracts3$season
  )
  mapply(function(data1,data2){
    p1 <- ggplot() + 
      geom_sf(
        data = data1,aes(fill = ALAND10)
      ) +
      geom_sf(
        data = data2 %>% st_union(),fill = alpha("red",0.4),color = alpha("red",0.4)
      ) +
      coord_sf(
        ylim = c( 43.04,43.07),xlim = c(-76.14,-76.10),clip = "on",expand = F
      )
    print(p1)
    
    },datalist1,datalist2
  ) 
}

makeplot2 <- function(){
  datalist1 <- split(
    tracts3,data2){
    p2 <- ggplot() + 
      geom_sf(
        data = data1,0.4)
      ) 
    print(p2)
    
  },datalist2
  ) 
}

video_file1 <- file.path(tempdir(),'Tracts1.mp4')
av::av_capture_graphics(makeplot1(),video_file1,vfilter='framerate=fps=10')
av::av_media_info(video_file1)
utils::browseURL(video_file1)

video_file2 <- file.path(tempdir(),'Tracts2.mp4')
av::av_capture_graphics(makeplot2(),video_file2,vfilter='framerate=fps=10')
av::av_media_info(video_file2)
utils::browseURL(video_file2)

解决方法

正如 Thomas Lin Pedersen 在您链接的 github 问题中所建议的那样,解决方案是在 Windows 机器上使用 png(...,type = 'cairo') 设备。如果您阅读 ?av::av_capture_graphics() 处的文档,您会看到 ... 参数可用于将参数传递给 png() 函数。因此,我建议完全这样做:

library(tidyverse)
library(sf)
library(av)

tracts <- read_sf("https://opendata.arcgis.com/datasets/230f9d23f6874be983901876cd600c4e_0.geojson") %>% 
  select(
    geometry,ALAND10,GEOID10
  )
st_crs(tracts)

set.seed(264)

v1 <- runif(1:dim(tracts)[1],.7,1.25)

tracts2 <- cbind(tracts,v1)

tracts_2017 <- tracts2 %>%
  mutate(season=2017)

tracts_2018 <- tracts2 %>%
  mutate(
    season=2018,ALAND10 = ALAND10*v1
  )
tracts3 <- rbind(tracts_2017,tracts_2018) 
st_crs(tracts3)

makeplot1 <- function(){
  datalist1 <- split(
    tracts3,tracts3$season
  )
  datalist2 <- split(
    tracts3,tracts3$season
  )
  mapply(function(data1,data2){
    p1 <- ggplot() + 
      geom_sf(
        data = data1,aes(fill = ALAND10)
      ) +
      geom_sf(
        data = data2 %>% st_union(),fill = alpha("red",0.4),color = alpha("red",0.4)
      ) +
      coord_sf(
        ylim = c( 43.04,43.07),xlim = c(-76.14,-76.10),clip = "on",expand = F
      )
    print(p1)
    
  },datalist1,datalist2
  ) 
}

video_file1 <- file.path(tempdir(),'Tracts1.mp4')
av::av_capture_graphics(makeplot1(),video_file1,vfilter='framerate=fps=10',type = "cairo")
av::av_media_info(video_file1)
utils::browseURL(video_file1)

此外,

目前的工作涉及将绘图保存为 .png。

正是 av::av_capture_graphics() 在幕后所做的事情,也是 gganimate 包正在做的事情。

最后,我建议对您的色标设置固定限制,因为这似乎在帧之间发生变化,使任何解释复杂化。 gganimate 包很好地说明了这些细节。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。