以前、メモ同士の類似度を可視化した時は、PyVizを使ってグラフ化&HTML出力した(メモ)。せっかくなので、もうちょい見た目を綺麗にしたものを、サイトマップがてら、常設するようにした。数日前からヘッダーにGraphが追加されていると思う。

以下はそのときのメモ

sigma.js

Web frontendでネットワークグラフを描画する方法はいくつかある。がっつり描画をカスタマイズするならD3で、ネットワークグラフライブラリなら、vis.jsCytoscape.jsSigma.jsあたりが使われているらしい。

ノード数やパフォーマンスを見て決めるのがセオリーだけど、今回の場合は長期的に見てもたかが数百ノードで、解析をするわけでもないので、1番自分のイメージに近いサンプルがあった sigma.js にした。

読み込みデータ

sigma.jsのサンプルを見ると、GEXFファイルを使用していた1。標準的なファイル形式があるならそれに揃えようと思ったけど、どうやらGephiを使うときの標準、くらいの立ち位置っぽい。グラフファイルフォーマットならGraphMLの方がサポートされているライブラリが多く、こっちの方が無難らしい。ちなみにどちらもXML形式で歴史を感じる。

何かワークフローに組むわけでもないので、以前 Related Post を自動で計算するときに作ったファイル(メモ)を流用するに留めた。

類似度の値さえあれば、可視化はすぐにできる。

sigma.jsで類似度を読み込ませる

sigma.jsで類似度を読み込ませる

クラスタで固める

類似度の高いノード同士を近くに配置するアルゴリズムは、類似度の値を元に、引力と斥力の2つの力をシミュレートし、お互いに関連の強いノードを空間的に近づける、というのがよく使われる。

sigma.jsでは、Graphologyというグラフデータ構造ライブラリが使われており、そのプラグインForceAtlas2でサポートされている。

const graph = new graphology.Graph();

const sensible = forceAtlas2.inferSettings(graph);
const options = {
  iterations: 50, // higher = more clustered
  settings: Object.assign({}, sensible, {
    edgeWeightInfluence: 1.0, // lower = more clustered
    linLogMode: false,
    outboundAttractionDistribution: false,
    strongGravityMode: false,
    barnesHutTheta: 0.5
  })
};
forceAtlas2.assign(graph, options);

色をつける

塊ごとに色をつけるには、まずコミュニティを検出し、そのコミュニティごとに色を設定すれば良い。Graphologyでは、Louvain method(ルーヴァン法)のプラグインCommunities Louvainが便利。

const graph = new graphology.Graph();

const communities = louvain(graph);
// ... set node color

ここまでで、だいたいそれっぽいネットワークグラフになる

コミュニティで固めた状態

コミュニティで固めた状態

その他

あとは細かい部分を調整する

  • Darkモードへの対応
  • ズームボタンの設置
  • クリックで各ページへ遷移

Darkモード対応が地味に面倒だった。sigma.jsはデフォルトで、ノードをホバーしたとき強調表示されるが、このスタイルをどうやってカスタマイズするのかが分からなかった。結局ソースを見て、defaultDrawNodeHoverを上書きして対応した。