LoginSignup
8
10

More than 5 years have passed since last update.

Excelに頼らず表形式データをChartistJSで棒グラフ化

Last updated at Posted at 2015-06-21

始まり

ある日の出来事。
「こんな感じの棒グラフを1年分くらい作ってくれない?」
「1年分?! ・・・な、なるほど… 」(さらっときたな。手打ちだと死ぬ、VBAは覚えたくない、どうしよ・・・)

■こんな感じでーと言われた実際の例(数値は適当に変えてあります)
元ネタ.png

ChartistJS

chartisttop.png

後々の利便性を考えるとブラウザに表示しちゃうのが一番だと思ったのでその方向で。
「JavaScript Chart」でググると以下の記事が出てきたので、日本で流行って無さそうなChartistJSを利用することに決めました。
ロゴのヒゲおじさんが格好いい。

PentahoといったBIの利用も一瞬頭をよぎりましたが、それはそれで牛刀だったので今回は不採用。

The 15 Best JavaScript Charting Libraries

データ

元データは既に存在(Excelに入っていた)のをCSV(カンマ区切り、囲み文字無し)に抽出。

入力データは以下の様な横持ちの時系列データ。
1日分のデータが3行ずつ固定で存在する形式です。

全部で大体1000行くらい、100KBくらいのデータ量です。

input1.csv
ymd,name,00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23
20140410,A,1,0,34,3,0,0,0,0,45,577,13442,683,796,1916,1971,4743,6711,6771,4659,890,424,80,36,9
20140410,B,209,0,19,0,0,8,42,503,3886,6602,5134,3084,1622,700,1359,1375,608,216,411,548,224,16,120,0
20140410,C,1070,635,301,1309,570,591,4619,11993,4767,2904,2180,1676,1338,1453,1634,1193,189,140,217,71,177,67,344,1194
20140411,A,12,0,0,2,1,50,0,0,99,584,14724,1976,945,2133,3148,4631,7282,6952,5429,704,333,130,16,13
20140411,B,25,1,0,0,0,11,17,294,3276,6643,5469,3345,1487,815,1355,1142,681,237,361,441,176,15,3,1
20140411,C,817,558,474,481,1123,849,4910,11737,5615,2549,1741,1820,1198,1621,1824,692,202,86,207,94,60,36,5,560
20140412,A,1,48,1,2,2,0,0,0,11,62,15274,627,689,624,897,1834,3134,1696,111,18,108,5,2,10
20140412,B,29,2,2,0,0,148,15,390,1933,3481,2509,1707,1231,564,467,744,436,252,356,349,70,7,2,1
20140412,C,883,319,271,437,605,296,1400,8041,3573,2012,729,1029,760,961,1129,1088,593,700,1212,516,143,134,3,10
20140413,A,0,0,0,2,0,0,0,0,34,13,70,218,185,645,253,398,983,433,13,9,6,5,5,0
20140413,B,45,0,7,0,0,7,0,9,799,1359,1987,1283,698,350,215,274,243,111,278,268,102,8,1,0
20140413,C,45,0,7,1,0,35,712,4594,3554,2199,770,816,996,1898,1731,1330,545,869,892,290,323,264,6,0

流れ

  1. CSVをJSで読み込み
  2. ChartistJSの欲しい構造に加工
  3. ChartistJSで棒グラフをプロット

環境構築

初期環境構築は以下を参照下さい。
* 初めてChartist.jsを使うまでにやったこと - Qiita

開発作業

ディレクトリ階層

ファイルは以下のように配備しています。

フォルダ階層
~/html
  |--bower_components
  |--index.html
  |--input1.csv

コーディング

HTML+JavaScriptです。
CSVファイル読み込み+データ加工+プロットを一気に実行しています。

index.html
<!DOCTYPE html>
<html>
  <head>
    <title>My first Chartist Tests</title>
    <link rel="stylesheet"
          href="bower_components/chartist/dist/chartist.min.css">
  </head>
  <body>
    <div id="ct-charts">
    </div>

    <script src="bower_components/chartist/dist/chartist.min.js"></script>
    <script type="text/javascript">

        // CSV読み込み
        function csv2Array(filePath) {
            var data = new XMLHttpRequest();
            data.open("GET", filePath, false); //true:非同期,false:同期
            data.send(null);

            var LF = String.fromCharCode(10); //改行コード
            var lines = data.responseText.split(LF);

            // 読み込んだデータをカンマで分割
            var arr = new Array();
            for (var i = 0; i < lines.length; i++) {
                var cells = lines[i].split(",");
                arr.push(cells);
            }
            return arr;
        }

        var csvArr = csv2Array("input2.csv");

        var datas = new Array();
        var series = new Array();
        var chartNames = new Array();

        // 不要なデータ部を除去して、chartistが求めるlabelsととseriesを生成
        // 複数日分のグラフを作成したいので、data配列を準備
        for (var i = 1; i < csvArr.length; i++) {
            var arr = csvArr[i];
            series.push(arr.slice(2, -1));  
            if ((i +1) % 3 == 0) {
                var data = {};
                data.labels = csvArr[0].slice(2, -1);
                data.series = series;
                datas.push(data);
                series = new Array();
                chartNames.push(arr[0]);
            }
        }

        var options = {
            seriesBarDistance : 15, // 棒の間隔
            width : 600, // グラフサイズ横
            height : 400, // グラフサイズ縦
                        high : 25000 // Y軸の最大値
        };

        var responsiveOptions = [
          ['screen and (min-width: 641px) and (max-width: 1024px)', {
            seriesBarDistance: 10,
            axisX : {
                labelInterpolationFnc: function (value) {
                    return value;
                }
            }
          }],
          ['screen and (max-width: 640px)', {
            seriesBarDistance: 5,
            axisX: {
              labelInterpolationFnc: function (value) {
                return value[0];
                }
            }
            }]
        ];

        // 複数日分のグラフを出力するため出力用のdivタグを生成
        // Chartistではグラフに名称を付与することが出来ないようなので、divタグの中身に設定する
        for (var i = 0; i < datas.length; i++) {
            var div1 = document.createElement('div');
            div1.innerHTML = chartNames[i];
            div1.className = 'ct-chart' + (i + 1);
            var div = document.getElementById('ct-charts').appendChild(div1);

            var data = datas[i];
            new Chartist.Bar('.ct-chart' + (i + 1), datas[i], options, responsiveOptions);
        }
    </script>
  </body>
</html>

出力結果

以下にアクセスすると、上手くでてくれた!
1年分のデータ量でもほとんどフリーズせず動いてくれました。
本当は7列ずつ表示とか良かったのかもしれませんが、力尽きたので1列で。

http://FQDN/username/index.html

最終結果.png

スクロールも中々スムーズでした。
この調子だとページングしなくてもギリギリ大丈夫そうです。(ホッ

出来たこと

  • グラフサイズの変更
  • Y軸のグラフの最大値・最小値は設定

出来なかったこと

力及ばず色々出来ませんでした。

  • グラフの凡例
    • よく分からなかったため出力できず…(本家のAPIも見当たらず…)
  • グラフ全体に名称を入れること
    • これも正しい手順が良くわからず

参考情報

おしまい

  • 手でポチポチやるより遥かに楽できたので幸せです :sunny:
  • Chartist本来の強みであるレスポンシブな要素は全く使えなかったので、機会があれば利用したいですね :sparkles:
8
10
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
8
10