前回、『Chart.js の活用(基礎編)』と題して、JavaScript ライブラリーの活用に関する記事を投稿しました。今回は Plotly というライブラリーを使った Sunburst チャートの作成例を紹介したいと思います。ファイルシステムや組織階層など、階層の深さが定義できないデータを再帰的 (Recursive) に処理することにも適したチャートです。
###1. 事前準備
####1-1. ライブラリーの配置
Plotly を活用するためには、Yellowfin がアクセスできる場所にライブラリーを配置する必要があります。https://plotly.com/javascript/ にアクセスして、[Getting started] > [Download] と進み、plotly.jsファイルを取得します。
取得したファイルは、Yellowfin サーバー上の以下のディレクトリに配置します。これで、Yellowfin がライブラリーを活用できるようになります。
(Yellowfin)/appserver/webapps/ROOT/js/chartingLibraries/chartjs/
####1-2. JavaScriptグラフの有効化
JavaScriptグラフを作成するためには、いくつかYellowfinサーバーで事前設定が必要です。必要な設定内容に関しては、以下Wikiの情報を参考にしてください。
https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=2293926
###2. データの準備
ライブラリーを配置し、JavaScript グラフを有効化したら、早速グラフの作成段階に進みます。以下の手順では、Yellowfin インストール時に規定でインストールされる Ski Team のデータとビューを利用します。
レポートを新規で作成し、Ski Team ビューを選択します。
[データ] ステップで、軸に [Camp Region] と [Camp Country]、集計値に [Camp Rating] をそれぞれ選択します。
画面左からサブクエリーを選択し、タイプに [結合]、スタイルに [基本] を選択し、[OK] ボタンを押下します。
サブクエリー設定画面で、計算フィールドを2つ作成します。
計算フィールド名 | 値 | 備考 |
---|---|---|
Region2 | ’’ | null値 |
Rating2 | 0 | 半角ゼロ |
マスタークエリーフィールドとサブクエリーフィールドを以下の通りに設定します。
マスタークエリーフィールド | サブクエリーフィールド |
---|---|
Camp Region | Region2 |
Camp Country | Camp Region |
Camp Rating | Rating2 |
[保存] ボタンを押下し、サブクエリー設定画面を閉じます。 |
結果、以下のような表が出来上がりました。後続の作業では、Camp Region 列を親、Camp Country 列を子として扱います。階層が特定できないデータであっても、このデータ構造であれば、際限なく深い階層のデータを管理できます。もちろん、データソース上で最初からこの構造でデータが管理されている場合、今回実施したデータ構造の変換作業は必要ありません。ちなみに、Camp Region (親)が null の行は、最上位の階層であることを示します。
###3. グラフの作成
[グラフ] ステップに進み、画面右側 [グラフの選択] から [JavaScriptグラフ] を選択します。
雛形を全て削除し、以下のコードに置き換えます。
generateChart = function(options) {
console.log(JSON.stringify(options));
var $chartDrawDiv = $(options.divSelector);
var height = options.dataset.chart_information.height;
var width = options.dataset.chart_information.width;
var processedData = processData(options.dataset.data);
doDrawing(processedData, $chartDrawDiv, height, width, options.errorCallback);
},
processData = function(dataset) {
data={ids:[], labels: [], parents: [], values: []}
for (i=0;i<dataset['camp_rating'].length;i++){
data['ids'].push(dataset['camp_country'][i].raw_data);
data['labels'].push(dataset['camp_country'][i].formatted_data);
data['parents'].push(dataset['camp_region'][i].formatted_data);
data['values'].push(dataset['camp_rating'][i].raw_data);
}
return data
},
doDrawing = function(data, $chartDiv, height, width, errorFunction) {
require(['js/chartingLibraries/plotly/plotly-2.8.3.min.js'], function(Plotly) {
var trace = [{
ids: data['ids'],
labels: data['labels'],
parents: data['parents'],
values: data['values'],
outsidetextfont: {size: 20, color: "black"},
leaf: {opacity: 0.4},
marker: {line: {width: 5}},
type: 'sunburst'
}];
var layout = {
margin: {l: 0, r: 0, b: 0, t: 0}
};
Plotly.newPlot($chartDiv[0], trace, layout);
});
}
コードの内容を説明する前に、作成されるチャートと取り扱うデータの中身を先に確認します。[プレビュー] に移ると、Sunburst と呼ばれるチャートが表示されます。円の中心部を最上位とし、円の周囲に移動するに従って、階層を下ります。例えば、Asia の下に Japan が位置づきます。
グラフ作成に使われているデータの内容を確認するために、options に格納されるデータの中身を見てみましょう(以下 Chrome の手順)。[プレビュー] 画面で [F12] ボタンを押下するか、ブラウザ右上の [Google Chrome の設定] > [その他のツール] > [デベロッパー ツール] の順に進んで、デベロッパーツールを開きます。
画面下部で [情報] の内容を確認すると、[グラフ] ステップで集計した [Camp Region] [Camp Country] 軸と [Camp Rating] 集計値が JSON の形で表示されています。後述のコードの説明の中で、データフィールドを特定する個所がありますが、そこで指定するフィールド名は以下の情報と一致させる必要があります。
###4. コードの説明
作成されるチャートとデータの中身を確認したところで、コードの説明に移ります。
generateChart = function(options) {
console.log(JSON.stringify(options));
var $chartDrawDiv = $(options.divSelector);
var height = options.dataset.chart_information.height;
var width = options.dataset.chart_information.width;
var processedData = processData(options.dataset.data);
doDrawing(processedData, $chartDrawDiv, height, width, options.errorCallback);
},
JavaScript グラフの処理において、最初に呼び出されるのが generateChart = function(options)
です。
options の中身をJSON 形式でコンソールに出力する処理をする行が console.log(JSON.stringify(options));
です。先ほどデベロッパーツールを用いて中身を確認した情報は、この行が出力した情報です。
以下の3行で、グラフを出力する div を選択し、グラフの高さと幅に関する変数を扱います。
var $chartDrawDiv = $(options.divSelector);
var height = options.dataset.chart_information.height;
var width = options.dataset.chart_information.width;
以下の2行で、別の関数を呼び出して、データ処理とグラフ描画処理を行っています。呼び出し先の関数での処理内容は後続の個所で説明をします。
var processedData = processData(options.dataset.data);
doDrawing(processedData, $chartDrawDiv, height, width, options.errorCallback);
processData = function(dataset) {
data={ids:[], labels: [], parents: [], values: []}
for (i=0;i<dataset['camp_rating'].length;i++){
data['ids'].push(dataset['camp_country'][i].raw_data);
data['labels'].push(dataset['camp_country'][i].formatted_data);
data['parents'].push(dataset['camp_region'][i].formatted_data);
data['values'].push(dataset['camp_rating'][i].raw_data);
}
return data
},
Yellowfin のデータセットを Plotly が扱う形式に変換して、data に格納しています。ids, labels, parents, values 項目はいずれも Plotly が Sunburst チャートを作成するために必須の項目で、for 分の中で Yellowfin のデータセットから、それぞれ camp_country, camp_country, camp_region, camp_rating を受け渡しています。
doDrawing = function(data, $chartDiv, height, width, errorFunction) {
require(['js/chartingLibraries/plotly/plotly-2.8.3.min.js'], function(Plotly) {
var trace = [{
ids: data['ids'],
labels: data['labels'],
parents: data['parents'],
values: data['values'],
outsidetextfont: {size: 20, color: "black"},
leaf: {opacity: 0.4},
marker: {line: {width: 5}},
type: 'sunburst'
}];
var layout = {
margin: {l: 0, r: 0, b: 0, t: 0}
};
Plotly.newPlot($chartDiv[0], trace, layout);
});
}
require(['js/chartingLibraries/plotly/plotly-2.8.3.min.js'],
で、plotly.js ライブラリーの場所を指定します。今回であれば、『ライブラリーの配置』 手順でplotly-2.8.3.min.js を保管したディレクトリを相対パスで指定します。
var trace
の中で、Yellowfin から受け取った data の中身を、Plotly の各項目に受け渡しています。Outsidetextfont
, leaf
, marker
などでチャートの属性情報を設定します。他にも多くのオプションがあるので、以下でご確認ください。
https://plotly.com/javascript/reference/sunburst/
Plotly.newPlot($chartDiv[0], trace, layout);
で、上記手順で設定した情報を用いて、実際にグラフを描画します。
###4. 最後に
いかがだったでしょう。私を含め、Sunburst チャートの存在を初めて知った人もいるのではないでしょうか。ちなみに、ここまでの手順で取り扱ったデータは、2 階層のデータでした。
一方で、階層の数が定義できないファイルシステムや組織階層などのデータを扱った場合にはどうなるでしょう。下の例は、ダミーの組織階層を使って作成した Sunburst チャートの例です。このように、階層数が読めないデータの処理においても、データ構造を可視化できます。
同じものを作成してみたい方は、こちら に CSV 形式のダミーデータを共有しているので、Yellowfin に取り込んで試してみてください。
CSV データのインポート https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=2294195
それではまた、Cheers!