search
LoginSignup
25

More than 5 years have passed since last update.

posted at

updated at

pythonでsankeyダイアグラム

背景

 モノの量的な流れを上手く表現したい場面に出くわした。

  • あるサイトを訪れた人が、どのページにどれだけ遷移し、あるいは離脱していくかを観察したい。
  • 家計(会社)の収支に関して『どの時点で』『何に』『どのくらい』という観点で観察したい、など。

 このような場面でよく用いられるのが、Sankeyダイアグラムだ。

Sankeyダイアグラム

Sankeysteam.png
(図はWikipediaから)

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

蒸気機関におけるエネルギー収支したのが始まりらしい。そして、その著者がM.H.Sankeyとのこと。

蒸気期間の例では、エネルギーが、どのように、どれくらい消費されるのか、また系を循環するのかが直感的に理解できる。

Pythonで描いてみたい

ipysankeywidgetというjupyter notebook上で動くwidgetが公開されている。ありがたい。

READMEに従って、一通りの準備を済ませた後で、
さっそくnotebookで動かしてみる。

from ipysankeywidget import SankeyWidget

notebook上で、sankeyダイアグラムを良い感じに描画してくれるように関数を用意する。

def sankey(width=300, margin_top=10, **value):
    return SankeyWidget(value=value, width=str(width), height=200,
                        margins=dict(top=margin_top, bottom=0, left=30, right=60))

使い方

基本的には、次の項目を辞書形式で描いてあげればよい。

  • どこから: "source"
  • どこへ:"target"
  • どれくらい: "value"
links = [
    {'source': 'A', 'target': 'B', 'value': 1},
    {'source': 'B', 'target': 'C', 'value': .5},
    {'source': 'A', 'target': 'D', 'value': .5},
]
sankey(links=links)

2017-04-06_16h43_09.png

上の例では、ノード”B”と”D”が揃えられているが、どのノードの位置を揃えるか、も変えられる。以下の例では、ノード"C"と"D"を揃えてみる。

rank_sets = [
    { 'type': 'same', 'nodes': ['C', 'D'] }
]
sankey(links=links, rankSets=rank_sets)

2017-04-06_16h45_44.png

こんな感じで、色々設定できるので、ちょっと複雑にしてみたのが下図。
実データがあれば、適用してみたかった...。

今回は、ここまで。
2017-04-06_16h52_36.png

# ノード情報
Ns= [
    {
      "id": "a",
      "title": "a"
    },
    {
      "id": "b",
      "title": "b"
    },
    {
      "id": "c",
      "title": "c"
    },
    {
      "id": "x",
      "title": "d"
    },
    {
      "id": "y",
      "title": "e"
    }
  ]

# リンク情報
Ls= [
    {
      "source": "a",
      "target": "x",
      "value": 1,
      "type": "x"
    },
    {
      "source": "a",
      "target": "y",
      "value": 0.7,
      "type": "y"
    },
    {
      "source": "a",
      "target": "y",
      "value": 0.3,
      "type": "z"
    },
    {
      "source": "b",
      "target": "x",
      "value": 2,
      "type": "x"
    },
    {
      "source": "b",
      "target": "y",
      "value": 0.3,
      "type": "y"
    },
    {
      "source": "b",
      "target": "y",
      "value": 0.9,
      "type": "z"
    },
    {
      "source": "x",
      "target": "c",
      "value": 3,
      "type": "x"
    },
    {
      "source": "y",
      "target": "c",
      "value": 1,
      "type": "y"
    },
    {
      "source": "y",
      "target": "c",
      "value": 1.2,
      "type": "z"
    }
  ]

# グループ情報
groups = [
    {'id': 'G1', 'title': 'TOP', 'nodes': ['a', 'b'] }
    ,{'id': 'G2', 'title': 'MIDDLE', 'nodes': ['x', 'y'] }
]

sankey(links=Ls, nodes=Ns, groups=groups, alignLinkTypes= False, margin_top=50)

参考URL

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
What you can do with signing up
25