0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

動的なチャートでオブジェクト同士の関係性を可視化 ‐ Yellowfin と amCharts の連携

Posted at

はじめに

amCharts という JavaScript ライブラリを活用すると、色々と動きの面白いチャートを作成することができます。
今回はその中から、Directed Tree のチャートを使った例を紹介したいと思います。
hierarchy (1).gif

事前準備

1-1. ビューの作成まで

以前の記事 を参考に、『1-2. ビューの作成』 までの作業を実施します。
今回使うデータは以下の表です。飲料製品の、各カテゴリとブランドのつながりを示すものとお考え下さい。

category bland value
コーヒー コナ 37
コーヒー モカ 37
コーヒー ブレンド 41
コーヒー トラジャ 43
紅茶 アッサム 42
紅茶 ウヴァ 37
紅茶 ジャワ 38
紅茶 セイロン 42
日本茶 緑茶 39
日本茶 ほうじ茶 42
日本茶 麦茶 39
日本茶 玄米茶 39
ソーダ ファンタ 40
ソーダ コーラ 38
ソーダ サイダー 41
ソーダ 強炭酸 41

2. グラフの作成

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

2-1. [データ] ステップ

ビューに設定した軸と集計値をテーブルに配置します。
image.png

2-2. [グラフ] ステップ

[グラフ] ステップに進み、画面右側 [グラフの選択] から [JavaScriptグラフ] を選択します。
image.png

JavaScriptタブ

雛形を全て削除し、以下のコードに置き換えます。コードの処理の内容は後ほど説明します。

全容
generateChart = function(options) {
   var $chartDrawDiv = $(options.divSelector);
   var processedCoffee = processCoffee(options.dataset.data);
   var processedTea = processTea(options.dataset.data);
   var processedJapan = processJapan(options.dataset.data);
   var processedSoda = processSoda(options.dataset.data);
   doDrawing($chartDrawDiv, processedCoffee, processedTea, processedJapan, processedSoda);
},

processCoffee = function(dataset) {
    var ds_coffee = [];
    for (i=0;i<dataset.category.length;i++){
        if(dataset.category[i].raw_data === "コーヒー"){
            ds_coffee.push({
                name: dataset.bland[i].raw_data,
                value: dataset.value[i].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_coffee));
    return ds_coffee;
},

processTea = function(dataset) {
    var ds_tea = [];
    for (ii=0;ii<dataset.category.length;ii++){
        if(dataset.category[ii].raw_data === "紅茶"){
            ds_tea.push({
                name: dataset.bland[ii].raw_data,
                value: dataset.value[ii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_tea));
    return ds_tea;
},

processJapan = function(dataset) {
    var ds_japan = [];
    for (iii=0;iii<dataset.category.length;iii++){
        if(dataset.category[iii].raw_data === "日本茶"){
            ds_japan.push({
                name: dataset.bland[iii].raw_data,
                value: dataset.value[iii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_japan));
    return ds_japan;
},

processSoda = function(dataset) {
    var ds_soda = [];
    for (iiii=0;iiii<dataset.category.length;iiii++){
        if(dataset.category[iiii].raw_data === "ソーダ"){
            ds_soda.push({
                name: dataset.bland[iiii].raw_data,
                value: dataset.value[iiii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_soda));
    return ds_soda;
},

doDrawing = function($chartDrawDiv, ds_coffee, ds_tea, ds_japan, ds_soda) {
    require(['https://cdn.amcharts.com/lib/5/index.js','https://cdn.amcharts.com/lib/5/hierarchy.js','https://cdn.amcharts.com/lib/5/themes/Animated.js'], function(){
        var $canvas = $('<div id="chartdiv"></div>');
        $chartDrawDiv.append($canvas);

        am5.ready(function() {
            var root = am5.Root.new("chartdiv");
        
        root.setThemes([
          am5themes_Animated.new(root)
        ]);
        
        var data = {
          value: 0,
          children: [
            {
              name: "コーヒー",
              children: ds_coffee
            },
            {
              name: "紅茶",
              children: ds_tea
            },
            {
              name: "日本茶",
              children: ds_japan
            },
            {
              name: "ソーダ",
              children: ds_soda
            }
          ],
        };
        
        var zoomableContainer = root.container.children.push(
          am5.ZoomableContainer.new(root, {
            width: am5.p100,
            height: am5.p100,
            wheelable: true,
            pinchZoom: true
          })
        );
        
        var zoomTools = zoomableContainer.children.push(am5.ZoomTools.new(root, {
          target: zoomableContainer
        }));
        
        var series = zoomableContainer.contents.children.push(am5hierarchy.ForceDirected.new(root, {
          maskContent:false,
          singleBranchOnly: false,
          downDepth: 2,
          topDepth: 1,
          initialDepth: 3,
          valueField: "value",
          categoryField: "name",
          childDataField: "children",
          idField: "name",
          linkWithField: "linkWith",
          manyBodyStrength: -10,
          centerStrength: 0.8
        }));
        
        series.get("colors").setAll({
          step: 2
        });
        series.links.template.set("strength", 0.5);
        series.labels.template.set("minScale", 0);
        series.data.setAll([data]);
        series.set("selectedDataItem", series.dataItems[0]);
        series.appear(1000, 100);
        
        });
    });
};

コード

generateChart
generateChart
generateChart = function(options) {
   var $chartDrawDiv = $(options.divSelector);
   var processedCoffee = processCoffee(options.dataset.data);
   var processedTea = processTea(options.dataset.data);
   var processedJapan = processJapan(options.dataset.data);
   var processedSoda = processSoda(options.dataset.data);
   doDrawing($chartDrawDiv, processedCoffee, processedTea, processedJapan, processedSoda);
},

JavaScript グラフの処理において、最初に呼び出されるのが generateChart = function(options) です。
[データ] ステップでテーブルに追加した情報が options に格納されて、メソッドに受け渡されます。
processCoffee、ProcessTea、ProcessJapan、ProcessSoda でデータ処理を行うメソッドを呼び出し、doDrawingで描画するメソッドをそれぞれ呼び出しています。各メソッドで実行する具体的な処理は後述します。

processCoffee
processCoffee
processCoffee = function(dataset) {
    var ds_coffee = [];
    for (i=0;i<dataset.category.length;i++){
        if(dataset.category[i].raw_data === "コーヒー"){
            ds_coffee.push({
                name: dataset.bland[i].raw_data,
                value: dataset.value[i].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_coffee));
    return ds_coffee;
},

コーヒーのツリーに結び付けるデータを、配列の形でデータセットに格納します。name にブランドを、value に売上を格納します。
console.log(JSON.stringify(ds_coffee)) を仕込んでおくと、下のようにブラウザのコンソールで具体的なデータを確認することができます。
image.png

processTea
processTea
processTea = function(dataset) {
    var ds_tea = [];
    for (ii=0;ii<dataset.category.length;ii++){
        if(dataset.category[ii].raw_data === "紅茶"){
            ds_tea.push({
                name: dataset.bland[ii].raw_data,
                value: dataset.value[ii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_tea));
    return ds_tea;
},

同様に、紅茶のツリーに結び付けるデータを、配列の形でデータセットに格納します。

processJapan
processJapan
processJapan = function(dataset) {
    var ds_japan = [];
    for (iii=0;iii<dataset.category.length;iii++){
        if(dataset.category[iii].raw_data === "日本茶"){
            ds_japan.push({
                name: dataset.bland[iii].raw_data,
                value: dataset.value[iii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_japan));
    return ds_japan;
},

次に日本茶です。

processSoda
processSoda
processSoda = function(dataset) {
    var ds_soda = [];
    for (iiii=0;iiii<dataset.category.length;iiii++){
        if(dataset.category[iiii].raw_data === "ソーダ"){
            ds_soda.push({
                name: dataset.bland[iiii].raw_data,
                value: dataset.value[iiii].raw_data,
            });
        }
    }
    console.log(JSON.stringify(ds_soda));
    return ds_soda;
},

最後にソーダです。

CSS
css
##### CSS
#chartdiv{
    height: 500px;
    width: 100%;
}

CSS タブに上記を記述します。後ほど、定義した id を JavaScript から呼び出します。

doDrawing
doDrawing
doDrawing = function($chartDrawDiv, ds_coffee, ds_tea, ds_japan, ds_soda) {
    require(['https://cdn.amcharts.com/lib/5/index.js','https://cdn.amcharts.com/lib/5/hierarchy.js','https://cdn.amcharts.com/lib/5/themes/Animated.js'], function(){
        var $canvas = $('<div id="chartdiv"></div>');
        $chartDrawDiv.append($canvas);

        am5.ready(function() {
                var root = am5.Root.new("chartdiv");
        
        root.setThemes([
          am5themes_Animated.new(root)
        ]);
        
        var data = {
          value: 0,
          children: [
            {
              name: "コーヒー",
              children: ds_coffee
            },
            {
              name: "紅茶",
              children: ds_tea
            },
            {
              name: "日本茶",
              children: ds_japan
            },
            {
              name: "ソーダ",
              children: ds_soda
            }
          ],
        };
        
        var zoomableContainer = root.container.children.push(
          am5.ZoomableContainer.new(root, {
            width: am5.p100,
            height: am5.p100,
            wheelable: true,
            pinchZoom: true
          })
        );
        
        var zoomTools = zoomableContainer.children.push(am5.ZoomTools.new(root, {
          target: zoomableContainer
        }));
        
        var series = zoomableContainer.contents.children.push(am5hierarchy.ForceDirected.new(root, {
          maskContent:false,
          singleBranchOnly: false,
          downDepth: 2,
          topDepth: 1,
          initialDepth: 3,
          valueField: "value",
          categoryField: "name",
          childDataField: "children",
          idField: "name",
          linkWithField: "linkWith",
          manyBodyStrength: -10,
          centerStrength: 0.8
        }));
        
        series.get("colors").setAll({
          step: 2
        });
        series.links.template.set("strength", 0.5);
        series.labels.template.set("minScale", 0);
        series.data.setAll([data]);
        series.set("selectedDataItem", series.dataItems[0]);
        series.appear(1000, 100);
        
        });
    });
};

require[] の中で、JavaScriptライブラリの場所を指定します。上記の例では CDN のアドレスを指定していますが、JS ライブラリをダウンロードして利用することも可能です。
var root = am5.Root.new("chartdiv") で、CSS で定義した id を指定します。
root.setThemes で、デザインのテーマを指定します。今回は動きのある Animated を指定していますが、その他にもこちらのテーマが指定可能です。
var data = {}の中で、作成したデータセットを、描画用のメソッドに受け渡しています。
var zoomableContainervar zoomTools で、マウス操作および画面上のアイコンによるズームを可能にします。
var series 以降で、表示内容やフィールド名称などに関する一通りの設定を設定し、適用しています。各設定の詳細はこちらでご確認ください。

出来上がり

結果、以下のようなチャートが出来上がりました。
image.png

最後に

オブジェクト同士のつながりは、やはり見やすいチャートで可視化したいものですね。
何より動きがあるチャートは見栄えが良い。
具体的な用途としては、人と人との関係性を可視化することなどにも使えそうですね。例えば親族同士のつながりを可視化して、インサイダー取引の疑いがある時に確認するなど。
他にも考えられ得る使用方法があれば是非ご意見ください。

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?