D3.js hierarchyのデータ構造と使い方

D3.jsで階層構造を可視化するhierarchyについて説明する。

hierarchyは階層データを可視化するためのライブラリで、次の5種類の描画を提供する。

  • Cluster
  • Tree (準備中)
  • Treemap (準備中)
  • Partition (準備中)
  • Pack

各描画はそれぞれのページを参照すればよい。ここではすべてに共通するデータ構造について説明する。

データ構造

まず、1つのノードについて次の形式でデータを用意する。

{
  "name": "A",
  "children": [{ },{ }]
}

子や孫ノードを追加したい場合は、children配列に同じ形式のオブジェクトを追加していく。末端ノードの場合は"children"を省略する。

たとえば、次の構造のツリーを描画しようとする場合、

次のようなデータ構造を用意する必要がある。

var data =
{
    "name": "A",
    "children": [
      { "name": "B" },
      {
        "name": "C",
        "children": [{ "name": "D" }, { "name": "E" }, { "name": "F" }]
      },
      { "name": "G" },
      {
        "name": "H",
        "children": [{ "name": "I" }, { "name": "J" }]
      },
      { "name": "K" }
    ]
  };

データ構造の変換

上で用意したデータで描画するには、データ構造を2回変換する必要がある。

用意した階層データ -> hierarchy用データ構造 -> 描画種類別データ構造

そのためには、どちらも関数を1回呼び出すだけでよい。同じデータ構造を別の描画へ変換できる構造になっている。

まず、hierarchy用のデータ構造への変換には次の関数を使用する。

var root = d3.hierarchy(data);

rootは用意したデータと同じ構造のオブジェクトを作成し、次の変数を追加する。

オブジェクト 説明
node.data ノードに関連付けられた元データへの参照。
node.depth 先頭を0とした深さ方向の位置。整数。
node.height 末端から子ノードまでの最大位置。最後は0。整数。
node.parent 上位ノードへの参照。先頭の場合はnull
node.children 子ノードへの参照。末端の場合は未定義。

root変数自体には、先頭のnodeに対応するオブジェクトが含まれている。前の図のような構造であれば、次のようにしてノード"B"のオブジェクトへアクセスできる。

root.children[0]

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である。