将多个图表合并成一个GIF动画。

4
我正在尝试使用caTools包将多个图形合并成gif。
我的基本代码如下:
 for( i in 1:100){
     plot(....) // 绘制几个点和线,每次i略有变化
  }
我想将它们合并成一个gif,以便看到绘图的“演变”。
但是对于来自caTools的write.gif(),我需要提供一张图片作为输入。对于每个i,如何将绘图转换为图像而不
  1. 保存为中间步骤
  2. 依赖ImageMagick或类似的外部依赖项。
请随意指出是否重复。[在R中从一系列图形创建电影似乎没有回答这个问题]
编辑:基本上,这需要我们将绘图转换为矩阵。由于这很可能每次保存绘图时都会发生,因此应该不难。但是我无法掌握如何确切地做到这一点。

为什么限制使用外部软件? - hrbrmstr
也许“gridBase”包或“?par”函数可以帮助你。 - holzben
@hrbrmstr 主要是出于可移植性的原因。 - Sujay
@holzben :: gridBase似乎可以与par()选项一起使用。有什么提示可以用吗? - Sujay
1
@Sujay 我想不出有哪个操作系统无法使用ImageMagick或者没有二进制版本可用。 - hrbrmstr
@Sujay 这是真的,但我发现使用“par”可能会很棘手。“gridBase”和“gridExtra”更易于使用。这篇文章给出了一个很好的例子:https://dev59.com/RWkx5IYBdhLWcg3wA_1S - holzben
3个回答

8
我建议使用animation包和ImageMagick代替:
library(animation)
## make sure ImageMagick has been installed in your system
saveGIF({
  for (i in 1:10) plot(runif(10), ylim = 0:1)
})

否则,您可以尝试在这种方式中使用它(有很大的优化空间):
library(png)
library(caTools)
library(abind)

# create gif frames and write them to pngs in a temp dir 
dir.create(dir <- tempfile(""))
for (i in 1:8) {
  png(file.path(dir, paste0(sprintf("%04d", i), ".png")))
  plot(runif(10), ylim = 0:1, col = i)
  dev.off()
}

# read pngs, create global palette, convert rasters to integer arrays and write animated gif
imgs <- lapply(list.files(dir, full.names = T), function(fn) as.raster(readPNG(fn)))
frames <- abind(imgs, along = 3) # combine raster pngs in list to an array 
cols <- unique(as.vector(frames)) # determine unique colors, should be less then 257
frames <- aperm(array(match(frames, cols) - 1, dim = dim(frames)), c(2,1,3)) # replace rgb color codes (#ffffff) by integer indices in cols, beginning with 0 (note: array has to be transposed again, otherwise images are flipped) 
write.gif(
  image = frames, # array of integers 
  filename = tf <- tempfile(fileext = ".gif"), # create temporary filename
  delay = 100, # 100/100=1 second delay between frames 
  col = c(cols, rep("#FFFFFF", 256-length(cols))) # color palette with 256 colors (fill unused color indices with white) 
)

# open gif (windows)
shell.exec(tf)  

1
我正在寻找一种无需使用ImageMagick的解决方案。 - Sujay
请尝试使用黑白临时图像来检查其他可能性。 - lukeA
如果我导入PNG文件,如何保留原始颜色?@lukeA - Iris
谢谢@lukeA,但是确实还有很多优化的空间;) 顺便说一下,我在256-length(cols)方面遇到了问题,因为在我的情况下,length(cols)==291 - Iris
嗯,你是怎么创建你的图片的?GIF支持256种颜色。似乎save.gif只支持全局调色板,而不是每一帧都有一个调色板。也许可以使用k-means聚类将它们降到256个?总的来说,这是否值得努力还是有疑问的——ImageMagick显然是更容易的选择。 - lukeA
我有一个在R中用png()创建的PNG列表,它们应该只有255种颜色。我不知道额外的颜色是从哪里来的。但我认为,现在不必花时间解决这个问题,我将直接使用Imagemagick。 - Iris

1
这是您在寻找的内容吗?
   library(ggplot2)
   a <- 0:10
    df <- data.frame(a=a,b=a)
    steps <-function(end){
      a <- ggplot(df[1:end,], aes(a,b)) + 
        geom_point() + 
        scale_x_continuous(limits=c(0,10)) +
        scale_y_continuous(limits=c(0,10))
      print(a)
    }
    gif <- function() {
      lapply(seq(1,11,1), function(i) {
        steps(i)
      })
    }
    library(animation)
    saveGIF(gif(), interval = .2, movie.name="test.gif")

我收到了一个错误信息 Error in in_dir(owd, expr) : could not find function "trace.animate"。你的函数 trace.animate() 定义在哪里?@ttlngr - Iris
抱歉 @Iris,我从脚本中复制了那个...在 saveGIF() 中使用函数 gif()(如定义)而不是 trace.animate()。我已经编辑了我的回答。 - ttlngr
很不幸,我在使用你的答案时遇到了这个错误 https://dev59.com/54fca4cB1Zd3GeqPgDxs - Iris
你是否确认已安装ImageMagick?你尝试从Github获取动画包了吗? - ttlngr
ImageMagick已安装,我可以使用它。我发布的链接中的解决方案对我不起作用,因为“package 'devtools' is not available (for R version 3.0.1)”。 - Iris
那么,我看没有其他解决方案,只能升级到更新的R版本。我的版本是3.0.2。 - ttlngr

0

我喜欢@ttlngr的答案,但我想要更简单一点的东西(它仍然使用ImageMagick)。

saveGIF({
  for (i in 1:10){  
    a <- ggplot(df[1:i,], aes(a,b)) + 
      geom_point() + 
      scale_x_continuous(limits=c(0,10)) +
      scale_y_continuous(limits=c(0,10))
  print(a)}
}, interval = .2, movie.name="test.gif")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接