Sankey DiagramをnetworkD3とtidygraphで作る

[Survey Results: What Degree is Best for Data Science?](https://novyden.blogspot.com/2020/03/survey-results-what-degree-is-best-for.html)というブログポストを読んで、Sankey Diagramの存在を知りました。
ブログポストにもあるようにアンケートを取った時の回答の流れを可視化する際に効果的かもしれません。  

描画方法が気になり、調べてみたのでこのポストでまとめてみようと思います。

## Sankey Diagramとは

Wikipediaから引用すると、以下のような記載がありました。

> サンキー・ダイアグラム(英Sankey diagram)は工程間の流量を表現する図表である。矢印の太さで流れの量を表している。特にエネルギーや物資、経費等の変位を表す為に使われる。

`networkD3` packageの例では以下のような図が紹介されています。

![sankey_energy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162536/c9924f8b-d631-3a04-f6cd-12f8b803c5cf.png)

## 準備

### package

今回は以下のpackageを利用します。

``` R
library(tibble)
library(dplyr)
library(tidygraph)
library(networkD3)
```

### data

今回は組み込みのデータセットではなく、[IBM HR Analytics Employee Attrition & Performance](https://www.kaggle.com/pavansubhasht/ibm-hr-analytics-attrition-dataset)を利用します。データセットはKaggleのサイトからダウンロードすることができます。

``` R
# ローカルにcsvをダウンロードし、読み込む
ibm <- readr::read_csv("your/path/WA_Fn-UseC_-HR-Employee-Attrition.csv")

# 可視化した際にわかりやすいようにデータを加工
ibm_df <- ibm %>% 
  mutate(
    department = case_when(
      Department == "Human Resources" ~ "HR",
      Department == "Research & Development" ~ "R&D",
      TRUE ~ "Sales"
    ),
    overtime = if_else(OverTime == "Yes", "overtime", "no_overtime"),
    attrition = if_else(Attrition == "Yes", "attrition", "enrollment")
  )
```

## Sankey Diagramの作成

### 単純なパターン

まずはnodeの数が少ないパターンから可視化を行ってみます。  
`networkD3`packeageの`sankeyNetwork()`はedegeとnodeのデータが必要になるため、`tidygraph::as_tbl_graph()`を使ってデータを加工します。

``` R
ibm_edge_ls <- ibm_df %>% 
  count(department, Attrition)

g <- as_tbl_graph(ibm_edge_ls, directed = FALSE)

# networkD3をつかうのでindexを0始まりに変更
edge <- g %>% 
  activate(edges) %>% 
  as_tibble() %>% 
  mutate(
    from = from - 1,
    to = to - 1
  )

node <- g %>% 
  activate(nodes) %>% 
  as_tibble()

p <- sankeyNetwork(
  Links = edge,
  Nodes = node,
  Source = "from",
  Target = "to",
  Value = "n",
  NodeID = "name",
  fontSize = 12,
  nodeWidth = 30
)

p
```

![sankey_attrition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162536/d1e4d855-99c6-5fef-6fb4-ceec106e47ae.png)

### nodeの数が多いパターン

nodeの数を増やし、多層的な関係を表現したい場合はgraphオブジェクトを連結する必要があります。

``` R
department_edge <- ibm_df %>% 
  count(department, overtime) %>% 
  as_tbl_graph()

overtime_edge <- ibm_df %>% 
  count(overtime, attrition) %>% 
  as_tbl_graph()

# bind_graph()ではnodeが重複するのでこの場合はgraph_join()を利用する
g2 <- department_edge %>% 
  graph_join(overtime_edge)

# networkD3をつかうのでindexを0始まりに変更
edge <- g2 %>% 
  activate(edges) %>%
  as_tibble() %>%
  mutate(
    from = from - 1,
    to = to - 1
  )

node <- g2 %>% 
  activate(nodes) %>% 
  as_tibble()

p2 <- sankeyNetwork(
  Links = edge,
  Nodes = node,
  Source = "from",
  Target = "to",
  Value = "n",
  NodeID = "name",
  fontSize = 12,
  nodeWidth = 30
)

p2
```

![sankey_overtime_attrition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162536/0b5848fd-5c20-dc02-b021-5c819b1eb398.png)


## 所感

- `tidygraph`を利用するとedgeとnodeを簡単に用意できるのでおすすめ
    - `tidygraph`の利用方法がそういえば日本語では、[コチラ](https://www.slideshare.net/kashitan/tidygraphggraph)の資料くらいしかないのでまとめてみてもいいかも
- htmlwidget形式になるのでshinyなどで共有できる環境があると効果的かもしれません

## 参考資料

- [Survey Results: What Degree is Best for Data Science?](https://novyden.blogspot.com/2020/03/survey-results-what-degree-is-best-for.html)
- [Sankey Diagram for energy consumption](https://www.r-graph-gallery.com/323-sankey-diagram-with-the-networkd3-library.html)
- [サンキー ダイアグラム](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%B3%E3%82%AD%E3%83%BC_%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0)
- [tidygraph](https://tidygraph.data-imaginist.com/)
- [Introducing tidygraph](https://www.data-imaginist.com/2017/introducing-tidygraph/)

Enjoy!