はだだだだ

定食にサラダは不要だと思う。

MENU

gganimateを使ってみた

以下の記事を参考にgganimateを使ってみました。

[R]アニメーションで動くグラフを作る方法メモ - Qiita

やったこと

  • 国別の1人当たりGDPを棒グラフにする。
  • gganimateを使って年ごとに棒グラフを表示する。

データ

World BankのHPから取得しました。2017年までの1人当たりGDPが取得できます。

Economy & Growth | Data

ダウンロードしたデータはそのまま使わず、ある程度エクセルで絞ってから使用しました。読み込み前の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軸を反転させようとしましたが、軸の表示が上手くいかなかったため、断念しました。

以上