在 R 中创建 GIF 时出现帧顺序问题(库:“magick”和“purrr”)

Posted

技术标签:

【中文标题】在 R 中创建 GIF 时出现帧顺序问题(库:“magick”和“purrr”)【英文标题】:Problem with order of frames when creating a GIF in R (Libraries: "magick" and "purrr") 【发布时间】:2020-06-04 22:44:17 【问题描述】:

我正在R 中创建一个 GIF 图像。首先,我使用循环在我的工作目录中创建并保存所有绘图。接下来,使用库 magickpurrr 我调用这些图并加入它们以创建一个 GIF。我的问题如下:

创建 GIF 时,帧的顺序不正确。每个情节的标题中都有数字大小写,因此可以看出它们的顺序不正确。这是我的代码:

# my df (result) is all possible combinations of cumulative frequency for # a 5 likert scale where each row sum is 1 along all its levels.
setwd(\myworkingdirectory...)
library(dplyr)
library(magick)
library(purrr)

values <- seq(0, 1, by=0.1)
values
df <- expand.grid(A1 = values, A2 = values, A3 = values, A4 = values, A5 = values)
df$TestSum <- rowSums(df)
result <- df[df$TestSum == 1, 1:5]
colnames(result) <- c("F1","F2","F3","F4","F5")
rownames(result) <- c(1:nrow(result))

colnames(result) <- c("F1","F2","F3","F4","F5")
> head(result)
   F1  F2 F3 F4 F5
1 1.0 0.0  0  0  0
2 0.9 0.1  0  0  0
3 0.8 0.2  0  0  0
4 0.7 0.3  0  0  0
5 0.6 0.4  0  0  0
6 0.5 0.5  0  0  0

#to simplify for the example...
result <- result[seq(1,nrow(result),9),]

Likert_plots <- function(Yr)
  png(filename = sprintf("%i%i.png",00,Yr))
  barplot(as.matrix(result[Yr,]), ylim = c(0,1), main = paste0("Case ", Yr), ylab = "Cumulative Freq.", xlab = "Levels")
  print(paste0("saving plot ", Yr))
  dev.off()


for (i in 1:nrow(result)) 
  Likert_plots(i)


list.files(pattern = "*.png", full.names = T) %>% 
  map(image_read) %>% 
  image_join() %>% 
  image_animate(fps=2) %>% 
  image_write("name.gif")

这些图的名称是正确的,我认为它们不是问题(例如:“01.png”、“02.png”...“0103.png”)我认为问题可能出在函数中调用它们,例如:list.files()map()image_join()。可能,这个可能的“有罪”功能不尊重订购号,而是另一个订单。如果是这样:我可以改变它吗?

感谢您对此提供的任何帮助。这里的GIF看问题。请注意,顺序遵循一些逻辑顺序: [1, 10, 100, 101, 102, 103, 2 , 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3, 31, 32, 33, 34, 35, 36, 37, 38, 39, 4, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 5, 50, 51 ..., 6, 60, 61 ... 7, 70, 71 ... 8, 80, 81 ...等等]

【问题讨论】:

请显示更多步骤。您如何读取文件名、使用哪个函数以及每个步骤的输出是什么?确实问题可能存在 如果您将绘图写入带有数字的文件,您必须确保您有前导零。 001, 002, 003, ... 010, 011, 012, ...., 100, 101, 102。然后它们将被正确排序。查看sprintf 以创建前导零。 代码已更新为我的所有步骤 (@Chelmy88)。此外,我尝试过使用@ricoderks 方法......(可以在上面的代码中看到)。结果是一样的。 @pgcudahy 回答对你有用吗? 刚刚试了一下,效果很好。谢谢大家。 【参考方案1】:

问题在于您的文件名。您看到的“某种逻辑顺序”来自list.files 如何对文件名进行排序。由于它们是字符串而不是数字,因此它们会根据第一个字符进行排序,然后是第二个字符,依此类推。在您的代码中,您有 png(filename = sprintf("%i%i.png",00,Yr)),我将其简化为 purrr::map_chr(1:105, ~ sprintf("%i%i.png",00,.))。如果你对输出进行排序(记住是一个字符串,而不是一个整数),你会得到

purrr::map_chr(1:105, ~ sprintf("%i%i.png",00,.)) %>% sort %>% head
#> [1] "01.png"   "010.png"  "0100.png" "0101.png" "0102.png" "0103.png"

您的 gif 的组装顺序是什么。问题是一个前导零被添加到您的所有数字前面。要获得正确的排序,请使用 stringr 中的 str_pad 添加可变数量的前导零以产生 4 位数字。 (其他选项见here)

purrr::map_chr(1:105, ~ stringr::str_pad(., 4, pad = "0")) %>% paste(".png", sep="") %>% sort %>% head
#> [1] "0001.png" "0002.png" "0003.png" "0004.png" "0005.png" "0006.png"

因此,将您的 png(filename = sprintf("%i%i.png",00,Yr)) 更改为 png(filename = paste(stringr::str_pad(Yr, 4, pad = "0"), ".png", sep=""))

有一种方法仍然可以使用sprintf,但我认为它的可读性要差得多。使用png(filename = sprintf("%04d.png",Yr))

【讨论】:

以上是关于在 R 中创建 GIF 时出现帧顺序问题(库:“magick”和“purrr”)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中创建动画 gif?

在 R 中创建我自己的蜘蛛图而不使用任何库

在delphi 2009 中创建一个gif 动画文件?

如何在 .net 中创建动画 gif

在 JavaScript 中创建 GIF 和 PNG

在 Cocoa 中创建动画 GIF - 定义帧类型