4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Sankey DiagramをnetworkD3とtidygraphで作る

Posted at

Survey Results: What Degree is Best for Data Science?というブログポストを読んで、Sankey Diagramの存在を知りました。
ブログポストにもあるようにアンケートを取った時の回答の流れを可視化する際に効果的かもしれません。

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

Sankey Diagramとは

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

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

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

sankey_energy.png

準備

package

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

library(tibble)
library(dplyr)
library(tidygraph)
library(networkD3)

data

今回は組み込みのデータセットではなく、IBM HR Analytics Employee Attrition & Performanceを利用します。データセットはKaggleのサイトからダウンロードすることができます。

# ローカルに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の数が少ないパターンから可視化を行ってみます。
networkD3packeageのsankeyNetwork()はedegeとnodeのデータが必要になるため、tidygraph::as_tbl_graph()を使ってデータを加工します。

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

nodeの数が多いパターン

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

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

所感

  • tidygraphを利用するとedgeとnodeを簡単に用意できるのでおすすめ
    • tidygraphの利用方法がそういえば日本語では、コチラの資料くらいしかないのでまとめてみてもいいかも
  • htmlwidget形式になるのでshinyなどで共有できる環境があると効果的かもしれません

参考資料

Enjoy!

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?