---
title: "Sankey Diagram という可視化方法 | grasys blog"
url: "https://blog.grasys.io/post/t-watanabe/sankey-diagram"
description: "こんにちは grasys でデータ分析をしている t.watanabe です！ みなさんは「web サイトのお客さんの移動ログ」や「ゲーム内のユーザさんの行動ログ」から「商品を買ってくれるお客さんがどのような行動をしているか」など考えることはありませんか？ ただ、人やモノの移動をどうやって可視化すべきか迷うときはない…"
---

# Sankey Diagram という可視化方法

-   ![](/_astro/noicon.CTHOhNiB_1HMs6A.webp)[t.watanabe](/authors/t-watanabe/)
-   公開日：2026年3月4日
-   カテゴリー：[Tech](/categories/tech/)
-   タグ：[#Sankey Diagram](/tags/sankey-diagram/)[#データ分析](/tags/データ分析/)

![Sankey Diagram という可視化方法](/_astro/hero.N2OxPC4y_19rlTM.webp)

こんにちは

grasys でデータ分析をしている t.watanabe です！

みなさんは「web サイトのお客さんの移動ログ」や「ゲーム内のユーザさんの行動ログ」から「商品を買ってくれるお客さんがどのような行動をしているか」など考えることはありませんか？

ただ、人やモノの移動をどうやって可視化すべきか迷うときはないでしょうか？

そのようなときに使いやすい Sankey Diagram を紹介したいと思います

## Sankey Diagram とは？

なにかしらの遷移の可視化に特化した図表です

python のライブラリの plotly で表示することを前提とします

![流量を線の太さで表現したサンキーダイアグラムの例](/_astro/01-sankey-9709f80a.D1zAmyxd_Z1FipuK.webp)

こちらのグラフは単純な Sankey Diagram です

plotly のイメージを引用しました

各青い矩形が遷移のターニングポイント(node)で帯の幅が遷移数、帯の結びつきが遷移を表しています

では、Sankey Diagram を描いてみましょう

## Sankey Diagram を描いてみる

まずは環境設定からです

今回は後々のデータ分析などをできる環境まで作りますので jupyter notebook に描くことを目指します

Windows の場合

Plain textcontent\_copy

```
powershell -c "irm https://astral.sh/uv/install.ps1 | more"
```

MacOS, Linux の場合

Plain textcontent\_copy

```
curl -LsSf https://astral.sh/uv/install.sh | less
```

uv を入れたら作業ディレクトリに移動し

Plain textcontent\_copy

```
uv init .
uv add plotly jupyter
uv sync
uv run jupyter notebook --allow-root --port=8888 --ip=0.0.0.0 --NotebookApp.token=''
```

と打ち込み jupyter を起動します

ブラウザで

Plain textcontent\_copy

```
http://localhost:8888
```

にアクセスしてください

![Sankey Diagram を描いてみるの画面](/_astro/02-7a98cd4b49f394aff7e20587724ec63b-1024x156-b8e86558.49X5P9l8_2dMdrq.webp)

このような画面がでれば成功です（最初はホワイトテーマなので好みのものに変えてください）

Plain textcontent\_copy

```
右クリック/New Notebook/
```

で notebook を作成し、セルに下記のコードをコピー・アンド・ペーストしてください

Plain textcontent\_copy

```
import plotly.graph_objects as go

fig = go.Figure(data=[go.Sankey(
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = ["A1", "A2", "B1", "B2", "C1", "C2"],
      color = "blue"
    ),
    link = dict(
      source = [0, 1, 0, 2, 3, 3], 
      target = [2, 3, 3, 4, 4, 5],
      value = [8, 4, 2, 8, 4, 2]
  )
)])

fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
fig.show()
```

実行すると冒頭の Sankey Diagram が表示されます

実データに適応する前に一つずつ確認します

Plain textcontent\_copy

```
import plotly.graph_objects as go
```

ここは plotly の Sankey Diagram を呼び出します

Plain textcontent\_copy

```
fig = go.Figure(data=[go.Sankey(
   ...
)])
```

Sankey Diagram をつくります

次はオプションです

Plain textcontent\_copy

```
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = ["A1", "A2", "B1", "B2", "C1", "C2"],
      color = "blue"
    ),
```

ポイントとなる “ノード” の設定を作ります

Plain textcontent\_copy

```
      pad = 15,
      thickness = 20,
```

これは表示時の空白やサイズの設定です

Plain textcontent\_copy

```
  line = dict(color = "black", width = 0.5),
```

帯の設定です

黒い色の 0.5 サイズです

Plain textcontent\_copy

```
  label = ["A1", "A2", "B1", "B2", "C1", "C2"],
```

ノードのラベルをつけます

あとでこの順序が重要になるので変数か何かにメモしておきましょう

Plain textcontent\_copy

```
  color = "blue"
```

ノードの色です、青で設定しています

次は帯の設定です

Plain textcontent\_copy

```
    link = dict(
      source = [0, 1, 0, 2, 3, 3], 
      target = [2, 3, 3, 4, 4, 5],
      value = [8, 4, 2, 8, 4, 2]
  )
```

数字が設定されていますね

なんの数字でしょうか？

そこで先程メモした順番のラベルが登場です

Plain textcontent\_copy

```
label = ["A1", "A2", "B1", "B2", "C1", "C2"],
```

これですね

左から A1:0, A2: 1, … C2:5 となります

source には遷移元となるラベルに対応する index を入れます

target は遷移先となる index を入れます

Plain textcontent\_copy

```
source = [0, 1, 0, 2, 3, 3], 
target = [2, 3, 3, 4, 4, 5],
は
source = ['A1', 'A2', 'A1', 'B1', 'B2', 'B2'], 
target = ['B1', 'B2', 'B2', 'C1', 'C1', 'C2'],
ということです
つまり

index[0] が A1 -> B1
index[1] が A2 -> B2
index[2] が A1 -> B2
index[3] が B1 -> C1
index[4] が B2 -> C1
index[5] が B2 -> C2

となります

value はそれぞれの index の帯の幅です
```

次に細かな表示の調整をします

Plain textcontent\_copy

```
fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
```

フォントサイズは 10 で Basic Sankey Diagram というタイトルで設定します

Plain textcontent\_copy

```
fig.show()
```

これで表示まで行きました

ちょっと、分かりづらいですね

ただ、一回表示までできてしまえばなれるかもしれないです

## サンプル描画

最後に実データで表示するサンプルを置いてきます

pandas のデータフレームをユーザごとに行動の順番を stage として定義し A, B, C として並べ、Sankey Diagram に起こします

stage は各ユーザが閲覧した web ページのようなイメージです

例えば下記の図でいうと「サトウ」さんは A -> B の順にページを移動したと読み取れます（図は時系列で表現されており、0番と6番でサトウさんが登場しています）

Plain textcontent\_copy

```
import pandas as pd
df = pd.DataFrame(
    {
        "user": ["サトウ", "タカハシ", "タナカ", "ワタナベ", "タカハシ", "タナカ", "サトウ", "タカハシ", "タナカ", "ワタナベ"],
        "stage": ["A", "A", "A", "A", "B", "B", "B", "C", "C", "C"],
    }
)
```

![サンプル描画の画面](/_astro/03-96b1147a11f9332ca30c2c7258b642d0-5a716d23.B90O29HV_tHtJp.webp)

Sankey Diagram では個別の行動ログを全体のボリュームとして集約して描画するため、全体の傾向を掴むのに適しています。

一方で、「特定のユーザーがどう動いたか」というミクロな追跡には不向きなので注意が必要です。

Plain textcontent\_copy

```

def df2sankey_diagram(df):
    import plotly.graph_objects as go
    
    df = pd.concat([df, df.groupby("user").shift(-1).rename(columns={"stage": "next_stage"})], axis=1)
    df = df.dropna()

    channel2index = {k: i for i, k in enumerate(list(set(df["stage"].tolist()) | set(df["next_stage"].tolist())))}
    index2channel = {v: k for k, v in channel2index.items()}

    labels = [x for x, _ in channel2index.items()]
    src = [channel2index[k] for k in df["stage"].tolist() if k in channel2index.keys()]
    dst = [channel2index[k] for k in df["next_stage"].tolist() if k in channel2index.keys()]
    
    fig = go.Figure(data=[go.Sankey(
        node = dict(
            pad = 15,
            thickness = 20,
            line = dict(color="black", width=0.5),
            label = labels,
        ),
        link = dict(
            source = src,
            target = dst,
            value = [1 for _ in src]
        )
    )])
    fig.update_layout(
        title_text="Sankey Diagram による状態遷移", 
        font_size=10, 
        width=2400, 
        height=400,
        legend=dict(
            title="Sample",
            traceorder='normal',
            itemsizing='constant'
        )
    )
    fig.show()
```

![サンプル描画を示すグラフ](/_astro/04-newplot-1024x171-8df85499.BlyWVdOG_kU9or.webp)

## 結び

色々なグラフがありますが、適切なグラフを用いてわかりやすく伝えることは難しいです

しかしながら、協力していく中で可視化は重要なファクタだと思います！

## 出典

[plotly, Sankey Diagram in Python](https://plotly.com/python/sankey-diagram)

[Installing uv](https://docs.astral.sh/uv/getting-started/installation)

## この記事を書いた人

[![](/_astro/noicon.CTHOhNiB_Z24aAgM.webp)](/authors/t-watanabe/)

### [t.watanabe](/authors/t-watanabe/)

t.watanabeのプロフィールと執筆記事をご覧いただけます。

[プロフィールと記事一覧](/authors/t-watanabe/)