前回に引き続き、ツリー構造のデータを可視化する「ツリーマップ」の手法を扱います。今回は、グラフィックスAPIのJava2Dを使用して、実際にツリーマップを描画し、画像ファイルへ出力を行います。
ソースコードのダウンロード
今回作成するプログラムのソースコードは、こちらから一括してダウンロードすることができます。ZIPファイルを展開して生成されるフォルダを、プロジェクトとしてNetBeansに読み込むことも可能です。
Java2Dによるグラフィックス
Javaには、Java2Dと呼ばれる2次元グラフィックスAPIが標準で付属しています。Java2Dの仕様は大変充実しており、例えば以下のような機能がサポートされています。
- 基本図形の描画
- テキストの描画
- パスの作成
- 交差判定
- 座標系の拡大・縮小・回転
- アンチエイリアス
- グラデーション
- 半透明描画
- 画像ファイルの入出力
視覚的に美しい情報可視化を行うにあたっては、高機能なグラフィックライブラリの使用が必須となります。Java2Dは、その有力な選択肢の一つとなるでしょう。
色集合のツリーマップ
今回は、Java2Dを用いて、色データの集合を対象としたツリーマップの描画に挑戦します。ツリーマップは、以下の要件にしたがって作成することにします。
- 第2回のアルゴリズムにしたがって、色データ集合のクラスタリングを実行し、クラスタツリーを作成する。
- クラスタリングの距離関数には、第3回のWard法を使用する。
- 第3回のアルゴリズムにしたがって、ツリーマップの領域分割を行う。
- ツリーマップ領域の面積比率は、ランダムに決定する。
- ツリーマップの各領域は、ツリーノードに対応する色で塗りつぶす。
- ツリーマップの各領域は、ツリーノードの深さに応じた太さで輪郭を描画する。ルートノードを最も太く、末端ノードに近づくほど細く描画する。
この結果出力されるイメージは、例えば図1のような見た目になります。分割された各領域の面積、色、そして輪郭の太さによって、データの全体的な構造を直感的に理解することができます。
ツリーマップの描画
それでは、ツリーマップの描画ロジックを作成していきましょう。
まず始めに、TreeMapRendererインターフェイスを用意します。TreeMapRendererは、指定された長方形領域の内部にツリーマップを描画するrender()メソッドを持ちます。
そして、このインターフェイスを実装したBinaryTreeMapRendererクラスを作成します。BinaryTreeMapRendererクラスは、次のような方針で描画を行います。
- ノードが末端なら、領域を確定し、内部を塗りつぶす。
- ノードが末端でなければ、領域を分割し、子ノードを再帰的に処理する。
- 子ノードの処理が終了後、親ノードの輪郭を描画する。
上記の方針に対応する実際の部分コードを、順番に見ていきましょう。なお、これらの部分コードを含むBinaryTreeMapRendererクラスの完全なソースコードは、こちらをご覧ください。
末端ノードの塗りつぶし
以下は、ノードが末端の色データである場合の処理です。bounds変数に格納されている現在の長方形領域を、ノードの色を使って塗りつぶしています。
ノード領域の分割
以下は、ノードがクラスタを示している場合の処理です。
始めに、クラスタが持つ2つの子ノードのgetArea()メソッドを呼び出し、面積比率を求めます(A)。次に、その面積比率にしたがって、長方形を左右または上下に分割します(B)。最後に、それぞれの子ノードを再帰的に処理します(C)。
ノードの輪郭の描画
ノードの塗りつぶしと、輪郭の描画の実行順序には注意が必要です。なぜなら、先に描画した輪郭が、その後の塗りつぶしによって上書きされてしまう可能性があるからです。この問題を避けるには、全ての子ノードの処理が終わった後に、輪郭を描画するようにします。
以下が、実際の輪郭の描画コードになります。depth変数で与えられるノードの深さを元にしてストロークを作成し、輪郭線の幅を指定しています。
デモプログラムの実行
それではいよいよ、このBinaryTreeMapRendererクラスを使用して、ツリーマップの描画を実践してみましょう。
以下が、ツリーマップを生成し、画像ファイルに出力するDemoクラスになります。このクラスは第2回のDemoクラスと似ていますが、色データが100個に増えていること、階層的クラスタリングの距離関数を最短距離法からWard法に変更していること、そしてクラスタリング結果をコンソールではなくツリーマップに書き出していることが異なります。
Demoクラスでは、OUTPUT_FILE_NAME定数で指定されたファイル名で画像を保存します。定数は、実行環境に応じて適宜書き換えてください。
Demoクラスを実行すると、図2の画像ファイルが出力されます。まるでステンドグラスのように、美しい画像を作成することができました。このイメージからは、クラスタリングによって似た色同士が階層状に集まっている様子も、大変分かりやすく把握することができます。
入力データはランダムに生成しているため、出力される画像は実行するたびに異なります。いろいろなパターンの画像が得られますので、イメージをじっくり観察してみてください。
また、以下の観点から考察や実験をしてみると、さらに面白いかもしれません。
- 入力データの数をさらに増やすと、ツリーマップはどうなるか?
- 階層的クラスタリングの距離関数をWard法から最短距離法に戻すと、ツリーマップはどうなるか?
まとめと次回予告
今回は、グラフィックスAPIのJava2Dを利用して、ツリーマップをグラフィカルに描画し、画像ファイルに出力するプログラムを作成しました。この実践を通して、ツリーマップが非常に効果的な情報可視化手法であることがお分かりいただけたかと思います。
さて、これまで作成したプログラムの動作確認では、人為的に用意したデータを入力していました。しかし、情報可視化は現実のデータに適用してこそ価値を持つものです。
次回からは、はてなブックマークが提供しているWeb APIを利用し、はてなブックマークのデータを可視化する方法を考えていきます。