Google Chart Tools - 表とデータの扱い
今回は Google Chart Tools を使った表の作成と Google Chart でデータ(DataTable)の扱いについて説明します。
html で表が書けるのになぜわざわざ Google Chart Tools で表を書くの ? と思われるかも知れませんが、 Google Chart Tools の表では次のことが簡単にできます。
- ソート
- テーブル内に割合のバーなどを表示
- ページ分割(ページネーション)
- 他のグラフと連携
- フィルタリング
特にソートやフィルターでは、データを値と表示文字を分けて管理できるので、 文字列の比較ではなく、実際の値での比較ができるようになっています。
なお、他のグラフとの連携やフィルタリングについては次回以降に説明する予定です。 また、 Google Chart では DataTable を元にグラフを描画します。
表(のグラフ)は DataTable をそのまま表示しているようなものです。 Google Chart のデータの扱いの理解に表はちょうどいいのではないかと思います。
基本的な表の作成
まずは基本的な表の書き方を説明します。<html> <head> <script type='text/javascript' src='https://www.google.com/jsapi'></script> <script type='text/javascript'> google.load('visualization', '1', {packages:['table']}); google.setOnLoadCallback(drawTable); function drawTable() { var data = new google.visualization.DataTable(); data.addColumn('string', '名前'); data.addColumn('number', '給料'); data.addColumn('boolean', 'フルタイム'); data.addRows([ ['Mike', {v: 10000, f: '$10,000'}, true ], ['Jim', {v: 8000, f: '$8,000'}, false], ['Alice', {v: 12500, f: '$12,500'}, true ], ['Bob', {v: 7000, f: '$7,000'}, true ] ]); var table = new google.visualization.Table(document.getElementById('table_div')); table.draw(data, {showRowNumber: true}); } </script> </head> <body> <div id="table_div" style="width: 80%; "></div> </body> </html>前回の折れ線グラフと書き方はほぼ同じです。 違いは次のところです。
- ロードパッケージが 'table'
- 描画用クラスが google.visualization.Table
データを値と表示文字を分ける場合には、オブジェクトで指定します。 この場合 v が値で f が表示文字列です。
これ以外にも p で装飾を指定することもできます。 装飾に関しては 'className' で html タグのクラス名を指定できるので、 CSS で指定することもできます。
'style' で直接 CSS のスタイルも書けます。
データテーブル(DataTable)
Google Chart Tools で扱うデータは google.visualization.DataTable オブジェクトです。これは 2 次元のデータと列情報の配列を持ちます。 列情報ではラベルや列に格納するデータの型を保持します。
列情報にデータ型情報を持っているので、 同一の列では同じ型のみ格納できます。
データテーブルの作成は 3 つの方法があります。
- 空のオブジェクトを作成し、addColumn, addRows などでデータを格納
- JSON 形式で定義したデータから作成
- 2 次元配列から作成
2 番目は JSON スタイルでオブジェクトを作成し、 それを元に DataTable を作成する方法です。
記述が面倒なので、この形式でコード内に直接記述することはあまりないかもしれません。 ただし、 1 番目の方法に比べるとロードが速いので、 データの量が多い場合などではこちらの方がいいでしょう。
var dataAsJson = {cols:[ {id:'A',label:'名前',type:'string'}, {id:'B',label:'給料',type:'number'}, {id:'C',label:'フルタイム',type:'boolean'}], rows:[ {c:[{v:'Mike'},{v:10000,f:'$10,000'},{v:true,f:'TRUE'}]}, {c:[{v:'Jim'},{v:8000,f:'$8,000'},{v:false,f:'FALSE'}]}, {c:[{v:'Alice'},{v:12500,f:'$12,500'},{v:true,f:'TRUE'}]}, {c:[{v:'Bob'},{v:7000,f:'$7,000'},{v:true,f:'TRUE'}]}] }; var data = new google.visualization.DataTable(dataAsJson);前回の折れ線グラフの例では arrayToDataTable を使った二次元配列から作成する 3 番目の方法でした。
この場合、 1 列目からラベルを取得し、各列のデータから自動的に型を判定しています。 今回のサンプルを arrayToDataTable を使って作成すると次のようになります。
var data = new google.visualization.arrayToDataTable([ ['名前', '給料', 'フルタイム'], ['Mike', 10000, true ], ['Jim', 8000, false], ['Alice', 12500, true ], ['Bob', 7000, true ] ]);
ただし、表示文字と値を分けていません。 これは arrayToDataTable ではオブジェクトによる指定はできないためです。
二次元配列から作成するのが一番簡単ですが、 値と表示文字を分ける場合には addColumn, addRows 等を使うか JSON スタイルで作成する必要があります。
なお、 arrayToDataTable でもデータの先頭列(2 列目)以降であれば、 オブジェクトによる指定も可能です。
フォーマット
{v: 10000, f: '$10,000'}
のように似たものを
2 回書いたり、配列から DataTable が作れないのは面倒だなと感じたかもしれません。
こういった場合は Format の機能を使えます。また、 Format ではデータの表示を国際化することもできます。
国際化の言語はブラウザーの設定がデフォルトです。 これはパッケージロード時に明示的に変更することも可能です。
数値フォーマット
数値の場合には NumberFormat を使用します。var data = new google.visualization.arrayToDataTable([ ['名前', '給料', '到達率'], ['Mike', 10000, 0.2 ], ['Jim', 8000, 1.0], ['Alice', 12500, 0.9 ], ['Bob', 7000, 0.7 ] ]); var table = new google.visualization.Table(document.getElementById('gct_table_number_format')); // 2 列目のフォーマッター var formatter1 = new google.visualization.NumberFormat({pattern: '$#,###'}); formatter1.format(data, 1); // 3 列目のフォーマッター var formatter2 = new google.visualization.NumberFormat({pattern: '###%'}); formatter2.format(data, 2); table.draw(data, {showRowNumber: true});NumberFormat のインスタンス作成時に渡すオブジェクトで表示形式を指定します。
prefix や suffix といった要素もあるのですが、 pattern が指定されているとこちらが使用されます。 ここには 数値用の ICU のパターンを指定します。
日付フォーマット
日付の場合には DateFormat を使用します。var data = new google.visualization.DataTable(); data.addColumn('string', '雇用者名前'); data.addColumn('date', '開始日 (Long 表記)'); data.addColumn('date', '開始日 (Short 表記)'); data.addRows([ ['Mike', new Date(2008, 1, 28, 0, 31, 26), new Date(2008, 1, 28, 0, 31, 26)], ['Bob', new Date(2007, 5, 1, 0), new Date(2007, 5, 1, 0)], ['Alice', new Date(2006, 7, 16), new Date(2006, 7, 16)] ]); // フォーマッターの作成 var formatter_long = new google.visualization.DateFormat({formatType: 'long'}); var formatter_short = new google.visualization.DateFormat({formatType: 'short'}); // データを整形 formatter_long.format(data, 1); formatter_short.format(data, 2); // データを描画 var table = new google.visualization.Table(document.getElementById('gct_table_date_format')); table.draw(data, {showRowNumber: true});データには JavaScript の Date オブジェクトを格納し、 DateFormat で表示形式を指定します。
formatType には "long", "short" の他に "medium" もあります。 ただし、日本語では short と medium は同じです。
DateFormat を使わずにそのまま表示した場合も short です。
また、pattern で出力形式を詳細に設定することもできます。 この場合には 日付用の ICU のパターンを指定します。
ちなみに Google Chart Tools というよりも JavaScript の注意点があります。
日付は Date(年, 月, 日) と指定します。 この際、 年、日は一般的な 2012 や 1 - 31 といった数値を指定しますが、 月は 0(1 月) - 11(12 月) で指定します。
パターンフォーマット
複数の列から新しい列を作成する場合には PatternFormat を使用します。var data = new google.visualization.DataTable(); data.addColumn('string', '名前'); data.addColumn('string', 'E-Mail'); data.addRows([ ['John Lennon', 'john@beatles.co.uk'], ['Paul McCartney', 'paul@beatles.co.uk'], ['George Harrison', 'george@beatles.co.uk'], ['Ringo Starr', 'ringo@beatles.co.uk'] ]); var table = new google.visualization.Table(document.getElementById('gct_table_pattern_format_div')); var formatter = new google.visualization.PatternFormat('<a href="mailto:{1}">{0}</a>'); // フォーマッターで、 0, 1 の列のデータから作ったデータを 0 列に格納 formatter.format(data, [0, 1]); // 先頭(0)列のみ表示するように DataView を作成 var view = new google.visualization.DataView(data); view.setColumns([0]); // 渡すのは data ではなく、 view // allowHtml はテーブル内での html 記述許可の設定 table.draw(view, {allowHtml: true, showRowNumber: true});PatternFormat を使い、 2 つの列から新しいデータを作成し、 1 列目に格納しています。
PatternFormat::format(データ, 利用する列の列番号配列 [, 格納先の列番号]); // 格納先を省略した場合には利用した列に格納されますテーブルの描画には通常は DataTable を直接渡しますが、 表示する列を指定するために DataView を作成し、それを介して描画しています。
装飾系フォーマット
前章は表示文字を変更するための Format でしたが、 テーブル内にバーを表示するといった装飾的な機能も Format で実現します。バーフォーマット
テーブル内にバーを表示する場合には BarFormat を使用します。var data = new google.visualization.DataTable(); data.addColumn('string', '分類'); data.addColumn('number', '収入'); data.addRows([ ['靴', 10700], ['スポーツ', -15400], ['おもちゃ', 12500], ['電化製品', -2100], ['食品', 22600], ['美術品', 1100] ]); var table = new google.visualization.Table(document.getElementById('gct_table_bar_format')); // バーの幅を 120pt に設定。(デフォルトは 100) var formatter = new google.visualization.BarFormat({width: 120}); formatter.format(data, 1); // 2 番目の列に適用 table.draw(data, {allowHtml: true, showRowNumber: true});
矢印フォーマット
テーブル内に矢印を表示する場合には ArrowFormat を使用します。var data = new google.visualization.arrayToDataTable([ ['分類', '収益率'], ['靴', 0.12], ['スポーツ', -0.073], ['おもちゃ', 0], ['電化製品', -0.21], ['食品', 0.22] ]); var table = new google.visualization.Table(document.getElementById('gct_table_number_format')); // 数値フォーマットも使用 var num_formatter = new google.visualization.NumberFormat({pattern: '###.#%'}); num_formatter.format(data, 1); // 矢印フォーマット var formatter = new google.visualization.ArrowFormat(); formatter.format(data, 1); var table = new google.visualization.Table(document.getElementById('gct_table_arrow_format')); table.draw(data, {allowHtml: true, showRowNumber: true});
カラーフォーマット
セルの値に応じて色を変更する場合には ColorFormat を使用します。var data = new google.visualization.arrayToDataTable([ ['名前', '点数'], ['Mike', 38 ], ['Jim', 85], ['Alice', 52 ], ['Bob', 70 ] ]); var table = new google.visualization.Table(document.getElementById('gct_table_number_format')); // 数値のフォーマッターも使用 var formatter1 = new google.visualization.NumberFormat({suffix:'点'}); formatter1.format(data, 1); var formatter = new google.visualization.ColorFormat(); // 0 - 40 は白字に赤 formatter.addRange(0, 40, 'white', 'red'); // 40 - 80 は黄色から白への段階 formatter.addGradientRange(40, 80, null, 'yellow', 'white'); // 80 - 100 は青字 formatter.addRange(80, 100, 'blue', null); formatter.format(data, 1); table.draw(data, {allowHtml: true, showRowNumber: true});色と範囲の設定は次の関数を使います。
- addRange(開始値, 終了値, 文字色, 背景色)
- addGradientRange(開始値, 終了値, 文字色, 開始背景色, 終了背景色)
ちなみに段階的に文字色(前景色)を指定する関数はありません。
ページ分割
ページ分割(ページネーション, ページング) というのは、データがたくさんある場合に 一定数づつ分割して表示することを言います。個人的には一度に表示してスクロールで見る方が好きなのですが、 海外ではページ分割して表示するのが主流っぽいです。
ページ分割するにはテーブル描画のオプションでページ分割の設定を有効にします。
var data = new google.visualization.arrayToDataTable([ ['名前', '身長', '出席'], ['Dave', 159, true ], ['Peter', 185, false], ['John', 145, true ], ['Moshes', 198, true ], ['Karen', 169, true ], ['Phil', 169, false], ['Gori', 159, true ], ['Bill', 155, false], ['Valery', 199, true ], ['Joey', 187, true ], ['Karen', 190, true ], ['Jin', 169, false], ['Gili', 178, true ], ['Harry', 172, false], ['Handerson', 175, true ], ['Vornoy', 170, true ] ]); // ページ分割の設定 var options = { page: 'enable', // ページ分割を有効 pageSize: 5, // 1 ページの項目数 pagingSymbols: {prev: '前', next: '次'}, // ラベル }; options['showRowNumber'] = true; var table = new google.visualization.Table(document.getElementById('gct_table_pagenation')); table.draw(data, options);
Google Chart Tools - 円グラフ、計器図
今回は Google Chart Tools の円グラフと計器図です。
グラフの基本的な記述方法ついては省略していますので、 詳細は初回記事をご覧ください。円グラフ(Pie Chart)
円グラフには Pie Chart を使用します。<script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> var data = google.visualization.arrayToDataTable([ [ '', ''], [ '仕事', 11], [ '食事', 2], [ '通勤', 2], ['TV 鑑賞', 2], [ '睡眠', 7] ]); var options = { title: '一日の活動', }; var chart = new google.visualization.PieChart( document.getElementById('gct_sample_pie_l')); chart.draw(data, options); </script> <div id="gct_sample_pie" style="width:60%; height:200pt" ></div>初回のサンプルで使っていましたが、 is3D オプションを true に設定すると 3D 表示となります。
データ形式
円グラフでは DataTable のデータを次のように使います。
列は 2 列のみ指定します。 先頭列が項目名で、 2 列目がデータの値です。 割合(%) は自動で計算されます。
先頭行(列情報)は特に使用しません。
計器図(Gauge)
もうグラフやチャートとは呼べなくなってきていますが、 Google Chart Tools ではスピードメーターのような Gauge が用意されています。これは Google Web Font でのフォントのロード時間の表示などに利用されています。
google.load("visualization", "1", {packages:["gauge"]}); google.setOnLoadCallback( function() { var data = google.visualization.arrayToDataTable([ [ '', ''], [ 'Memory', 80], [ 'CPU', 55], ['Network', 68] ]); var options = { redFrom: 90, redTo: 100, // 赤の範囲 yellowFrom: 75, yellowTo: 90, // 黄色の範囲 minorTicks: 5 // 小目盛りの単位 (デフォルトは 2) }; var chart = new google.visualization.Gauge( document.getElementById('gct_sample_gauge')); chart.draw(data, options); } );注意点としては Gauge のパッケージは corechart ではなく、 "gauge" を使います。
オプションで赤、黄色、緑のゾーンを指定することができます。
色 | オプション |
---|---|
赤 | redFrom, redTo |
黄色 | yellowFrom, yellowTo |
緑 | greenFrom, greenTo |
データ形式
計器図では DataTable のデータを次のように使います。
円グラフと同様に列は 2 列のみ指定します。 1 行が 1 つのメーターとなります。
先頭行(列情報)は特に使用しません。
次のように 1 列を 1 つのメーターとする書き方もできます。
var data = google.visualization.arrayToDataTable([ ['Memory', 'CPU', 'Network'], [ 80, 55, 68] ]);
ただし、範囲、色のゾーンを各メーターで別々に指定できないので、 一度に複数のメーターを表示することはあまりないかも知れません。
Google Chart Tools - 動的なグラフの変更
Google Chart Tools では基本的にページのロード時にグラフの作成を行います。 今回は一度作成したグラフを動的に変更する方法についてです。
再描画(ブラウザーのリサイズへの対応)
Google Chart Tools では、 100%, 80% といったページサイズに合わせたグラフの作成が可能です。しかし、ブラウザーのサイズを変更した場合には、それに追従して再描画するところまでは行いません。
動的なグラフの変更の手始めとして、このブラウザーへのリサイズに合わせて再描画できるグラフを作成します。
ブラウザーのサイズを変更すると <body> で onresize イベントが発生します。
ここでグラフの再描画を行います。
<html> <head> <title> リサイズするグラフのサンプル </title> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("visualization", "1", {packages:["corechart"]}); var resizable_chart; var resizable_options; var resizable_data; google.setOnLoadCallback( function () { resizable_data = google.visualization.arrayToDataTable([ [ '', '売上高', '営業利益', '経常利益'], ['2004', 1000, 400, 380], ['2005', 1170, 460, 400], ['2006', 660, 1120, 900], ['2007', 1030, 540, 480], ['2008', 1350, 750, 800], ['2009', 1205, 1010, 805], ['2010', 880, 585, 500], ['2011', 1450, 1300, 1005], ['2012', 1105, 770, 650], ]); resizable_options = { title: '会社業績' }; resizable_chart = new google.visualization.LineChart(document.getElementById('gct_resizable_chart')); resizable_chart.draw(resizable_data, resizable_options); } ); </script> </head> <body onresize="resizable_chart.draw(resizable_data, resizable_options);"> <div id='gct_resizable_chart' style="width=100%; height=200pt"></div> </body> </html>ここでポイントはデータ、グラフ、オプションの変数をグラフの作成関数の外で宣言しているところです。 これらの変数を使って onresize 時にグラフを描画しています。
オプションの変更(表のページ分割量の変更)
以前の記事で表のページ分割方法について説明しました。この際、 1 ページの項目数は固定でした。 項目数を変更できた方がユーザーは使いやすいでしょう。
グラフのオプションの変更のサンプルとして、このページ分割量を変更できるテーブルを作成します。
<script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load('visualization', '1', {packages: ['table']}); // 関数外で宣言 var visualization; var paging_data; var paging_options = {'showRowNumber': true}; function create_paging_table () { var dataAsJson = {cols:[ {id:'A',label:'名前',type:'string'}, {id:'B',label:'身長',type:'number'}, {id:'C',label:'出席',type:'boolean'}, {id:'D',label:'時刻',type:'timeofday'}], rows:[ {c:[{v:'Dave'},{v:159.0,f:'159'},{v:true,f:'TRUE'},{v:[12,25,0,0],f:'12:25:00'}]}, {c:[{v:'Peter'},{v:185.0,f:'185'},{v:false,f:'FALSE'},{v:[13,15,0,0],f:'13:15:00'}]}, {c:[{v:'John'},{v:145.0,f:'145'},{v:true,f:'TRUE'},{v:[15,45,0,0],f:'15:45:00'}]}, {c:[{v:'Moshes'},{v:198.0,f:'198'},{v:true,f:'TRUE'},{v:[16,32,0,0],f:'16:32:00'}]}, {c:[{v:'Karen'},{v:169.0,f:'169'},{v:true,f:'TRUE'},{v:[19,50,0,0],f:'19:50:00'}]}, {c:[{v:'Phil'},{v:169.0,f:'169'},{v:false,f:'FALSE'},{v:[18,10,0,0],f:'18:10:00'}]}, {c:[{v:'Gori'},{v:159.0,f:'159'},{v:true,f:'TRUE'},{v:[13,15,0,0],f:'13:15:00'}]}, {c:[{v:'Bill'},{v:155.0,f:'155'},{v:false,f:'FALSE'},{v:[7,40,48,0],f:'7:40:48'}]}, {c:[{v:'Valery'},{v:199.0,f:'199'},{v:true,f:'TRUE'},{v:[6,0,0,0],f:'6:00:00'}]}, {c:[{v:'Joey'},{v:187.0,f:'187'},{v:true,f:'TRUE'},{v:[5,2,24,0],f:'5:02:24'}]}, {c:[{v:'Karen'},{v:190.0,f:'190'},{v:true,f:'TRUE'},{v:[6,14,24,0],f:'6:14:24'}]}, {c:[{v:'Jin'},{v:169.0,f:'169'},{v:false,f:'FALSE'},{v:[5,45,36,0],f:'5:45:36'}]}, {c:[{v:'Gili'},{v:178.0,f:'178'},{v:true,f:'TRUE'},{v:[6,43,12,0],f:'6:43:12'}]}, {c:[{v:'Harry'},{v:172.0,f:'172'},{v:false,f:'FALSE'},{v:[6,14,24,0],f:'6:14:24'}]}, {c:[{v:'Handerson'},{v:175.0,f:'175'},{v:true,f:'TRUE'},{v:[6,57,36,0],f:'6:57:36'}]}, {c:[{v:'Vornoy'},{v:170.0,f:'170'},{v:true,f:'TRUE'},{v:[13,12,0,0],f:'13:12:00'}]}]}; paging_data = new google.visualization.DataTable(dataAsJson); paging_options['page'] = 'enable'; paging_options['pageSize'] = 5; paging_table = new google.visualization.Table(document.getElementById('gct_paging_table')); draw_paging_table(); } // テーブルの描画 function draw_paging_table() { paging_table.draw(paging_data, paging_options); } google.setOnLoadCallback(create_paging_table); // ページ分割時の項目数を設定 function setNumberOfPages(value) { if (value) { paging_options['pageSize'] = parseInt(value, 10); paging_options['page'] = 'enable'; } else { paging_options['pageSize'] = null; paging_options['page'] = null; } draw_paging_table(); } </script> <form action="" style="margin-top: 10px; margin-bottom: 5px; padding: 5px; border: 1px solid gray; background-color: buttonface;"> <span style="font-size:10pt;">表示する行数:</span> <select style="font-size:10pt;" onchange="setNumberOfPages(this.value)"> <option value="">すべて表示</option> <option value="3">3</option> <option selected="selected" value="5">5</option> <option value="7">7</option> <option value="10">10</option> </select> </form> <div id="gct_paging_table" style="width:400px; height:220px;"></div>リサイズ時の方法と同様に必要な変数をグラフ作成関数外で宣言し、 メニューの変更イベントで、オプションを変更して再描画しています。
データの変更(インタラクティブな計器図)
データテーブルは作成後も setValue() などのメソッドで値を変更することができます。DataTable::setValue(行番号, 列番号, 新しい値)データを変更して再描画を行うことによって、 動的にグラフを変更することが可能です。
// 行番号には列情報の行は含みません
サンプルとして動的に値を変更できる計器図の例を挙げます。
<script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load('visualization', '1', {packages: ['gauge']}); var dynamicGauge; var dynamicGaugeData; var dynamicGaugeOptions; // グラフの作成関数 function drawDynamicGauge() { dynamicGaugeData = google.visualization.arrayToDataTable([ ['Speed'], [70] ]); dynamicGauge = new google.visualization.Gauge(document.getElementById('gct_dynamic_gauge')); dynamicGaugeOptions = { max: 160, greenFrom: 40, greenTo: 60, yellowFrom: 60, yellowTo: 100, redFrom: 100, redTo: 160, minorTicks: 8 }; dynamicGauge.draw(dynamicGaugeData, dynamicGaugeOptions); } // データを変更する関数 function changeSpeed(dir) { var diff = dir * 25; var newvalue = dynamicGaugeData.getValue(0, 0) + diff; if (newvalue < 0) newvalue = 0; // データの値を変更 dynamicGaugeData.setValue(0, 0, newvalue); dynamicGauge.draw(dynamicGaugeData, dynamicGaugeOptions); } google.setOnLoadCallback(drawDynamicGauge); </script> <div id="gct_dynamic_gauge" style="width: 160px; height: 160px;"></div> <input type="button" value="Down" onclick="changeSpeed(-1)" /> <input type="button" value="Up" onclick="changeSpeed(1)" />