サーバーなしでD3.jsを使う
D3.jsはグラフの表示などができるJavaScriptのライブラリです。今回はこれを使って散布図を表示させてみます。
はじめに
データの可視化をする方法として一番有名なものはエクセルです。しかし、エクセルだと操作できるグラフを作ったり、かっこいいグラフを作るのは結構しんどいです。ほかに思いつく方法はPythonとかRとかMATLABですが、普通のパソコンには入っていないので、グラフ作成ツールを作っても共有できません。でもブラウザならどのパソコンにも入ってるし、便利かもと気づいたので、ブラウザで動くD3.jsを試してみました。
元ネタ
[1]» HTML5 の File API でドラッグ&ドロップする TECHSCORE BLOG
[2]JavaScript - CSVをパースする - Qiita
[3]D3.js チュートリアル:基本5 – Axisで軸を表示して散布図を作る。 - Data is fun.
HTMLの準備
そもそもJavaScriptを使ったことがないので、勉強もかねています。(WEB系の技術も勉強しないと。。)
<html> <head> <title>ドラッグ&ドロップで散布図</title> <script src="jquery-2.1.4.min.js"></script> <script src="d3/d3.min.js" charset="utf-8"></script> <script language="javascript">TODO</script> <body> <div id="droppable" style="border: gray solid 5px; padding: 2px; width:250px; height:50px;"> ここにファイルをドラッグ&ドロップ </div> </body> </html>
このHTMLのdroppableなdivにファイルをドラッグ&ドロップすると散布図を表示させるよう改造していきます。JavaScriptの制約でローカルにあるファイルにはアクセスできないですが、ドラッグ&ドロップならオッケーみたいです。WEBサーバーを立てればローカルファイルでもいいんですけど、ソフトを配った人にサーバー入れて!なんて言えないですよね。
ドラッグ&ドロップ
HTML5を使うとブラウザにファイルをドラッグ&ドロップして読み込むことができます[1]。ファイルが読み終わると、drawScatter()という自作の関数を呼びます。この関数に散布図表示コードを書いていきます。
var fileReader = new FileReader(); fileReader.onload = function(event) { drawScatter(event.target.result); } fileReader.readAsText(file);
散布図の表示
データセット
表示させるデータはPRMLという本のclassificationを使います。前にもC#で試したことがありました。
wildpie.hatenablog.com
データ形式は1.208985 0.421448 0.000000みたいに、x軸 y軸 labelとなっています。labelは0と1の二種類です。これはcsvのパース関数を使うとそれぞれの数値を配列に入れることができます[2]。
function drawScatter(data) { var csvArray = parseCSV(data); console.log(csvArray); }
console.log()の結果を一部表示すると下記のようになります。これが200個ある感じです。
D3.jsで表示
D3.js チュートリアル[3]に散布図の作り方が詳しく載っていたので参考にしています。詳しくはこのサイトをご覧ください。
はじめに表示する領域を作ります。
var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 500 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
スケールの設定をします。データの範囲は[-2.5,3]でプロット画面は[0,width]の範囲とします。
var xScale = d3.scale.linear() .domain([-2.5, 3]) .range([0, width]); var yScale = d3.scale.linear() .domain([-3, 3]) .range([height, 0]);
軸の設定をします。
svg.append('g') .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append('g') .attr("class", "y axis") .call(yAxis);
プロットするデータを定義します。csvArrayのデータを取り出して、'circle'を生成して、'cx'、'cy'で位置、'r'で大きさ、'fill'で色を指定します。
var colorCategoryScale = d3.scale.category10(); var points = svg.selectAll('circle') .data(csvArray) .enter() .append('circle') .attr('cx', function(d) { return xScale(d[0]) }) .attr('cy', function(d) { return yScale(d[1]) }) .attr('r', 7) .attr('fill', function(d) { return colorCategoryScale(d[2]); });
そんなこんなでこれを実行すると以下のようになります。
散布図を操作する
JavaScriptを使っているので、マウスで操作することができます。下の例ではマウスオーバー時は点を緑にして、大きさを2倍にしています。マウスオーバーをやめると元に戻ります。
points.on('mouseover', function() { d3.select(this) .attr('r', 14) .attr("fill", function(d) { return "green"; }); }) .on('mouseout', function() { d3.select(this) .attr('r', 7) .attr('fill', function(d) { return colorCategoryScale(d[2]); }) });