webマーケティングの世界ではユーザのコンテンツ間の遷移パターンが重要な分析対象となる場合が多くあります。例えばHPの動線を改善するためにTOPページからどのようなコンテンツにどれだけ遷移するのかを分析したり、離脱を減らすために離脱するユーザはどのような行動パターンを取るのかを分析します。始点/終点のような2点の場合このような分析はクロス集計や遷移行列のようなもので表現できます。一方コンテンツは一般的に多数あるので始点/2番目/3番目/終点のような複数層パターンでの遷移を考慮する必要があります。このパターンは組み合わせが膨大になり単純なクロス集計のようなものでは情報が繁雑になります。

このような複数層を直観的に可視化できるツールとしてサンキーダイアグラムというものがあります。(以下に図表)

 

上記例はぺージTOPから1回目のコンテンツ遷移そして2回目のコンテンツ遷移のパターンを可視化したものです。CONTENTS11→CONTENTS32とは最初1回目の遷移先がCONTENTS1で2回目がCONTENTS3に遷移したことを表します(すなわち末尾数字は何回目かを表します)。この例ですとCONTENTSが4つしかないので比較的容易に読み取ることができます。一方でコンテンツが増えると層間の辺はコンテンツ数の2乗となり可読性に問題があることが分かります。それを整数計画法で解決しようというのがこの論文https://ialab.it.monash.edu/~dwyer/papers/optimal-sankey-diagrams.pdf

で解説されています。

本稿ではまずこのサンキーダイアグラムの簡単な紹介と、可読性を上げるために 整数計画法 を用いる方法を当該論文の内容に沿って紹介します。

サンキーダイアグラムを描く

サンキーダイアグラムをググると以下のツールが上位候補として挙がってきます。

  • Google Charts Sankey Diagram
  • Python
  • R
  • Tableau

私はPython派なので本稿ではPythonを前提にご説明します。基本的な使い方はこの記事を参照願います。

Anaconda環境からAnacondaプロンプトを呼び出しhttps://github.com/ricklupton/ipysankeywidget このGithubを参考に以下のように打ち込みます。

$ pip install ipysankeywidget
$ jupyter nbextension enable --py --sys-prefix ipysankeywidget

次にpythonコード上で以下のように記述します。

これを打ち込むと冒頭で示したサンキーダイアグラムが表示されます。

可読性を上げるためには

さてこの記事の趣旨はこんな便利なツールがありますではなく、こいつの可読性を上げるにはどうするか?でした。色々議論の余地があると思いますが当該論文では

可読性が高い=コンテンツ間の太いエッジ同士の交点は少なく、細いエッジ同市の交点が多い

とあり、本記事でもこれを定義として進めていきます。直観的に考えて太いもの同士が交わると見にくいですよね?

整数計画法を適用し問題を解く

整数計画法 とはある制約条件のもとで任意の目的関数を最小化(最大化)するアルゴリズムです。線形計画法との違いは変数がバイナリー(すなわち1/0であるかどうかの違いで整数計画法は1/0の変数のみ用います)したがって太い(細い)エッジ同市の交点ができた時に大きく(小さく)なる関数を定義し、それを制約条件のもとで最小化する整数計画問題を解くことで可読性の高いサンキーダイアグラムの表示方法の解が得られるというのが当該論文の主張です。

本記事ではPythonの線形計画法のパッケージであるpulpを使います。

 変数の設定

一番上のソースコードのlinksで定義されるデータをinputとします。

簡単のためTOPページはなしとします。

頂点集合vを取得する。

エッジの重み変数wを作成する、ここれは重みはエッジの流入出量とする。

交差変数cの作成を行う。エッジが交差したた1それ以外は0となるように定義する。

ある頂点がほかの頂点より同層ないで上にあれば1それ以外は0となるような 頂点の順序変数xを作成する。

 

目的関数の設定

最小化したい目的関数を設定します。

目的関数:=Σ(エッジu1v1の数×エッジu2v2)×cu1v1u2v2

u1,u2は1層目の頂点、v1,v2は2層目の頂点エッジu1v1はu1とv1を結ぶ辺cu1v1u2v2は辺が交差していれば1それ以外0となる変数でΣは全ての頂点の組み合わせを走るとします。

 

制約条件の作成

同じ層に属する頂点の2つの組は必ずどちらかが上であればかならず他方が下であるという制約を定式化します。具体的に述べるとxij=1 頂点iがjより上と定義すると必ず xij+xji=1となるように制約を設けるということです。

またiがjより上でkがiより上の場合kは必ずjより上にあるという推移率も定式化します。

頂点の位置関係と交差関係に矛盾がないように制約式を立てる。また交差の対称性も定式化する。

ソルバーを実行して問題を解く

 

実際の解を見てみる

上のコードを走らせると

[‘CONTENTS31’, ‘CONTENTS21’, ‘CONTENTS11’, ‘CONTENTS41’]
[‘CONTENTS22’, ‘CONTENTS32’, ‘CONTENTS12’, ‘CONTENTS42’]

という出力が得られるのでこれを最初のソースコード中に以下のように記述します。

事前事後を比べると(左図が事前右図が事後)

 

こころなしか事後の方が見やすくなっています。