Проблема с порядком кадров при создании GIF в R (библиотеки: "magick" и "purrr") - PullRequest
1 голос
/ 20 февраля 2020

Я создаю GIF-изображение в R. Во-первых, я использую al oop для создания и сохранения всех графиков в моем рабочем каталоге. Затем, используя библиотеки magick и purrr, я вызываю эти графики и присоединяюсь к ним, чтобы создать 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 ... и т. Д.]

enter image description here

1 Ответ

1 голос
/ 21 февраля 2020

Проблема с вашими именами файлов. «Какой-то логический порядок», который вы видели, связан с тем, как list.files сортирует имена файлов. Поскольку они являются строками, а не числами, они сортируются по первому символу, затем второму и т. Д. c. В вашем коде у вас есть 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. Проблема в том, что один начальный ноль добавляется к * 1007. * все ваших номеров. Чтобы получить правильное упорядочение, используйте str_pad из stringr, чтобы добавить переменное число ведущих нулей, чтобы получить 4 числа git. (см. здесь для других опций)

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))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...