D3.js v4/v5 hierarchy データ構造と使い方
D3.js hierarchy(v4/v5対応)の使い方について説明します。
hierarchyは、階層データを視覚化するためのライブラリで以下の5つの描画が可能です。
それぞれの描画は各ページを参照ください。ここではすべてに共通するデータ構造について解説していきたいと思います。
データ構造
まず、一つのノードに対するデータは以下のフォーマットで準備します。
1 2 3 4 |
{ "name": "A", "children": [{ },{ }] } |
子、孫ノードを追加したい場合は”children”配列に同じフォーマットのオブジェクトを追加していきます。末端のノードの場合は”children”を省略します。例えば、下の構造のツリーを描画したいときは、
こちらのデータ構造になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var data = { "name": "A", "children": [ { "name": "B" }, { "name": "C", "children": [{ "name": "D" }, { "name": "E" }] }, { "name": "F" }, { "name": "G", "children": [{ "name": "H" }] }, { "name": "I" } ] }; |
データ構造の変換
用意した上記データを描画するために、2回データ構造を変換する必要があります。
用意した階層データ (上記) → hierarchy用のデータ構造 → 描画種類ごとのデータ構造
といっても、2回とも関数を一つ呼び出すだけです。同じデータ構造で異なる描画に変換できる仕組みになっています。
まず、hierarchy用のデータ構造への変換は下の関数を使います。
1 |
var root = d3.hierarchy(data); |
rootには、用意したデータと同じ構造のオブジェクトが作成され、以下の変数が追加されます。
node.data | ノードに関連する元データへの参照。 |
node.depth | 先頭を0とした深さ方向の位置。整数。 |
node.height | 末端から自ノードまでの最大位置。末端は0。整数。 |
node.parent | 親ノードへの参照。先頭の場合はnull。 |
node.children | 子ノードへの参照。末端の場合は未定義。 |
root変数自体には先頭のnodeに対応するオブジェクトが格納されており、先ほどと同じ下の構造の場合、
1 |
root.children[0] |
とすれば、ノード”B”のオブジェクトにアクセスできます。
ノードには、次に説明する関数が準備されています。詳細を下に記載します。それぞれのデモと相互参照しながらご覧下さい。
描画種類ごとのデータ構造への変換はそれぞれのデモページを参照ください。
hierarchyノード用の関数一覧
node.ancestors() | 自ノードを含む、親をたどるルートの配列を返します。 |
node.descendants() | 自ノードを含む子、孫をたどる配列を返します。 |
node.leaves() | 自ノードに関連する、末端の(子要素を持たない)ノード配列を返します。 |
node.path(target) | ノードから指定されたターゲットノードへの最短パスをノードを格納した配列で返します。 |
node.links() | ノード間をつなぐリンク配列を次の形式で返します。 [{“source”: 親ノード, “target”:子ノード}, …] |
node.sum() | 子孫ノードに設定した値の合計値を算出します。function(d) { return d.value; }のように引数に関数を設定します。treemap、partition、packで親の大きさを決定する際に使用します。 |
node.count() | このノード下にある末端のノード数を計算してnode.valueに割り当てます。このノードが末端の場合、1を返します。 |
node.sort(compare) | 指定された比較関数compareを使用して、兄弟間をソートします。 |
node.each(function) | 指定したノードの子、孫要素を順番に、functionの指定に基づいて処理します。 |
node.eachAfter(function) | 指定したノードの子、孫要素を順番に、functionの指定に基づいて処理します。末尾が優先して呼び出されます。子ノードがあるノードは必ず子ノードの後に処理されます。 |
node.eachBefore(function) | 指定したノードの子、孫要素を順番に、functionの指定に基づいて処理します。先頭が優先して呼び出されます。親ノードがあるノードは必ず親ノードの後に処理されます。 |
node.copy() | 指定したノードから始まるサブツリーのディープコピーを返します。コピーしたツリーの先頭要素の親はnullになります。 |
まとめ
入れ子になった構造から、ノードだけを配列で再構成してくれるなど、便利な関数が用意されています。具体的な使い方はデモを参照ください。