D3.js v4/v5 cluster 使い方 – サンプル

2018-02-10

D3.jsの階層構造を可視化するcluster(d3.hieararchy)のプログラムデモです。決定木などのクラスター分析の結果表示に活用できます。データの準備とデータ構造については、こちらをご覧ください。デモでは解説のために最もシンプルなコードを採用しています。

プログラムデモ – 描画のみ

 

サンプルコード

 解説

1. スタイルの準備

リンクのスタイルを設定しておきます。今回、ノードのスタイルはsvg要素に直接設定します。

2. 描画用のデータ準備

描画用のデータを用意します。データ構造の詳細はこちらを参照ください。

3. 描画用のデータ変換

準備したデータを、描画用のデータ構造に変更します。準備したデータ→hierarchy用のデータ→描画種類ごと(今回はcluster)のデータと2段階の変換が必要です。

まず、

のコマンドで、dataをhierarchy用のデータ構造rootに変更します。rootには、こちらの変数が設定されます。

次に、cluster用のデータに変更するための関数を呼び出します。

d3.cluster()で呼び出した関数にrootを引数として設定すると、次のデータがrootに付与されます。

x ノードの並び(兄弟)方向の座標
y ノードの深さ(親子)方向の座標(先頭が0)

今回のデモでは、付与される座標はxが画面縦方向、yが画面横方向となりますので注意が必要です。

また、d3.cluster()には以下の設定が可能です。

cluster.size() 描画する構造のサイズを[並び方向, 深さ方向]の2要素配列で設定します。引数が設定されていない場合は現在のサイズを返します。デフォルトは[1, 1]。
cluster.nodeSize() ノード1つのサイズを[並び方向, 深さ方向]の2要素配列で設定します。引数が設定されていない場合は現在のサイズを返します。デフォルトはnullです。nodeSize()がnullの場合は上のsize()を使用します。nodeSize()が指定されている場合先頭の要素の位置が(0,0)に設定されます。
cluster.separation() 隣り合う要素間の間隔を決める関数を設定します。デフォルトは次の関数になっています。
function separation(a, b) {
return a.parent == b.parent ? 1 : 2;
}
本プログラムデモはデフォルト設定で、隣り合うノードが異なる親の場合、同じ親の場合と比較して2倍の隙間が空いています。

ここで、今回はsize( )を使ってclusterの幅を設定していますが、先頭の座標が0、深さ方向末端の座標が設定した幅となるように計算されるため、

のように、svgの描画領域の幅より小さめにclusterの幅を設定しています。

4. svg要素の配置

先頭の要素の座標が0に設定されるため、グループを表す”g”要素を設定して全体をx方向に移動させます。このグループ要素の中にノードとリンクを設定していきます。

まず、リンク用のsvg要素を設定します。

データの割り当ての部分で

の関数を使っていますが、これは入れ子になったノードを配列として並べてくれる関数です。順番は指定したノードに対する深さ方向、並び方向の順で並びます。今回のデモでは、A→B→C→G→H→K→D→E→F→I→Jの順です。また、子から先頭に向かってリンクを描画する設定で、先頭Aからのリンクはないためsliceで先頭のノードを除外しています。

続いてノードのsvg要素を設定します。

ノードには’circle’と’text’の二つを設定するため、はじめに’g’要素を設定し、その中に’circle’と’text’を設定していきます。’g’要素で位置を設定していますが、clusterの深さ方向がy、並び方向がxである点に注意してください。

子ノードが多くあるノードの右側はリンクが密集するため、子ノードがある場合は右側、無い場合は左側にtextを設定しています。”text-anchor”はtextの位置を設定するスタイルです。

まとめ

データを2回変換する必要があることと、y座標がclusterの深さ方向である点が分かりにくい点です。ご注意ください。末端のノードを同じ位置に並べるのがclusterレイアウトですが、同じような構造で、同じ親の子を同じ位置に並べるtreeレイアウトがあります。ほとんど同じプログラムで使い分けることができます。