サンキーダイアグラムでモノや情報の流れを可視化 ： Yellowfin と FusionCharts の活用

FusionChart と Yellowfin 連携の第 3 弾です。
FusionCharts と連携してサンキーダイアグラムを作成してみようと思います。サンキーダイアグラムは、エネルギー、キャッシュ、人などの流れや量などを表すことなどに使われます。また、EC サイトの購買行動の順序を認識するためにも用いられることがあります。
以下の手順では、2013 年の各国の輸出・輸入量を示すダイアグラムを作成します。

## 1. 事前準備
[前回記事](https://qiita.com/ExtremeCarvFJ/items/ad453a6110cec093bdb9)  を参考に、ビューの作成までの作業を実施します。
準備するデータに関しては、最低限 from (起点), to (終点), value (量) があれば大丈夫です。以下の手順と同じデータを使ってみたい方は、[こちら]( https://github.com/ChasingHH/ShareFiles/blob/Share/Export.csv)にサンプルデータを共有しています。

## 2. グラフの作成
準備が整ったら、グラフの作成に手順を進めます。新規でレポートを作成し、以下の手順に従ってグラフを作成します。

#### 2-1. [データ] ステップ
[from] [to] [value] を 「カラム(列)」 に追加します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/03643492-a36b-a0cb-2ba7-bd6c8bc4ac28.png)


#### 2-2. [グラフ] ステップ
[グラフ] ステップに進み、画面右側 [グラフの選択] から [JavaScript グラフ] を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/172cd450-aedd-bfa2-7560-0c62e5193428.png)

##### JavaScriptタブ
雛形を全て削除し、以下のコードに置き換えます。コードの処理の内容は後ほど説明します。
```javascript:JS
generateChart = function(options) {
   var $chartDrawDiv = $(options.divSelector);
   var processedDataLabel = processDataLabel(options.dataset.data);
   var processedDataValue = processDataValue(options.dataset.data);
   doDrawing(processedDataLabel, processedDataValue, $chartDrawDiv);
},

processDataLabel = function(dataset) {
    var ds_label = [];
    for (i=0;i<dataset.from.length;i++){
        if(dataset.value[i].formatted_data === "0"){
            ds_label.push({
                label: dataset.from[i].raw_data,
            });
        }
    }
    return ds_label;
},

processDataValue = function(dataset) {
    var ds_value = [];
    for (ii=0;ii<dataset.from.length;ii++){
        if(dataset.value[ii].formatted_data != "0"){
            ds_value.push({
                from: dataset.from[ii].raw_data,
                to: dataset.to[ii].raw_data,
                value: dataset.value[ii].raw_data,
            });
        }
    }
    return ds_value;
},

doDrawing = function(ds_label, ds_value, $chartDrawDiv) {
    console.log(JSON.stringify(ds_label));
    console.log(JSON.stringify(ds_value));
    require(['js/chartingLibraries/fusioncharts-suite-xt/js/fusioncharts.js'], function(){
        const dataSource = {
            chart: {
                caption: "2013年貿易量",
                theme: "fusion",
                orientation: "horizontal",
                nodelabelposition: "start",
            },
            nodes: ds_label,
            links: ds_value
        };
        FusionCharts.ready(function() {
            var myChart = new FusionCharts({
                type: "sankey",
                renderAt: $chartDrawDiv[0],
                width: 800,
                height: 500,
                dataFormat: "json",
                dataSource
            }).render();
        });
    });
};

```
##### プレビュー
[プレビュー] に移り、どのようなチャートが作成されるか確認します。特定の個所にマウスをホバーすると、ツールチップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/66a6ae2d-ea56-f211-02e7-fd7019d42817.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/c8153337-1c23-a921-5a88-298fb2a8c610.png)

## 3. コードの内容
チャートの動作概要が分かったところで、コードの中身を見てみましょう。

##### generateChart
```JavaScript:generateChart
generateChart = function(options) {
   var $chartDrawDiv = $(options.divSelector);
   var processedDataLabel = processDataLabel(options.dataset.data);
   var processedDataValue = processDataValue(options.dataset.data);
   doDrawing(processedDataLabel, processedDataValue, $chartDrawDiv);
},
```

JavaScript グラフの処理において、最初に呼び出されるのが generateChart = function(options) です。
[データ] ステップでテーブルに追加した情報が、options に格納されて、メソッドに受け渡されます。
`var $chartDrawDiv = $(options.divSelector)` でグラフを出力する div を選択します。
`var processedDataLabel = processDataLabel(options.dataset.data);`
`var processedDataValue = processDataValue(options.dataset.data);`
`doDrawing(processedDataLabel, processedDataValue, $chartDrawDiv);`
上記3行で、別の関数を呼び出して、データ処理とグラフ描画処理を行っています。呼び出し先の関数での処理内容は後続の個所で説明をします。

##### processDataLabel
```JavaScript:processDataLabel
    var ds_label = [];
    for (i=0;i<dataset.from.length;i++){
        if(dataset.value[i].formatted_data === "0"){
            ds_label.push({
                label: dataset.from[i].raw_data,
            });
        }
    }
    return ds_label;
```
サンキーダイアグラムの作成にあたって、2 種類のデータセットを作成する必要があります。1 つ目はノードを描画する目的のデータで、国名を取り込みます。2 つ目はデータの流れと量を描画する目的のデータで、from (起点)、to (終点)、value (量) を取り込みます。

processDataLabel では、ノードの情報を扱います。Yellowfin のデータセットを JSON の配列に変換して ds_label にオブジェクトとして格納しています。[データ] ステップでテーブルに追加した列 [from] から、ノード (国名) に用いる情報を取得しています。
今回のサンプルデータであれば、以下のような JSON の書式になります。画面は [グラフ] ステップでディベロッパーツールのコンソールから確認したものです。コードの中に `console.log(JSON.stringify(ds_label))` を記述しておくと、データオブジェクトの中身をコンソールで確認することができます。今回の場合は、doDrawing の先頭に記述しています。デバッグに便利なので、活用してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/fc97eb77-1c1e-2e80-99c4-ce81ae833b20.png)

##### processDataValue
```JavaScript:processData
processDataValue = function(dataset) {
    var ds_value = [];
    for (ii=0;ii<dataset.from.length;ii++){
        if(dataset.value[ii].formatted_data != "0"){
            ds_value.push({
                from: dataset.from[ii].raw_data,
                to: dataset.to[ii].raw_data,
                value: dataset.value[ii].raw_data,
            });
        }
    }
    return ds_value;
},
```

processDataValue ではノード間のデータの量を扱います。Yellowfin のデータセットを JSON の配列に変換して ds_value にオブジェクトとして格納しています。[データ] ステップでテーブルに追加した列 [from] [to] [value] を全て格納して、ノード間のデータの流れを表示するためのデータオブジェクトを作成します。サンプルデータの JSON 書式は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/7f1614b3-2be3-54a5-640a-3a8588d59dce.png)

```JavaScript:doDrawing
doDrawing = function(ds_label, ds_value, $chartDrawDiv) {
    console.log(JSON.stringify(ds_label));
    console.log(JSON.stringify(ds_value));
    require(['js/chartingLibraries/fusioncharts-suite-xt/js/fusioncharts.js'], function(){
        const dataSource = {
            chart: {
                caption: "2013年貿易量",
                theme: "fusion",
                orientation: "horizontal",
                nodelabelposition: "start",
            },
            nodes: ds_label,
            links: ds_value
        };
        FusionCharts.ready(function() {
            var myChart = new FusionCharts({
                type: "sankey",
                renderAt: $chartDrawDiv[0],
                width: 800,
                height: 500,
                dataFormat: "json",
                dataSource
            }).render();
        });
    });
};
```

`require[]` の中で、JavaScriptライブラリーを格納したディレクトリーを相対パスで記述します。

`dataSource` `chart` の中で、チャートのタイトルや凡例などに関する設定を施しています。例えば、`orientation: "horizontal"` の中で、データの流れの方向を水平に指定しています。vertical に変更すると、上から下への流れに変わります。

サンキーダイアグラムを描画するためには、ノード (国名) のデータセットを nodes に、2 か国間のデータの流れを links に受け渡す必要があります。それを実行しているのが、`nodes: ds_label,` と `nodes: ds_value` の 2 行です。

`FusionCharts.ready` でチャートを描画します。
`type: "sankey",` でチャートの種類を指定します。
`renderAt: $chartDrawDiv[0]` でチャートを描画する div を指定します。`$chartDrawDiv` はコードの先頭で宣言した変数です。
`width` と `height` はダッシュボードの大きさなどに合わせてピクセル単位で指定します。FusionCharts のサンプルを見ると、%で指定していますが、Yellowfin で扱う場合は、ピクセルで指定した方がきれいに表示されます。

## 4. 最後に
ナポレオンのロシア進行 (出所：[wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%B3%E3%82%AD%E3%83%BC_%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0) )がサンキーダイアグラムの先駆けになったという説もあるほど、情報の流れを可視化するために、随分昔から使われているチャートなんですね。
是非皆様の業務にも活用してみてください。

では、良いデータ分析を! Cheers!!