はじめに
Yellowfin と amCharts JavaScript ライブラリの活用第2弾として、今回はベン図を作成したいと思います。ちなみに、第一弾はこちら。
事前準備
1-1. ビューの作成まで
以前の記事 を参考に、『1-2. ビューの作成』 までの作業を実施します。
今回ビューが参照するテーブルのデータは以下です。犬好きか、猫好きか、あるいは両方好きかのアンケート結果とお考え下さい。
name | dog | cat |
---|---|---|
ゆい | はい | いいえ |
たろう | いいえ | はい |
みなみ | はい | いいえ |
しょうのすけ | はい | いいえ |
ななえ | いいえ | はい |
ステファン | はい | はい |
上記テーブルの内容を、参照コードを使って以下のように修正します。dog 列の「はい」を「犬」に、cat 列の「はい」を「猫」に置き換えているだけです。
name | dog | cat |
---|---|---|
ゆい | 犬 | いいえ |
たろう | いいえ | 猫 |
みなみ | 犬 | いいえ |
しょうのすけ | 犬 | いいえ |
ななえ | いいえ | 猫 |
ステファン | 犬 | 猫 |
2. グラフの作成
準備が整ったら、グラフの作成に手順を進めます。新規でレポートを作成し、以下の手順に従ってグラフを作成します。
2-1. [データ] ステップ
dog、cat、name 列をテーブルに配置し、name の個数を count するテーブルを作成します。
Yellowfin の集約に関しては、こちらをご参照ください。
2-2. [グラフ] ステップ
[グラフ] ステップに進み、画面右側 [グラフの選択] から [JavaScriptグラフ] を選択します。
JavaScriptタブ
雛形を全て削除し、以下のコードに置き換えます。コードの処理の内容は後ほど説明します。
generateChart = function(options) {
var $chartDrawDiv = $(options.divSelector);
var processedData = processData(options.dataset.data);
doDrawing($chartDrawDiv, processedData);
},
processData = function(dataset) {
var ds = [];
for (i=0;i<dataset.dog.length;i++){
if(dataset.dog[i].raw_data == 'はい' && dataset.cat[i].raw_data == 'いいえ'){
var sets1 = [];
sets1.push(dataset.dog[i].formatted_data);
ds.push({
name: dataset.dog[i].formatted_data,
value: dataset.name[i].formatted_data,
sets: sets1,
sliceSettings: {
fill: am5.color(0x6e5a40)
}
});
} else if(dataset.dog[i].raw_data == 'いいえ' && dataset.cat[i].raw_data == 'はい'){
var sets2 = [];
sets2.push(dataset.cat[i].formatted_data);
ds.push({
name: dataset.cat[i].formatted_data,
value: dataset.name[i].formatted_data,
sets: sets2,
sliceSettings: {
fill: am5.color(0xb1d245),
}
});
} else if(dataset.dog[i].raw_data == 'はい' && dataset.cat[i].raw_data == 'はい'){
var sets3 = [];
sets3.push(dataset.dog[i].formatted_data);
sets3.push(dataset.cat[i].formatted_data);
ds.push({
name: "両方",
value: dataset.name[i].formatted_data,
sets: sets3,
sliceSettings: {
fill: am5.color(0x5aaa95),
}
});
}
}
console.log(JSON.stringify(ds));
return ds;
},
doDrawing = function($chartDrawDiv, ds, obj) {
require(['https://cdn.amcharts.com/lib/5/index.js','https://cdn.amcharts.com/lib/5/venn.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 container = root.container.children.push(am5.Container.new(root, {
width: am5.p100,
height: am5.p100,
layout: root.verticalLayout
}));
var chart = container.children.push(am5venn.Venn.new(root, {
categoryField: "name",
valueField: "value",
intersectionsField: "sets",
paddingTop: 40,
paddingBottom: 40,
paddingLeft: 40,
paddingRight: 40
}));
var pattern = am5.CirclePattern.new(root, {
fill: am5.color(0x000000),
color: am5.color(0xffffff),
radius: 10,
gap: 10,
checkered: true
})
chart.slices.template.setAll({ templateField: "sliceSettings" });
chart.labels.template.set("fill", am5.color(0xffffff));
chart.labels.template.setup = function(target) {
target.set("background", am5.RoundedRectangle.new(root, {
stroke: am5.color(0xffffffff),
fill: am5.color(0x000000),
cornerRadiusTL: 5,
cornerRadiusTR: 5,
cornerRadiusBL: 5,
cornerRadiusBR: 5,
fillOpacity: 1
}));
};
chart.data.setAll(ds);
chart.hoverGraphics.setAll({
strokeDasharray: [3, 3],
stroke: am5.color(0xffffff),
strokeWidth: 2
});
});
});
};
コード
コードの中身を、順を追って説明します。
generateChart
generateChart = function(options) {
var $chartDrawDiv = $(options.divSelector);
var processedData = processData(options.dataset.data);
doDrawing($chartDrawDiv, processedData);
},
- JavaScript グラフの処理において、最初に呼び出されるのが generateChart = function(options) です
- [データ] ステップでテーブルに追加した情報が options に格納されて、メソッドに受け渡されます
- processData でデータ処理を行うメソッドを呼び出し、doDrawingで描画するメソッドをそれぞれ呼び出しています。各メソッドで実行する具体的な処理は後述します
processData
processData = function(dataset) {
var ds = [];
for (i=0;i<dataset.dog.length;i++){
if(dataset.dog[i].raw_data == 'はい' && dataset.cat[i].raw_data == 'いいえ'){
var sets1 = [];
sets1.push(dataset.dog[i].formatted_data);
ds.push({
name: dataset.dog[i].formatted_data,
value: dataset.name[i].formatted_data,
sets: sets1,
sliceSettings: {
fill: am5.color(0x6e5a40)
}
});
} else if(dataset.dog[i].raw_data == 'いいえ' && dataset.cat[i].raw_data == 'はい'){
var sets2 = [];
sets2.push(dataset.cat[i].formatted_data);
ds.push({
name: dataset.cat[i].formatted_data,
value: dataset.name[i].formatted_data,
sets: sets2,
sliceSettings: {
fill: am5.color(0xb1d245),
}
});
} else if(dataset.dog[i].raw_data == 'はい' && dataset.cat[i].raw_data == 'はい'){
var sets3 = [];
sets3.push(dataset.dog[i].formatted_data);
sets3.push(dataset.cat[i].formatted_data);
ds.push({
name: "両方",
value: dataset.name[i].formatted_data,
sets: sets3,
sliceSettings: {
fill: am5.color(0x5aaa95),
}
});
}
}
console.log(JSON.stringify(ds));
return ds;
},
processData メソッドで、下記データが生成されます。
[{
"name": "猫",
"value": 2,
"sets": ["猫"],
"sliceSettings": {"fill":{"_hex":11653701}
},{
"name": "犬",
"value": 3,
"sets": ["犬"],
"sliceSettings": {"fill":{"_hex":7232064}
},{
"name": "両方",
"value": 1,
"sets": ["犬","猫"],
"sliceSettings": {"fill":{"_hex":5941909}
}
}]
- if で 3 条件に分けて、データセットを作成しています。if 条件の中では、raw_data を使って条件分岐を行っています。raw_data は、参照コードで値を置き替える前の元データを参照するときは、raw_data を指定します
- sets キーの値は、[] で囲まれた配列の形になっています。つまり、JSON 全体としては、配列の入れ子構造になっています。そのため、予め set1 = で配列の値を作成しておいて、後に親の JSON データの sets の値に指定しています
- sets1.push や ds.push などの中では、配列に formatted_data を追加しています。formatted_data は参照コードで値を置き替えた後のデータを参照する時に指定します
- sliceSettings キーの値には、丸の内部を塗りつぶす色を固定値で設定しています。もちろん、データベースから色を定義する 16 進数のデータを取得して、ここに設定しても大丈夫です。sliceSettings で設定できる値一覧はこちらでご確認ください
- 生成されるデータの中身を確認したい場合は、
console.log(JSON.stringify(ds_coffee))
で、データをコンソールに出力しておくと便利です
CSS
#chartdiv{
height: 500px;
width: 100%;
}
- CSS タブに上記を記述します。後ほど、定義した id を JavaScript から呼び出します
doDrawing
doDrawing = function($chartDrawDiv, ds, obj) {
require(['https://cdn.amcharts.com/lib/5/index.js','https://cdn.amcharts.com/lib/5/venn.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 container = root.container.children.push(am5.Container.new(root, {
width: am5.p100,
height: am5.p100,
layout: root.verticalLayout
}));
var chart = container.children.push(am5venn.Venn.new(root, {
categoryField: "name",
valueField: "value",
intersectionsField: "sets",
paddingTop: 40,
paddingBottom: 40,
paddingLeft: 40,
paddingRight: 40
}));
var pattern = am5.CirclePattern.new(root, {
fill: am5.color(0x000000),
color: am5.color(0xffffff),
radius: 10,
gap: 10,
checkered: true
})
chart.slices.template.setAll({ templateField: "sliceSettings" });
chart.labels.template.set("fill", am5.color(0xffffff));
chart.labels.template.setup = function(target) {
target.set("background", am5.RoundedRectangle.new(root, {
stroke: am5.color(0xffffffff),
fill: am5.color(0x000000),
cornerRadiusTL: 5,
cornerRadiusTR: 5,
cornerRadiusBL: 5,
cornerRadiusBR: 5,
fillOpacity: 1
}));
};
chart.data.setAll(ds);
chart.hoverGraphics.setAll({
strokeDasharray: [3, 3],
stroke: am5.color(0xffffff),
strokeWidth: 2
});
});
});
};
-
require[]
の中で、JavaScriptライブラリの場所を指定します。上記の例では CDN のアドレスを指定していますが、JS ライブラリをダウンロードして利用することも可能です -
var root = am5.Root.new("chartdiv")
で、CSS で定義した id を指定します
root.setThemes
で、デザインのテーマを指定します。今回は動きのある Animated を指定していますが、その他にもこちらのテーマが指定可能です。 -
container
、pattern
、chart.slices
、chart.labels
、chart.hoverGraphics
では、チャートの見た目を定義しています。各項目の詳細は、Common elements や Venn diagram をご参照ください -
chart.data.setAll(ds)
の中で、作成したデータセットを、描画用のメソッドに受け渡しています。渡す際のデータ型は、JSON オブジェクトである必要があります
これでベン図の完成です。
最後に
Yellowfin と JS チャートを連携する際、Yellowfin のデータを、いかにしてチャートの仕様に合わせたデータ型に生成するががカギとなります。
今回のような、配列の入れ子になっているデータ型でも、さほど問題なく生成することができました。
Yellowfin の機能を補完することができるように、様々なチャートの作成に挑戦してみようと思います。
では皆様、良いデータ分析を!