はじめに
gganimate
パッケージについて理解したいシリーズです。
この記事では、1次元ランダムウォークのアニメーションをR言語で作成します。
【他の内容】
【目次】
1次元ランダムウォーク
gganimate
パッケージを利用して、1次元のランダムウォークのアニメーション(gif画像)を作成します。transition_reveal()
については、transition_reveal.Rmdを参照してください。
利用するパッケージを読み込みます。
# 利用パッケージ library(gganimate) library(tidyverse)
1サンプル
まずは、1個のサンプルを描画します。
-1
か1
をランダムに生成します。
# 試行回数を指定 max_iter <- 100 # ランダムに値を生成 random_vec <- sample(x = c(-1, 1), size = max_iter, replace = TRUE) random_vec[1:10]
## [1] -1 1 1 -1 1 1 -1 -1 -1 -1
試行回数を指定して、正方向の移動(1
)または負方向の移動(-1
)をランダムに生成します。
生成した値をデータフレームに格納して、過去の値の合計を求めます。
# 試行ごとに集計 random_df <- tibble::tibble( iteration = 0:max_iter, random_val = c(0, random_vec) ) %>% dplyr::mutate(value = cumsum(random_val)) # 各試行までの合計 head(random_df)
## # A tibble: 6 x 3 ## iteration random_val value ## <int> <dbl> <dbl> ## 1 0 0 0 ## 2 1 -1 -1 ## 3 2 1 0 ## 4 3 1 1 ## 5 4 -1 0 ## 6 5 1 1
0回目の結果(スタート地点・原点)に相当する行を加えておきます。
n回目の位置(点)は、0回目からn回目の和で決まります。このような和を累積和と言い、cumsum()
で計算できます。random_val
列の1行目から各行までの和をcumsum()
で計算してvalue
列とします。
折れ線グラフのアニメーションを作成します。
# 1次元ランダムウォークを作図 anim <- ggplot(random_df, aes(x = iteration, y = value)) + geom_point(color = "hotpink", size = 5) + # 散布図 geom_path(color = "hotpink", size = 1, alpha = 0.5) + # 折れ線 geom_hline(yintercept = 0, color = "red", linetype = "dashed") + # 水平線 gganimate::transition_reveal(along = iteration) + # フレーム labs(title = "Random Walk", subtitle = "iter : {frame_along}") # gif画像を作成 gganimate::animate(plot = anim, nframes = max_iter+1, fps = 10)
目安として、期待値()の線を引いています。
複数サンプル
続いて、複数個のサンプルを同時に描画します。
-1
か1
をランダムに生成します。
# 試行回数を指定 max_iter <- 100 # サンプルサイズを指定 sample_size <- 10 # ランダムに値を生成 random_vec <- sample(x = c(-1, 1), size = max_iter*sample_size, replace = TRUE) random_vec[1:10]
## [1] 1 1 -1 1 -1 1 -1 1 1 1
試行回数max_iter
とサンプルサイズsample_size
を指定して、max_iter * sample_size
個の値を生成します。
生成した値をデータフレームに格納します。
# 元になるデータフレームを確認 tibble::tibble( iteration = rep(0:max_iter, each = sample_size), id = rep(1:sample_size, times = max_iter+1), random_val = c(rep(0, sample_size), random_vec) ) %>% dplyr::filter(iteration == 1) %>% # 1回目の結果を表示 head()
## # A tibble: 6 x 3 ## iteration id random_val ## <int> <int> <dbl> ## 1 1 1 1 ## 2 1 2 1 ## 3 1 3 -1 ## 4 1 4 1 ## 5 1 5 -1 ## 6 1 6 1
全てのサンプルに対して0回目の結果に相当する行を加えます。
また、random_vec
の1番目の要素をサンプル1の1回目の結果、2番目の要素をサンプル2の1回目の結果と続けて、さらにsample_size + 1
番目の要素をサンプル1の2回目の結果と続けて割り当てることにします。
0
からmax_iter
までの整数をそれぞれsample_size
個に複製して、試行回数(iteration
)列とします。
1
からsample_size
までの整数をmax_iter + 1
回繰り返して、サンプル番号(id
)列とします。
sample_size
個の0
の後にrandom_vec
を続けて、乱数(random_val
)列とします。
サンプルごとに過去の値を合計します。
# 試行ごとに集計 random_df <- tibble::tibble( iteration = rep(0:max_iter, each = sample_size), id = rep(1:sample_size, times = max_iter+1) %>% as.factor(), random_val = c(rep(0, sample_size), random_vec) ) %>% dplyr::group_by(id) %>% # サンプルごとにグループ化 dplyr::mutate(value = cumsum(random_val)) %>% # 各試行までの合計 dplyr::group_by() # グループ化の解除 # 3サンプルの3回目までの結果 random_df %>% dplyr::filter(iteration <= 3, id %in% 1:3)
## # A tibble: 12 x 4 ## iteration id random_val value ## <int> <fct> <dbl> <dbl> ## 1 0 1 0 0 ## 2 0 2 0 0 ## 3 0 3 0 0 ## 4 1 1 1 1 ## 5 1 2 1 1 ## 6 1 3 -1 -1 ## 7 2 1 -1 0 ## 8 2 2 -1 0 ## 9 2 3 -1 -2 ## 10 3 1 1 1 ## 11 3 2 -1 -1 ## 12 3 3 1 -1
作図用に、サンプル番号(id
列の値)を因子型にしておきます。
id
列が同じ値でグループ化して、サンプルごとにcumsum()
で累積和を計算します。
アニメーションを作成します。
# 2次元ランダムウォークを作図 anim <- ggplot(random_df, aes(x = iteration, y = value, color = id)) + geom_point(size = 5, show.legend = FALSE) + # 散布図 geom_path(size = 1, alpha = 0.5, show.legend = FALSE) + # 折れ線 geom_hline(yintercept = 0, color = "red", linetype = "dashed") + # 水平線 gganimate::transition_reveal(along = iteration) + # フレーム labs(title = "Random Walk", subtitle = "iter : {frame_along}") # gif画像を作成 gganimate::animate(plot = anim, nframes = max_iter+1, fps = 10)
sample_size
個の折れ線グラフが描画されます。
最終結果は次のようになります。
# 最終結果 random_df %>% dplyr::filter(iteration == max_iter) %>% ggplot() + geom_point(mapping = aes(x = iteration, y = value, color = id), size = 5, show.legend = FALSE) + # 散布図 geom_path(data = random_df, mapping = aes(x = iteration, y = value, color = id), size = 1, alpha = 0.5, show.legend = FALSE) + # 折れ線 geom_hline(yintercept = 0, color = "red", linetype = "dashed") + # 水平線 labs(title = "Random Walk", subtitle = paste0("iter : ", max_iter))
以上で、1次元ランダムウォークを作図できました。試行回数(時間)方向の変化も合わせて可視化しているので2次元に移動していますが、あくまで縦軸に対してランダムに移動しています。次は、x軸とy軸の2方向へ移動する場合を扱います。
おわりに
transition_reveal()
の記事の一部として書き始めたのですが、充実したので別の記事どころか3記事になりました。というわけで続きます。
【次の内容】