在 R 中创建 GIF 时的帧顺序问题(库:"magick" 和 "purrr")

Problem with order of frames when creating a GIF in R (Libraries: "magick" and "purrr")

我正在 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()。可能,这个可能的 "guilty" 函数不考虑顺序号,而是考虑另一个顺序。那样的话:我可以改吗?

感谢您对此提供的任何帮助。这里的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 ...等等儿子]

问题出在您的文件名上。您看到的 "some logical order" 来自 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 的组装顺序是什么。问题是单个前导零被添加到 all 您的数字之前。要获得正确的排序,请使用 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))