SELECTED ENTRIES
CATEGORIES
ARCHIVES
SPONSORED LINK
MOBILE
qrcode
LINKS
PROFILE
OTHERS

07
--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--
>>
<<
--

Agata's Blog

MATLABやPythonとともにD3.jsを使ってデータ解析とデータビジュアライゼーションに挑戦する某エンジニアのBlog
D3.js v4で利用可能なカラーマップ一覧
0

    D3.jsがVer.4にバージョンアップしてから、いろいろなカラーマップが利用可能になりました。せっかくなので、今回はv4で追加されたカラーマップを紹介します。

     

    v4から追加されたカラーマップのなかに、0〜1の数値を入力するとRGB形式のカラーベクトルが返ってくるという、便利な関数があります。これらの関数を使うには、D3.js本体 (d3.v4.min.js) のほかに、d3-scale-chromatic.v1.min.js も追加で読み込む必要があります。以下では、このライブラリに含まれているカラーマップ関数一覧をプルダウンメニューから選択すると、そのカラーマップを画面上に表示するプログラムを、D3.jsを使って作成してみました。

     

    javascript のソースコードを表示するには、以下の「JavaScript」タブを選択して下さい。

     

    ます、17行目以降で、関数名の一覧を配列に保存しています。この配列を使って、47~56行目の部分でプルダウンメニューのDOM要素を作成しています (D3.jsのサンプルプログラムではほとんど見かけませんが、じつはこんなふうに D3 でプルダウンメニューを作成することもできます)。このなかに、49行目で on メソッドを使って、プルダウンメニューが変更されたら、カラーバーの表示を更新するための関数が呼び出されるようにしています。 59~71行目は初期状態のカラーバーを作成しています。また、74行目以降で、プルダウンメニューが変更されたときに呼び出される関数を記述しています。

     

     

     

     

    JUGEMテーマ:JavaScript

    このエントリーをはてなブックマークに追加
    | D3.js | 22:19 | comments(0) | - | - |
    D3.js v4でTree図を作成する (3)
    0

      D3.jsを使う魅力は、なんといってもユーザの操作に従ってダイナミックに動くグラフを作成できるという点です。というわけで、前回までに作成した「静的なツリー図」を、インタラクティブに動く「動的なツリー図」にしてみましょう。

       

      以前作成したサンプルと同様に、対象となる html 内のプルダウン要素を指定して、その要素がユーザによって更新されたときにツリー図を更新するようにしました。具体的には、44行目でプルダウン要素を指定したうえで、その要素がユーザ操作によって更新されたときの動作を99行目以降で設定しています。更新処理のなかでは、(1) ノードの位置、(2) エッジの端点、(3) テキストの透明度 のそれぞれを更新しています。ここでは、前回説明したd3.hierarchy()メソッドで生成されたオブジェクトのうち、階層の深さを示す depth の値を参照することで、これら3つの更新処理を実現しています。

       

       

      JUGEMテーマ:JavaScript

      このエントリーをはてなブックマークに追加
      | D3.js | 22:29 | comments(0) | - | - |
      D3.js v4でTree図を作成する (2)
      1

      前回は、D3.js Ver.4を使って簡単なツリー図を作成してみました。そのなかでいろんな関数が出てきましたが、それらはいったい何をしているのでしょうか。ちょっと覗いてみることにしましょう。

       

      ツリー図を作成するうえで、ポイントとなるのは次の4行です。

       

      // Treeレイアウト
      var treemap = d3.tree()
      .size([width, height]);
      // 階層データの前処理
      var rootNode = d3.hierarchy(treeData);
      // ノード描画用のデータ
      var nodes = treemap(rootNode);
      // ノード間を結ぶパス描画用のデータ
      var links = nodes.links();
      

       

      最初の d3.tree().size([width, height]) は、描画領域の幅 (width) と高さ (height) にあわせてツリー図を作成するためのメソッドです。次の d3.hierarchy(treeData) は、JSONのような階層構造をもつデータをパースするための関数です。パースした後のオブジェクト rootNode を、先ほど準備した treemap() 関数に入れると、D3.js が自動的に各ノードの x,y 座標を計算して、階層の深さなどの情報とあわせたオブジェクトを返してくれます。ちょっと試しに console.log() を使って変数 nodes を見てみましょう。

       

       

      SVG描画領域の幅と高さにあわせて、各ノードの x,y 座標や階層の深さ (depth) の情報が入っているのがわかります。次にこのオブジェクトに .links() メソッドを適用すると、ノードとノードを結ぶエッジの情報を含む構造体が返ってきます。こちらも console.log を使って中身を覗いてみましょう。

       

       

      オブジェクトのなかに、エッジの両端 (sourceとtarget) それぞれの x,y 座標が入っているのがわかります。

       

      前回のプログラムでは、こうして得られた x,y 座標の情報をもとに、SVG上で円とパスを配置してツリー図を作成していたというわけです。

       

      ただ、これだけだとなんとも味気ないツリー図なので、次回はこのツリー図にいろいろと手を加えてみることにします。

       

       

      JUGEMテーマ:JavaScript

      このエントリーをはてなブックマークに追加
      | D3.js | 21:56 | comments(0) | - | - |
      D3.js v4でTree図を作成する (1)
      0

        D3.js が Ver.4 にアップデートしていろいろなところが変わりましたが、Treeレイアウトの作成方法もその1つです。この変更によって、残念ながら Ver.3 でのTreeレイアウトのプログラムは Ver.4 では動作しなくなってしまいました。

         

        さらに困ったことに、Ver.4 でTreeレイアウトを作成しようとしても、簡単なサンプルがなかなか見当たらないのが現状です (特に日本語では) 。例えばインターネットを検索すると「d3.js version4でシンプルなTree図を作成」という記事も見つかるのですが、ノードどうしを線でつなぐ部分の関数が複雑だったり、コードの説明がほとんどなかったりして、おそらくD3.jsを学びはじめた人にとってはハードルが高そうです。

         

        そこで、D3.js Ver.4 を使って、ごくごくシンプルなTree図を作成するサンプルプログラムを作ってみました。コードの中にも簡単な説明を入れましたが、それぞれの関数について次回紹介したいと思います。

         

         

        JUGEMテーマ:JavaScript

        このエントリーをはてなブックマークに追加
        | D3.js | 21:06 | comments(0) | - | - |
        過去30日間に世界で発生した地震を可視化する その2
        0
          以前このブログで、アメリカ地質調査所 (USGS: United States Geological Survey) の公開データをもとに、世界で過去30日間に発生したマグニチュード2.5以上の地震を可視化しました。今回はこのときのプログラムを改良して、特定地域で発生した地震のみをデータから抽出して表示できる、インタラクティブなウェブページを作ってみます。

          まず、基礎となるプログラムについては、以前の記事 (過去30日間に世界で発生した地震を可視化する) を参照して下さい。抽出したデータに従ってSVG要素を操作する方法については、「データの変化をSVG要素に反映する」を参考にして下さい。ツールチップの作成については、過去の記事 (ツールチップの作成方法) に詳しく紹介していますので、そちらもあわせて参照してもらえると、より理解が深まります。

          サンプルページ



          // 各ラジオボタン選択時に実行する関数
          function selectAll(){
              updateData("All");
          }
          
          function selectJapan(){
              updateData("Japan");
          }
          
          function selectAlaska(){
              updateData("Alaska");
          }
          
          function selectChile(){
              updateData("Chile");
          }
          
          function selectEcuador(){
              updateData("Ecuador");
          }
          
          // データ配列の初期化
          var dataSet = [];
          
          // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
          var margin = {top: 40, right: 20, bottom: 40, left: 20};
          var width = 1200 - margin.left - margin.right;
          var height = 500 - margin.top - margin.bottom;
          
          // ツールチップ用の設定
          var div = d3.select("body")
            .append("div")
            .attr("class", "tooltip")
            .style("opacity", 0);
          
          // SVGの表示領域を生成
          var svg = d3.select("#MyGraph")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
              .append("g")
              .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
          
          // 横軸のスケール関数を常に使えるようグローバル変数として定義
          var time_scale;
          
          // 初期状態を描画
          d3.csv("./js/30Days_MagnitudeOver2.5.csv", function(error, dataSet){
            // CSVファイル内の時刻情報をJavaScriptのDate形式にパース
            var format = d3.time.format("%Y-%m-%dT%X.%LZ");
            time_start = new Date(format.parse(dataSet[0].time));
            time_end = new Date(format.parse(dataSet[dataSet.length - 1].time));
            // 時間軸のスケール関数を生成
            time_scale = d3.time.scale()
              .domain([time_start, time_end])
              .range([0, width]);
            // 地震の規模を楕円のサイズで表すためのスケール関数
            var r_scale = d3.scale.linear()
              .domain([0.0,10.0])
              .range([0.0, 200.0]);
            // 散布図を描画
            svg.selectAll("ellipse")
              .data(dataSet, function(d){
                return d.time;
              })
              .enter()
              .append("ellipse")
              .attr("rx", 0)
              .attr("ry", 0)
              .attr("cx", function(d,i){
                var tmp = new Date(format.parse(d.time));
                return time_scale(tmp);
              })
              .attr("cy", 150)
              .attr("stroke","#A0A0A0")
              .attr("fill", function(d,i){
                if (d.place == "Japan"){return "orange"}
                else{return "#D0D0D0"};
              })
              .on("mouseover", function(d){ // マウスオーバー時にツールチップを表示
                div.transition()
                  .duration(500)
                  .style("opacity", 1.0);
                div.html("Location: " + d.place + "
          Magnitude: " + d.mag) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { // マウスアウトするとツールチップを非表示 div.transition() .duration(500) .style("opacity", 0.0); }) .transition() .delay(function(d,i){ return i*2; }) .attr("rx", 5) .attr("ry", function(d,i){ return r_scale(d.mag) }); // 時間軸を描画 svg.append("g") .attr("class", "axis") .attr("transform", "translate(0,320)") .call(d3.svg .axis() .scale(time_scale) .orient("bottom") .tickFormat(function(d,i){ var fmtFunc = d3.time.format("%b-%d"); return fmtFunc(d); }) ) .selectAll("text") .attr("transform", "rotate(45)") .attr("dy", 10) .attr("dx", 10) .style("text-anchor", "start"); }); // ラジオボタン選択時に実行する関数 function updateData(selecter){ d3.csv("./js/30Days_MagnitudeOver2.5.csv", function(error, dataSet){ // ラジオボタンで洗濯された地域のデータのみをCSVから抽出 if(selecter != "All"){ var dataSet = dataSet.filter(function(item, index){ if (item.place == selecter) return true; }); }; // CSVファイル内の時刻情報をJavaScriptのDate形式にパース var format = d3.time.format("%Y-%m-%dT%X.%LZ"); time_start = new Date(format.parse(dataSet[0].time)); time_end = new Date(format.parse(dataSet[dataSet.length - 1].time)); // 地震の規模を楕円のサイズで表すためのスケール関数 var r_scale = d3.scale.linear() .domain([0.0,10.0]) .range([0.0, 200.0]); // 散布図を描画 var ellipse = svg.selectAll("ellipse") .data(dataSet, function(d){ return d.time; }); ellipse.enter() .append("ellipse") .attr("rx", 0) .attr("ry", 0) .attr("cx", function(d,i){ var tmp = new Date(format.parse(d.time)); return time_scale(tmp); }) .attr("cy", 150) .attr("stroke","#A0A0A0") .attr("fill", function(d,i){ if (d.place == "Japan"){return "orange"} else{return "#D0D0D0"}; }) .on("mouseover", function(d){ // マウスオーバー時にツールチップを表示 div.transition() .duration(500) .style("opacity", 1.0); div.html("Location: " + d.place + "
          Magnitude: " + d.mag) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { // マウスアウトするとツールチップを非表示 div.transition() .duration(500) .style("opacity", 0.0); }) .transition() .delay(function(d,i){ return i*2; }) .attr("rx", 5) .attr("ry", function(d,i){ return r_scale(d.mag) }); // データと紐づけされていないSVG要素を削除 ellipse.exit() .transition() .duration(1000) .attr("rx", 0) .attr("ry", 0) .remove(); }); };

           
          このエントリーをはてなブックマークに追加
          | D3.js | 00:15 | comments(0) | - | - |
          【D3.js】Chordダイアグラムの作成
          0
            JUGEMテーマ:JavaScript

            D3.js には Chordダイアグラム (Chord diagram) を作成するための d3.layout.chord() というメソッドがあるのですが、そもそも Chordダイアグラム自体に馴染みがないというかたが多いのではないでしょうか。そこで、Chordダイアグラムについて簡単に説明したうえで、D3.jsによる作成方法を紹介します。

            Chordダイアグラムは、グループ間の関連性を図示するときによく使われます。例えば、ある集団を「男性/女性」という2つのグループに分けた場合と、「犬好き/猫好き」という2つのグループに分けた場合について考えてみましょう。現実の世のなかには「犬も猫も好き」な人もいれば、「どちらもキライ!」という人もいますが、ここでは簡単のために、みんな犬か猫のどちらか一方が好きだとします。さて、こうするとこの集団のメンバーは、4 種類 (「男性で犬好き」「男性で猫好き」「女性で犬好き」「女性で猫好き」) に分類できることになりますね。具体的に考えるために、この集団は男性12人と女性4人から成り、それぞれ以下のように犬好きと猫好きに分かれているとします。
             
            犬好き 猫好き 合計
            男性 7 5 12
            女性 1 3 4
            合計 8 8

            さて、このようなデータを可視化するときに、Chord ダイアグラムが役立ちます。Chord ダイアグラムを使うと、こういうグループ間の関連性を一目で把握できるようになります。上の表をもとに、実際に作成したChordダイアグラムが下図になります。



            ここでは図の右側、青色とオレンジ色の円弧が「男性/女性」のグループを表しています。また、左側の緑色と赤色の円弧が「犬好き/猫好き」のグループを表しています。そしてそれぞれのグループ間を橋渡ししている赤と緑の帯が、それぞれの関連性 (「男性で犬好き」など) を表現しています。このように、Chordダイアグラムを使うと、先の表にあるような2種類のグループ間の関連や連携が、見事に1枚の図に表現されていることが分かります。

            サンプルページ

            // D3.jsによる基本10色
            var color = d3.scale.category10();
            
            // Chord diagramの元となるデータ
            var matrix = [
                [0, 0, 7, 5],
                [0, 0, 1, 3],
                [7, 1, 0, 0],
                [5, 3, 0, 0]
            ];
            
            // D3.layout.chord()メソッドを使ってChordダイアグラムを作成
            var chord = d3.layout.chord()
                .padding(.05)
                .matrix(matrix);
            
            var width = 600,
                height = 500,
                innerRadius = Math.min(width, height) * 0.4,
                outerRadius = innerRadius * 1.1;
            
            var svg = d3.select("#MyGraph")
                .attr("width", width)
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
            
            // Chord diagramを描画
            svg.append("g").selectAll("path")
                .data(chord.groups)
                .enter()
                .append("path")
                .style("fill", function(d){ return color(d.index); })
                .style("stroke", function(d) { return color(d.index); })
                .style("opacity", 0.8)
                .attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
                .on("mouseover", fade(.1)) // マウスをのせた部分を強調表示
                .on("mouseout", fade(0.8)); // マウスを移動すると描画を元に戻す
            
            // 目盛りを描画
            var ticks = svg.append("g").selectAll("g")
                .data(chord.groups)
                .enter()
                .append("g")
                .selectAll("g")
                .data(groupTicks)
                .enter()
                .append("g")
                .attr("transform", function(d) {
                  return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
                      + "translate(" + outerRadius + ",0)";
                });
            
            ticks.append("line")
                .attr("x1", 1)
                .attr("y1", 0)
                .attr("x2", 5)
                .attr("y2", 0)
                .style("stroke", "#000");
            
            // 目盛りの数字を描画
            ticks.append("text")
                .attr("x", 8)
                .attr("dy", ".35em")
                .attr("transform", function(d) {
                    return d.angle > Math.PI ? "rotate(180)translate(-16)" : null;
                })
                .style("text-anchor", function(d) {
                    return d.angle > Math.PI ? "end" : null;
                })
                .text(function(d) { return d.label; });
            
            svg.append("g")
                .attr("class", "chord")
                .selectAll("path")
                .data(chord.chords)
                .enter()
                .append("path")
                .attr("d", d3.svg.chord().radius(innerRadius))
                .style("fill", function(d) { return color(d.target.index); })
                .style("opacity", 0.9);
            
            // 描画する目盛りの数字と角度を返す関数
            function groupTicks(d) {
              var k = (d.endAngle - d.startAngle) / d.value;
              return d3.range(0, d.value).map(function(v, i) {
                return {
                  angle: v * k + d.startAngle,
                  label: i % 5 ? null : v
                };
              });
            }
            
            // mouseover/mouseout 時のSVG要素の透明度を決定する関数
            function fade(opacity) {
              return function(g, i) {
                svg.selectAll(".chord path")
                    .filter(function(d) {
                        return d.source.index != i && d.target.index != i;
                    })
                    .transition()
                    .style("opacity", opacity);
              };
            }
            



             
            このエントリーをはてなブックマークに追加
            | D3.js | 23:07 | comments(0) | - | - |
            過去30日間に世界で発生した地震を可視化する
            0
              JUGEMテーマ:JavaScript

              アメリカ地質調査所 (USGS: United States Geological Survey) の公開データをもとに、世界で過去30日間に発生したマグニチュード2.5以上の地震を可視化しました。楕円のサイズが地震の規模を示しています。日本で発生した地震はオレンジで表しています。



              サンプルページ

              var dataSet = [];
              
              // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
              var margin = {top: 40, right: 20, bottom: 40, left: 20};
              var width = 1200 - margin.left - margin.right;
              var height = 500 - margin.top - margin.bottom;
              
              // ツールチップ用の設定
              var div = d3.select("body")
                .append("div")
                .attr("class", "tooltip")
                .style("opacity", 0);
              
              d3.csv("./js/30Days_MagnitudeOver2.5.csv", function(error, dataSet){
                // SVGの表示領域を生成
                var svg = d3.select("#MyGraph")
                  .attr("width", width + margin.left + margin.right)
                  .attr("height", height + margin.top + margin.bottom)
                  .append("g")
                  .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
                
                // CSVファイル内の時刻情報をJavaScriptのDate形式にパース
                var format = d3.time.format("%Y-%m-%dT%X.%LZ");
                time_start = new Date(format.parse(dataSet[0].time));
                time_end = new Date(format.parse(dataSet[dataSet.length - 1].time));
                
                // 時間軸のスケール関数を生成
                var time_scale = d3.time.scale()
                  .domain([time_start, time_end])
                  .range([0, width]);
              
                // 地震の規模を楕円のサイズで表すためのスケール関数
                var r_scale = d3.scale.linear()
                  .domain([0.0,10.0])
                  .range([0.0, 200.0]);    
                      
                // 散布図を描画
                svg.selectAll("ellipse")
                  .data(dataSet)
                  .enter()
                  .append("ellipse")
                  .attr("rx", 0)
                  .attr("ry", 0)
                  .attr("cx", function(d,i){
                    var tmp = new Date(format.parse(d.time));
                    return time_scale(tmp);
                  })
                  .attr("cy", 150)
                  .attr("stroke","#A0A0A0")
                  .attr("fill", function(d,i){
                    if (d.place == "Japan"){return "orange"}
                    else{return "#D0D0D0"};
                  })
                  .on("mouseover", function(d){ // マウスオーバー時にツールチップを表示
                    div.transition()
                      .duration(500)
                      .style("opacity", 1.0);
                    div.html("Location: " + d.place + "
              Magnitude: " + d.mag) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { // マウスアウトするとツールチップを非表示 div.transition() .duration(500) .style("opacity", 0.0); }) .transition() .delay(function(d,i){ return i*2; }) .attr("rx", 5) .attr("ry", function(d,i){ return r_scale(d.mag) }); // 時間軸を描画 svg.append("g") .attr("class", "axis") .attr("transform", "translate(0,320)") .call(d3.svg .axis() .scale(time_scale) .orient("bottom") .tickFormat(function(d,i){ var fmtFunc = d3.time.format("%b-%d"); return fmtFunc(d); }) ) .selectAll("text") .attr("transform", "rotate(45)") .attr("dy", 10) .attr("dx", 10) .style("text-anchor", "start"); })
              このエントリーをはてなブックマークに追加
              | D3.js | 11:08 | comments(0) | - | - |
              折れ線グラフをアニメーションで表示する
              0
                JUGEMテーマ:JavaScript

                前回作成したグラフですが、せっかくなので表示に動きをつけてみます。散布図をアニメーションで表示する方法については以前このブログで取り上げました。今回は、折れ線グラフをアニメーションで表示する方法を紹介します。

                D3.js を使った折れ線グラフの作成では、まず d3.svg.line() メソッドを使って path を生成します (詳しくは以前の記事を参照)。この path をアニメーションで表示させるには、stroke-dasharray と stroke-dashoffset という、2種類のプロパティを操作します。前者の stroke-dasharray プロパティを使うと、パスを破線で描画するときの線と間隙の長さを指定することができます。また後者の stroke-dashoffset プロパティは、破線が表示される開始位置を指定することができます。このあたり、言葉で説明してもなかなか分かりにくいので、下記の図を参考にして下さい。



                サンプルページとプログラムは下記の通りです。まず、40行目では getTotalLength() メソッドを使って、27〜37行目で作成した path の長さを取得しています。そのうえで、43〜48行目の部分で、上記2種類のプロパティを操作して、4秒かけてこのパスを表示しています。

                サンプルページ

                var dataSet = [];
                
                // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                var margin = {top: 40, right: 40, bottom: 40, left: 100};
                var width = 800 - margin.left - margin.right;
                var height = 500 - margin.top - margin.bottom;
                
                d3.csv("./js/WorldPopulation.csv", function(error, dataSet){
                
                  // SVGの表示領域を生成
                  var svg = d3.select("#MyGraph")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
                    
                  // スケール関数を作成。
                  var xScale = d3.scale.linear()
                    .domain([1000,2200])
                    .range([0,width]);
                
                  var yScale = d3.scale.log()
                    .domain([0.1,10])
                    .range([height,0]);
                
                  // 折れ線グラフを生成
                  var line = d3.svg.line()
                    .x(function(d,i){
                      return xScale(d.Year);
                    })
                    .y(function(d,i){
                      return yScale(d.Population);      
                    });
                
                  var path = svg.append("path")
                    .attr("class", "line")
                    .attr("d", line(dataSet));
                  
                  // パスの長さを取得
                  var pathLength = path.node().getTotalLength();
                  
                  // "stroke-dasharray" と "stroke-dashoffset" を使ってパスをアニメーションで描画
                  path.attr("stroke-dasharray", pathLength + " " + pathLength)
                    .attr("stroke-dashoffset", pathLength)
                    .transition()
                    .duration(4000)
                    .ease("linear")
                    .attr("stroke-dashoffset", 0);
                      
                  // 散布図を描画
                  svg.selectAll("circle")
                    .data(dataSet)
                    .enter()
                    .append("circle")
                    .attr("r", 0)
                    .attr("cx", function(d){
                      return xScale(d.Year);
                    })
                    .attr("cy", function(d){
                      return yScale(d.Population);
                    })
                    .attr("fill","orange")
                    .transition()
                    .delay(function(d,i){
                      return 2000+(i*100);
                    })
                    .attr("r", 5);
                
                  // Y軸を描画
                  svg.append("g")
                    .attr("class", "axis")
                    .call(d3.svg
                      .axis()
                      .scale(yScale)
                      .orient("left")
                      .tickValues([0.1,0.2,0.4,0.6,0.8,1,2,4,6,8,10])
                      .tickPadding(10) // 軸と数値の間のスペースを指定
                      .tickFormat(d3.format(".1f"))
                  );
                  
                  // Y軸のグリッドを描画
                  svg.append("g")
                    .attr("class", "axis")
                    .call(d3.svg
                      .axis()
                      .scale(yScale)
                      .orient("left")
                      .innerTickSize(-width)
                      .tickFormat("")
                  );
                
                  // X軸を描画
                  svg.append("g")
                    .attr("class", "axis")
                    .attr("transform", "translate(0," + height + ")")
                    .call(d3.svg
                      .axis()
                      .scale(xScale)
                      .orient("bottom")
                      .innerTickSize(-height) // X軸のグリッドを描画
                      .tickPadding(10) // 軸と数値の間のスペースを指定
                      .tickFormat(function(d){return d;})
                  );
                  
                  // 凡例
                  svg.append("g")
                    .attr("class", "axis")
                    .append("text")
                    .attr("x", -40)
                    .attr("y", -20)
                    .text("[単位: 10億人]");
                
                  svg.append("g")
                    .attr("class", "axis")
                    .append("text")
                    .attr("x", width/2)
                    .attr("y", margin.top + height)
                    .text("Year");
                
                })
                
                

                 
                このエントリーをはてなブックマークに追加
                | D3.js | 22:00 | comments(0) | - | - |
                グラフにグリッド線を追加する
                0
                  D3.js でグリッド線を追加する方法はいくつかありますが、今回はいちばん簡単な方法を紹介します。

                  それでは前回作成したグラフにグリッド線を追加してみましょう。まず、html ファイルの <style>〜</style> タグ内 (CSS) に以下を追加します。

                    .tick line{
                      opacity: 0.2;
                    }

                  次に、軸の目盛り線の長さを指定する innerTickSize() メソッドでマイナスの値を指定して、目盛り線をグラフの内側に伸ばしてしまいます。内側に伸ばす線の長さをグラフのサイズにすることで、グラフのグリッド線にしてしまうというわけです。

                  軸の描画とグリッド線の描画を分けることで、軸の目盛り用に表示する数値の数とグリッド線の数とを個別に指定することもできます。今回の例では、Y軸に対して軸の描画 (54行目〜63行目) とグリッド線の描画 (66行目〜74行目) を個別に指定しています。

                  軸の目盛り用に表示する数値の数とグリッド線の数とが一致する場合には、軸の描画とグリッド線の描画を同時にすることができます。今回の例では、X軸に対してこれらを同時に実行しています (78行目〜88行目)。

                  サンプルページ



                  var dataSet = [];
                  
                  // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                  var margin = {top: 40, right: 40, bottom: 40, left: 100};
                  var width = 800 - margin.left - margin.right;
                  var height = 500 - margin.top - margin.bottom;
                  
                  d3.csv("./js/WorldPopulation.csv", function(error, dataSet){
                  
                    // SVGの表示領域を生成
                    var svg = d3.select("#MyGraph")
                      .attr("width", width + margin.left + margin.right)
                      .attr("height", height + margin.top + margin.bottom)
                      .append("g")
                      .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
                      
                    // スケール関数を作成。
                    var xScale = d3.scale.linear()
                      .domain([1000,2200])
                      .range([0,width]);
                  
                    var yScale = d3.scale.log()
                      .domain([0.1,10])
                      .range([height,0]);
                  
                    var line = d3.svg.line()
                      .x(function(d,i){
                        return xScale(d.Year);
                      })
                      .y(function(d,i){
                        return yScale(d.Population);      
                      });
                  
                    // 折れ線グラフを生成
                    svg.append("path")
                      .attr("class", "line")
                      .attr("d", line(dataSet));
                      
                    // 散布図を描画
                    svg.selectAll("circle")
                      .data(dataSet)
                      .enter()
                      .append("circle")
                      .attr("r", 5)
                      .attr("cx", function(d){
                        return xScale(d.Year);
                      })
                      .attr("cy", function(d){
                        return yScale(d.Population);
                      })
                      .attr("fill","orange");
                  
                    // Y軸を描画
                    svg.append("g")
                      .attr("class", "axis")
                      .call(d3.svg
                        .axis()
                        .scale(yScale)
                        .orient("left")
                        .tickValues([0.1,0.2,0.4,0.6,0.8,1,2,4,6,8,10])
                        .tickPadding(10) // 軸と数値の間のスペースを指定
                        .tickFormat(d3.format(".1f"))
                    );
                    
                    // Y軸のグリッドを描画
                    svg.append("g")
                      .attr("class", "axis")
                      .call(d3.svg
                        .axis()
                        .scale(yScale)
                        .orient("left")
                        .innerTickSize(-width)
                        .tickFormat("")
                    );
                  
                    
                    // X軸を描画
                    svg.append("g")
                      .attr("class", "axis")
                      .attr("transform", "translate(0," + height + ")")
                      .call(d3.svg
                        .axis()
                        .scale(xScale)
                        .orient("bottom")
                        .innerTickSize(-height) // X軸のグリッドを描画
                        .tickPadding(10) // 軸と数値の間のスペースを指定
                        .tickFormat(function(d){return d;})
                    );
                    
                    // 凡例
                    svg.append("g")
                      .attr("class", "axis")
                      .append("text")
                      .attr("x", -40)
                      .attr("y", -20)
                      .text("[単位: 10億人]");
                  
                    svg.append("g")
                      .attr("class", "axis")
                      .append("text")
                      .attr("x", width/2)
                      .attr("y", margin.top + height)
                      .text("Year");
                  
                  })
                  
                  


                   
                  このエントリーをはてなブックマークに追加
                  | D3.js | 11:08 | comments(0) | - | - |
                  世界の総人口の推移を片対数グラフで描画する
                  0
                    JUGEMテーマ:JavaScript

                    急速に増加するようなデータを可視化するには、対数グラフが便利です。今回は D3.js で片対数グラフを作成する方法を紹介します。

                    一例として、国連 (United Nations) による世界の総人口の推計値データをグラフ化してみました。まず、データをCSV形式で保存します。

                    Year,Population
                    1000,0.31
                    1250,0.4
                    1500,0.5
                    1750,0.79
                    1800,0.98
                    ・・・

                    このCSVファイルを読み込んで、片対数グラフで表示するプログラムを作成します。CSVファイルを読み込んでグラフ化する基本的な方法については、過去の記事 (D3.js を使ったCSVファイルの読み込み) を参照して下さい。

                    片対数グラフを作成するには、これまで使ってきた線形 (linear) のスケール関数 d3.scale.linear() の代わりに、対数 (log) のスケール関数 d3.scale.log() を使います。それでは具体的な作成例とプログラムを見てみましょう。

                    サンプルページ



                    対数のスケール関数は、22行目から24行目で作成しています。これだけでも片対数グラフを作成できるのですが、より見やすくするために、いくつか手を入れることにしました。まず、Y軸の目盛りの数字をすべて表示すると数字が重なって見にくくなるため、60行目で ticsValues() メソッドを使って表示する目盛りの数値を指定しています。また、61行目で ticsFormat() メソッドを使って、目盛りの数値を小数点以下1桁で表示するように指定しました。

                    var dataSet = [];
                    
                    // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                    var margin = {top: 40, right: 40, bottom: 40, left: 100};
                    var width = 800 - margin.left - margin.right;
                    var height = 500 - margin.top - margin.bottom;
                    
                    d3.csv("./js/WorldPopulation.csv", function(error, dataSet){
                    
                      // SVGの表示領域を生成
                      var svg = d3.select("#MyGraph")
                        .attr("width", width + margin.left + margin.right)
                        .attr("height", height + margin.top + margin.bottom)
                        .append("g")
                        .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
                        
                      // スケール関数を作成。
                      var xScale = d3.scale.linear()
                        .domain([1000,2200])
                        .range([0,width]);
                    
                      var yScale = d3.scale.log()
                        .domain([0.1,10])
                        .range([height,0]);
                    
                      var line = d3.svg.line()
                        .x(function(d,i){
                          return xScale(d.Year);
                        })
                        .y(function(d,i){
                          return yScale(d.Population);      
                        });
                    
                      // 折れ線グラフを生成
                      svg.append("path")
                        .attr("class", "line")
                        .attr("d", line(dataSet));
                        
                      // 散布図を描画
                      svg.selectAll("circle")
                        .data(dataSet)
                        .enter()
                        .append("circle")
                        .attr("r", 5)
                        .attr("cx", function(d){
                          return xScale(d.Year);
                        })
                        .attr("cy", function(d){
                          return yScale(d.Population);
                        })
                        .attr("fill","orange");
                    
                      // Y軸を描画
                      svg.append("g")
                        .attr("class", "axis")
                        .call(d3.svg
                          .axis()
                          .scale(yScale)
                          .orient("left")
                          .tickValues([0.1,0.2,0.4,0.6,0.8,1,2,4,8,10])
                          .tickFormat(d3.format(".1f"))
                      );
                      
                      // X軸を描画
                      svg.append("g")
                        .attr("class", "axis")
                        .attr("transform", "translate(0," + height + ")")
                        .call(d3.svg
                          .axis()
                          .scale(xScale)
                          .orient("bottom")
                          .tickFormat(function(d){return d;})
                      );
                      
                      // 凡例
                      svg.append("g")
                        .attr("class", "axis")
                        .append("text")
                        .attr("x", 20)
                        .attr("y", 20)
                        .text("[単位: 10億人]");
                    
                      svg.append("g")
                        .attr("class", "axis")
                        .append("text")
                        .attr("x", width/2)
                        .attr("y", margin.top + height)
                        .text("Year");
                    
                    })
                    
                    


                     
                    このエントリーをはてなブックマークに追加
                    | D3.js | 09:51 | comments(0) | - | - |