gganimateを使ってみた
以下の記事を参考にgganimateを使ってみました。
[R]アニメーションで動くグラフを作る方法メモ - Qiita
やったこと
- 国別の1人当たりGDPを棒グラフにする。
- gganimateを使って年ごとに棒グラフを表示する。
データ
World BankのHPから取得しました。2017年までの1人当たりGDPが取得できます。
ダウンロードしたデータはそのまま使わず、ある程度エクセルで絞ってから使用しました。読み込み前のcsvファイルをこちらに置いておきます。
hadadada00
※gdp.csvを右クリックで保存してください。
コード
library(tidyverse) library(gganimate) library(gifski) ### import csv gdp <- read.csv("./gdp.csv") ### data transformation # remove unncecessary columns and rows gdp <- gdp %>% filter(Indicator.Name == "GDP per capita (current US$)") %>% select(-Country.Code, -Indicator.Code, -Indicator.Name) # transform data structure gdp <- gdp %>% gather(-Country.Name, key = "year", value = "gdp_per_capita") # remove "X" before year gdp <- gdp %>% mutate(year = as.integer(substr(year, 2, 5))) # countries list which will be displayed in the graph countries <- gdp %>% filter(year == 2017) %>% filter(rank(-gdp_per_capita) <= 30) %>% select(Country.Name) %>% unlist() # remove unncesessary countries' rows # and NA gdp_per_capita rows # and 2018 data gdp <- gdp %>% filter(Country.Name %in% countries) %>% filter(!is.na(gdp_per_capita)) %>% filter(year != 2018) # add order variable for sort x axix gdp <- gdp %>% arrange(year, gdp_per_capita) %>% mutate(order = 1:n()) ### data visualisation # make graph graph <- gdp %>% ggplot(aes(x = order, y = gdp_per_capita, fill=factor(ifelse(Country.Name =="Japan","Highlighted","Normal")))) + geom_bar(stat = "identity", alpha = 0.5, show.legend = FALSE) + labs(title = "year: {closest_state}", x = "Country", y = "GDP per capita (current US$") + scale_x_continuous(breaks=gdp$order, labels=gdp$Country.Name) + ylim(c(0, 125000)) + theme(axis.text.x = element_text(angle = 90, hjust = 1)) + transition_states(year, transition_length = 2, state_length = 1) + view_follow(fixed_y = TRUE) + ease_aes("linear") animate(graph, nframes = 300) anim_save("gdp_per_capita.gif")
工夫した点は以下2点です。
- 年ごとに1人当たりGDPの順で並び替えている
- 日本のグラフだけ色を変えている
年ごとに1人当たりGDPの順で並び替えている
1人当たりGDPを昇順で左から並べているため、毎年x軸(国名)の順番が変わります。そのため、以下の箇所で工夫をしています。
# add order variable for sort x axix gdp <- gdp %>% arrange(year, gdp_per_capita) %>% mutate(order = 1:n()) # make graph graph <- gdp %>% ggplot(aes(x = order, y = gdp_per_capita, fill=factor(ifelse(Country.Name =="Japan","Highlighted","Normal")))) + ... scale_x_continuous(breaks=gdp$order, labels=gdp$Country.Name) +
ggplotとgganimateの処理は独立しているため、gganimateのフレームごとにggplotのsortをするような処理は無理なようです。
そのため、事前にyear, gdp_per_capitaでソートして連番(order)を振り、描画の順番を決めておきます。
次に、ggplotのx軸の設定をorderにし、scale_x_continuous内でorderのラベルをCountry.Nameに変更しています。
年毎にgdp_per_capitaに応じて国の並び替えをするのではなく、事前に用意した順番(order)通りに棒グラフを並べ、それに対応する国名のラベルを上書きするイメージです。
このやり方は以下を参考にしました。
r - How does gganimate order an ordered bar time-series? - Stack Overflow
日本のグラフだけ色を変えている
ポイントは以下です。fillを指定するときにifelseで条件指定しています。
graph <- gdp %>% ggplot(aes(x = order, y = gdp_per_capita, fill=factor(ifelse(Country.Name =="Japan","Highlighted","Normal")))) +
以下の記事を参考にしました。
r - change color of only one bar in ggplot - Stack Overflow
実行結果
以下のgifアニメ(gdp_per_capita.gif)が出来ます。
ラベルや動きの微調整が必要ですが、やりたいことが概ねできたため、これで終了にしようと思います。
なお、国名が見づらいためcood_flipでx軸とy軸を反転させようとしましたが、軸の表示が上手くいかなかったため、断念しました。
以上