web-dev-qa-db-ja.com

積み上げて並べた複数のgananimateプロット

フレーム数が同じである4つのアニメーションプロットがあり、そのうち3つをスタックし、4つ目を3つのスタックしたアニメーションの右側に配置します。通常、grid.arrangeのようなものを使用しますが、それはgganimateでは機能しないようです。

ここのコードに基づいて次のコードを取得しました: https://github.com/thomasp85/gganimate/wiki/Animation-Composition

a_mgif <- image_read(a_gif)
b_mgif <- image_read(b_gif)
c_mgif <- image_read(c_gif)
d_mgif <- image_read(d_gif)

new_gif <- image_append(c(a_mgif[1], b_mgif[1], c_mgif[1], d_mgif[1]), stack = TRUE)

for(i in 2:100){
  combined <- image_append(c(a_mgif[i], b_mgif[i], c_mgif[i], d_mgif[i]), stack = TRUE)
  new_gif <- c(new_gif, combined)
}

magick::image_write(new_gif, path="animation.1.gif")

これは正常に動作し、4つの積み重ねられたアニメーションプロットを生成します。次のように、最初の3つのスタックプロットの右側に4番目のプロットが表示されるように変更しようとしました。

new_gif.1 <- image_append(c(a_mgif[1], b_mgif[1], c_mgif[1]), stack = TRUE)
new_gif.2 <- image_append(c(new_gif.1, d_mgif[1]), stack = FALSE)

for(i in 2:100){
  combined.1 <- image_append(c(a_mgif[i], b_mgif[i], c_mgif[i]), stack = TRUE)
  combined.2 <- image_append(c(combined.1, d_mgif[i]), stack = FALSE)
  new_gif.2 <- c(new_gif.2,combined.2)
}

magick::image_write(new_gif.2, path="animation.2.gif")

これは、ファイルを書き込むまでは機能しているようです。ファイルの書き込みには永遠に時間がかかり、何時間も実行しても完了しませんでしたが、すべてがスタックされている最初のバージョンは1分以内に書き込まれるため、明らかに問題があります。どちらの例でもまったく同じデータ/プロットです。ここで何がうまくいかないかについてのアイデアはありますか?

6
Abdel

私にとってうまくいったのは、image_append呼び出しをimage_flattenにラップすることでした。また、まずimg1とimg4を水平方向に組み合わせてから、これをimg2とimg3と積み重ねました。

ここでは例から2つのアニメーションのみをリサイクルしましたが、このソリューションは4つの独立したアニメーションでも機能するはずです-少なくとも私にとっては、ImageMagick 6.9.10.23とmagick_2.3を使用したR4.0では、約3分とおそらく630かかります一時ストレージのMB:

library(dplyr)
library(ggplot2)
library(magick)
library(gganimate)

A <- rnorm(100,50,10)
B <- rnorm(100,50,10)
DV <- c(A,B)
IV <- rep(c("A","B"), each=100)
sims <- rep(rep(1:10, each=10), 2)
df <- data.frame(sims, IV, DV)

means_df <- df %>%
    group_by(sims,IV) %>%
    summarize(means=mean(DV),
              sem = sd(DV)/sqrt(length(DV)))

stats_df <- df %>%
    group_by(sims) %>%
    summarize(ts = t.test(DV~IV,var.equal=TRUE)$statistic)

a <- ggplot(means_df, aes(x = IV,y = means, fill = IV)) +
    geom_bar(stat = "identity") +
    geom_point(aes(x = IV, y = DV), data = df, alpha = .25) +
    geom_errorbar(aes(ymin = means - sem, ymax = means + sem), width = .2) +
    theme_classic() +
    transition_states(
        states = sims,
        transition_length = 2,
        state_length = 1
    ) + 
    enter_fade() + 
    exit_shrink() +
    ease_aes('sine-in-out')

a_gif <- animate(a, width = 240, height = 240)

b <- ggplot(stats_df, aes(x = ts))+
    geom_vline(aes(xintercept = ts, frame = sims))+
    geom_line(aes(x=x,y=y),
              data = data.frame(x = seq(-5,5, .1),
                                y = dt(seq(-5,5, .1), df = 18))) +
    theme_classic() +
    ylab("density") +
    xlab("t value") +
    transition_states(
        states = sims,
        transition_length = 2,
        state_length = 1
    ) +
    enter_fade() + 
    exit_shrink() +
    ease_aes('sine-in-out')

b_gif <- animate(b, width = 240, height = 240)

c_gif <- animate(b, width = 240, height = 240)
d_gif <- animate(a, width = 240, height = 240)

i=1
combined <- image_append(c(a_gif[i], d_gif[i]))
new_gif <- image_append(c(image_flatten(combined),
                          b_gif[i], c_gif[i]), stack=TRUE)

for(i in 2:100){
    combined <- image_append(c(a_gif[i], d_gif[i]))
    fullcombined <- image_append(c(image_flatten(combined), 
                                   b_gif[i], c_gif[i]), stack=TRUE)
    new_gif <- c(new_gif, fullcombined)
}

image_write(new_gif, format="gif", path="animation.2.gif")

編集:代替または、cowplotを使用してプロットを配置し、ループ内の個々のフレームを生成してから、gifskiを使用してアニメーションを作成できます。 draw_imageに座標を追加できるため、画像の配置の点でさらに柔軟です(対応するcowplotの例を参照)。以下は簡単なグリッドの例です:

library(dplyr)
library(ggplot2)
library(magick)
library(gganimate)
library(cowplot)
library(gifski)

A <- rnorm(100,50,10)
B <- rnorm(100,50,10)
DV <- c(A,B)
IV <- rep(c("A","B"), each=100)
sims <- rep(rep(1:10, each=10), 2)
df <- data.frame(sims, IV, DV)

means_df <- df %>%
    group_by(sims,IV) %>%
    summarize(means=mean(DV),
              sem = sd(DV)/sqrt(length(DV)))

stats_df <- df %>%
    group_by(sims) %>%
    summarize(ts = t.test(DV~IV,var.equal=TRUE)$statistic)

a <- ggplot(means_df, aes(x = IV,y = means, fill = IV)) +
    geom_bar(stat = "identity") +
    geom_point(aes(x = IV, y = DV), data = df, alpha = .25) +
    geom_errorbar(aes(ymin = means - sem, ymax = means + sem), width = .2) +
    theme_classic() +
    transition_states(
        states = sims,
        transition_length = 2,
        state_length = 1
    ) + 
    enter_fade() + 
    exit_shrink() +
    ease_aes('sine-in-out')

a_gif <- animate(a, width = 240, height = 240)

b <- ggplot(stats_df, aes(x = ts))+
    geom_vline(aes(xintercept = ts, frame = sims))+
    geom_line(aes(x=x,y=y),
              data = data.frame(x = seq(-5,5, .1),
                                y = dt(seq(-5,5, .1), df = 18))) +
    theme_classic() +
    ylab("density") +
    xlab("t value") +
    transition_states(
        states = sims,
        transition_length = 2,
        state_length = 1
    ) +
    enter_fade() + 
    exit_shrink() +
    ease_aes('sine-in-out')

b_gif <- animate(b, width = 240, height = 240)

c_gif <- animate(b, width = 240, height = 240)
d_gif <- animate(a, width = 240, height = 240)

tdir <- tempdir()
for(i in 1:100){
    new_gif <- plot_grid(ggdraw() + draw_image(a_gif[i], scale = 0.9), 
                         ggdraw() + draw_image(d_gif[i], scale = 0.9),
                         ggdraw() + draw_image(b_gif[i], scale = 0.9),
                         ggdraw(),
                         ggdraw() + draw_image(c_gif[i], scale = 0.9),
                         ncol=2)
    ggsave(
        filename = file.path(tdir, paste0("out_", sprintf("%03d", i), ".png")),
        plot = new_gif, width = 2.4, height = 3.6, device = "png")
}

png_files <- sort(list.files(path = tdir, pattern = "out_", full.names = TRUE))
gifski(png_files, gif_file = "out.gif", width = 480, height = 720, delay = .1,
       progress = TRUE)
2
user12728748