0

我正在尝试使用 tmap 创建动画 GIF 并将其显示在我的 Shiny 应用程序中。当我将 tm_shape() + tm_polygons() 用于单个日期时,生成的图像总是可以的。但是,当我使用 tm_facets() 并将结果提供给 tmap_animation 时,生成的 GIF 具有随机的深绿色帧,如下所示。在此处输入图像描述

这是我使用生成动画的代码:

data(World)

confirmed = read.csv('./data/time_series_covid_19_confirmed.csv', stringsAsFactors = T) %>%
  select(-Province.State, -Country.Region) %>%
  pivot_longer(!c('Lat', 'Long', 'iso3'), names_to = 'date', values_to = 'confirmed') %>%
  mutate(date = as.Date(gsub('X', '', date), '%m.%d.%Y')) %>%
  group_by(iso3, date) %>%
  summarise(confirmed = sum(confirmed)) %>%
  mutate(perc_change = 100 * ifelse(
      lag(confirmed, default = 0) == 0 | confirmed < 1000 | lag(confirmed) > confirmed, 
      0, 
      (confirmed - lag(confirmed)) / lag(confirmed)
    )
  ) %>%
  inner_join(select(World, iso_a3, geometry), by=c('iso3' = 'iso_a3')) %>%
  st_sf()

conf_anim = confirmed %>%
  filter(date < '2020-02-28') %>%
  tm_shape() + tm_polygons('perc_change', style='cont') +
  # tm_fill('perc_change', palette='Blues', style='fixed', 
  #         breaks=c(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, Inf)) + tm_borders() +
  tm_facets(along='date', free.coords = F)

tmap_animation(conf_anim, filename = './www/conf_anim.gif', delay=50)

任何人都知道我该如何解决这个问题?

4

2 回答 2

1

我遇到过同样的问题。我在GitHub 问题选项卡上询问了它tmap,团队将其追溯到用于生成 gif 动画的gifski包的问题。tmap我发现gifski不使用tmap.

mtennekes 现在建议的解决方法是将动画保存为 mp4 而不是 gif,它使用av包:

tmap_animation(conf_anim, filename = './www/conf_anim.mp4', delay=50)

不是一个完整的修复程序,但希望它对您的直接应用有所帮助。

于 2021-03-11T10:19:43.160 回答
0

万一其他人为此苦苦挣扎,我可以使用 tmap、gifski(tmap 用于生成 GIF)、dplyr 和 png 库创建一个解决方法。这种方法并不快,并且以这种方式生成 GIF 可能需要很长时间。使用 MP4 格式而不是 GIF 提到的另一个答案 - 如果您可以选择这种方法,则此方法要快得多。

假设您有一个名为df_sf的 sf 对象,您尝试沿facet_along_col_str进行刻面,并且 tm_polygons 的第一个参数是polygon_col_str,下面是帮助您生成 GIF 的代码:

library(tmap)
library(gifski)
library(png)
library(dplyr)

generate_gif = function(sf_df, facet_along_col_str, polygon_col_str, gif_file, delay) {
  dims = get_dims(sf_df, facet_along_col_str, polygon_col_str)
  save_gif(get_maps(sf_df), height=dims[1], width=dims[2], delay=delay, gif_file=gif_file)
}

get_dims = function(sf_df, facet_along, polygon_col) {
  slice = st_drop_geometry(select(sf_df, !!as.symbol(map_slice_col)))[[1]][1]
  t = tm_shape(filter(sf_df, !!as.symbol(map_slice_col) == slice)) +
    tm_polygons(polygons_col)
  filename = tempfile(fileext='.png')
  tmap_save(t, filename=filename)
  dims = dim(readPNG(filename))
  file.remove(filename)

  return(dims)
}

get_maps = function(sf_df, facet_along, polygon_col) {
  slices = st_drop_geometry(select(sf_df, !!as.symbol(map_slice_col)))[[1]]
  slices = sort(unique(slices))
  for (i in 1:length(slices)) {
    t = tm_shape(filter(sf_df, !!as.symbol(facet_along) == slices[i])) +
      tm_polygons(polygon_col)
    print(t)
  }
}
于 2021-03-11T18:30:46.903 回答