SELECTED ENTRIES
CATEGORIES
ARCHIVES
SPONSORED LINK
MOBILE
qrcode
LINKS
PROFILE
OTHERS

05
--
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

Python+pandasとD3.jsを使ってデータ解析とデータビジュアライゼーションに挑戦する某エンジニアのBlog
D3.js でギブス現象を見る
0
    JUGEMテーマ:JavaScript

    今回は、プルダウンメニューで選択した数値によって変化するグラフを作成します。とはいっても、ただの練習のためだけのプログラムを書いても面白くないので、フーリエ変換 (Fourier transform) のギブス現象 (Gibbs phenomenon) が発生する様子を D3.js を使って可視化してみます。

    ギブス現象というのは、周期関数のフーリエ級数において、元の周期関数の不連続点付近でフーリエ級数の m 次部分和が大きく振動する現象のことを指します。

    言葉で書いてもなかなか分かりにくい現象なので、実際の例で見てみましょう。簡単のために元信号 f(x) を次のような x = π で不連続点を持つ矩形信号とします。


    この関数をフーリエ級数展開すると、次式のようになります。

    ではいよいよ、D3.js を使ってこのフーリエ級数展開の m 次部分和を描画してみます。加えて今回は、m の数値をプルダウンメニューから選択できるようにしてみます。こうすることで、m の値を増やすと次第に不連続点 (x = π) 周辺で振動が発生するギブス現象を可視化することができます。

    サンプルページ



    まず準備として、html ファイルに以下を追加します。ここでは D3.js で描画するグラフの線として、幅2ピクセルのオレンジ色の線を指定しています。また、プルダウンメニューとして m = 1 〜 100 まで選択可能としました。
     

    <style>
      .line{
        fill: none;
        stroke: orange;
        stroke-width: 2px;
      }
    </style>

    (中略)

    <p>
    m = <select id="listbox">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
      <option value="4">4</option>
      <option value="5">5</option>
      <option value="10">10</option>
      <option value="20">20</option>
      <option value="50">50</option>
      <option value="100">100</option>
    </select>
    </p>
    <svg id="MyGraph"></svg>


    ここで、対象となるプルダウンメニューを特定できるよう、id = "listbox" として ID を設定しています。

    次に、プルダウンメニューで選択された m の値を取得して、フーリエ級数展開の m 次部分和を描画する D3.js プログラムを以下に示します。44 行目でまず html 内のプルダウン要素を選択しています。そのうえで、47 行目でこのプルダウンメニュー選択の更新を検知して、グラフを更新しています。具体的には、プルダウンにより選択された m の値を 49, 59 行目で取得しています。そのうえで 56 行目以降で定義する update() 関数でフーリエ級数展開の m 次部分和を計算し、70 行目以降で定義する updateLine() 関数でグラフを更新しています。

    // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
    var margin = {top: 40, right: 40, bottom: 80, left: 80};
    var width = 800 - margin.left - margin.right;
    var height = 500 - margin.top - margin.bottom;
    
    // 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 dx = 2.0*Math.PI/800.0;
    var x = d3.range(0,2.0*Math.PI,dx);
    var y = d3.range(0,x.length);
    
    // 時間軸のスケール関数を生成
    var x_scale = d3.scale.linear()
      .domain([0, 2.0*Math.PI])
      .range([0, width]);
        
    // 縦軸のスケール関数を生成
    var y_scale = d3.scale.linear()
      .domain([-2,2])
      .range([height, 0]);  
      
    // データごとに折れ線グラフを描画するための関数
    var line = d3.svg.line()
      .x(function(d, i){ return x_scale(x[i]);})
      .y(function(d, i) { return y_scale(y[i]);})
      .interpolate("linear");
    
    var polyline = svg.append('path')
      .attr("class", "line")
      .attr('stroke', 'black')
      .attr('stroke-width', '1')
      .attr('fill', 'transparent');
    
    // 初期値として m = 1 のグラフを描画
    update(1);
    updateLine();
    
    // 対象となる html 内のプルダウン要素を選択 
    var select = document.getElementById( 'listbox' );
    
    // プルダウンメニューが更新されるとグラフを更新する
    select.onchange = function(){
      // プルダウンで選択されているoption要素を取得する
      var selectedItem = this.options[ this.selectedIndex ];
      var value = selectedItem.value;
      update(value);
      updateLine();
    }
    
    // フーリエ級数展開の m 次部分和を計算する
    function update(k){
      for (var i = 0; i < k; i++){
        for (var j = 0; j < x.length; j++){
          if (i == 0){
            y[j] = (4/Math.PI)*(1/(2*(i+1)-1))*Math.sin((2*(i+1)-1)*x[j]);
          }
          else{
            y[j] = y[j] + (4/Math.PI)*(1/(2*(i+1)-1))*Math.sin((2*(i+1)-1)*x[j]);
          }
        }
      }
    }
    
    // グラフを更新する
    function updateLine(){
      polyline
        .transition()
        .duration(300)
        .attr('d', line(y));
    }
    
    // X軸を描画
    svg.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + height/2 + ")")
      .call(d3.svg
        .axis()
        .scale(x_scale)
        .orient("bottom")
      );
      
    // Y軸を描画
    svg.append("g")
      .attr("class", "axis")
      .call(d3.svg
        .axis()
        .scale(y_scale)
        .orient("left")
      );
      
    

     
    このエントリーをはてなブックマークに追加
    | D3.js | 07:51 | comments(0) | - | - |
    【D3.js】 フォースレイアウトの作成例
    0
      JUGEMテーマ:JavaScript

      D3.js では力学モデルに基づく描画をおこなうフォースレイアウト (force layout) が準備されています。フォースレイアウトを使うと、ノードとリンクによって表現されたグラフ (Graph) 形式のデータをアニメーションとして可視化することができます。

      フォースレイアウトでは、d3.layout.force() を使って、ノード間の距離やノード間に働く力、リンクの伸び縮みのしやすさなどを設定して、動きのあるデータ可視化を実現することができます。フォースレイアウトで設定できる主なパラメータは、以下のとおりです。
       
      パラメータ 意味
      .node ノードを指定
      .links ノード間を結ぶリンクを指定
      .size 表示領域のサイズを指定
      .linkDistance リンクの長さを指定
      .linkStrength リンクの伸び縮みのしやすさを指定
      .gravity 表示領域の中心に引き寄せる重力の強さを指定
      .charge ノード間の引力/斥力を指定

      サンプルページ


      なお、サンプルページのプログラムでは、リンクの線幅や色を指定するために css (あるいは html ファイルの <style type="text/css"> 〜 </style>) に次の記述を追加しています。
       
        .line{
          fill: none;
          stroke: orange;
          stroke-width: 2px;
        }

      サンプルプログラムは、以下のとおりです。
       
      var width = 800;
      var height = 500;

      var color = d3.scale.category20(); //D3.jsが用意する標準10色

      // フォースレイアウトの元となるデータを作成
      var dataSet = {
        nodes : [],
        links : []
      }

      var N1 = 8;

      for(var k=0; k<N1; k++){
        var st = "Node"+k;
        dataSet.nodes.push({name : st});
      }

      for(var k=1; k<N1; k++){
        dataSet.links.push({source : k-1, target : k});
      }

      // SVGの表示領域を生成
      var svg = d3.select("#MyGraph")
        .attr("width", width)
        .attr("height", height)

      // フォースレイアウトの設定
      var force = d3.layout.force()
        .nodes(dataSet.nodes)
        .links(dataSet.links)
        .size([width, height])
        .linkDistance(80)
        .linkStrength(1)
        .gravity(0.01)
        .charge(-20)
        .start()
        
      // ノード間のリンクを描画
      var link = svg.selectAll("line")
        .data(dataSet.links)
        .enter()
        .append("line")
        .attr("class", "line")

      // ノードを描画  
      var node = svg.selectAll("circle")
        .data(dataSet.nodes)
        .enter()
        .append("circle")
        .attr("r", 20)
        .call(force.drag)

      // ノードの名前をテキストで表示
      var nodeText = svg.selectAll("text")
        .data(dataSet.nodes)
        .enter()
        .append("text")

      // フォースレイアウトを描画  
      force.on("tick", function(){
        link
          .attr("x1", function(d){return d.source.x;})
          .attr("y1", function(d){return d.source.y;})
          .attr("x2", function(d){return d.target.x;})
          .attr("y2", function(d){return d.target.y;})
        node
          .attr("cx", function(d){return d.x;})
          .attr("cy", function(d){return d.y;})
          .style("fill", function(d,i){
            return color(i%20);
          })
          .style("fill-opacity", 0.5)
        nodeText
          .text(function(d){return d.name;})
          .attr("x", function(d){return d.x+25;})
          .attr("y", function(d){return d.y-5;})
      })
      このエントリーをはてなブックマークに追加
      | D3.js | 22:48 | comments(0) | - | - |
      D3.js で六角形を描く (hexbin) その4
      0
        JUGEMテーマ:JavaScript

        これまで 3 回にわたって、hexbin プラグインを使った六角形の描画方法について見てきました。今回は応用編として、hexbin() メソッドによるヒートマップがゆっくりと作成されるアニメーションを作ってみます。また、せっかくなのでヒートマップの色もランダムに変わるようにします。

        下のサンプルプログラムでは、まず基本となる色の選択肢を作成しています (5行目)。そのうえで、この選択肢のなかから 1 色をランダムに取り出して、白からその色へと変化するグラデーションを定義します (8〜12行目)。ちなみにここでは、Floor関数の Math.floor() と 0〜1 の範囲の乱数を生成する Math.random() を組み合わせて、Math.floor(Math.random() * m) とすることで、0 から m-1 までの整数をランダムに生成しています。

        そのうえで、ヒートマップを構成するひとつひとつの六角形を、初期位置 (39行目) からそれぞれのあるべき位置 (52行目) まで時間差をつけて移動させています。移動の動き方として .ease("bounce") で bounce を指定することで、上から落ちてきた六角形がコツンと何かに反射してバウンドしながら止まるような効果を与えています。

        サンプルページ



        // SVGのサイズを指定
        var width = 800;
        var height = 500;
        
        var baseColor = ["royalblue", "orange", "lawngreen", "fuchsia", "goldenrod", "yellow"];
        
        // 白から、選択された色へと変化するグラデーション
        var color = d3.scale
          .linear()
          .domain([0, 20])
          .range(["white", baseColor[Math.floor(Math.random()*6)]])
          .interpolate(d3.interpolateLab);
          
        // SVGの幅と高さを指定
        var svg = d3.select("#MyGraph")
          .attr("width", width)
          .attr("height", height)
          .append("g");
        
        // ランダムに400個のデータ点を配置
        var points = [];
        for (var i=0; i<=800; i++){
          points.push([d3.random.normal(width/2, 80)(), d3.random.normal(height/2, 80)()]);
        }
        
        // 半径20pxの六角形を定義    
        var hexbin = d3.hexbin()
          .radius(20);
        
        // 領域内にデータ点を含む箇所に六角形を描画
        svg.append("g")
          .attr("class", "hexagon")
          .selectAll("path")
          .data(hexbin(points))
          .enter()
          .append("path")
          .attr("d", hexbin.hexagon())
          .attr("transform", function(d,i) {
            return "translate(" + d.x + "," + -50 + ")"; // 初期位置
          })
          .style("fill", function(d){
            if (d.length > 20) return color(20);
            else return color(d.length); // 領域内のデータ点数 (d.length) によってグラデーション
          })
          .transition() // 六角形がぱらぱらと落ちてくるアニメーション
          .delay(function(d,i){
            return i*50;
          })
          .duration(1500)
          .ease("bounce")
          .attr("transform", function(d,i) {
            return "translate(" + d.x + "," + d.y + ")";
          });
        

        このエントリーをはてなブックマークに追加
        | D3.js | 22:04 | comments(0) | - | - |
        D3.js で六角形を描く (hexbin) その3
        0
          JUGEMテーマ:JavaScript

          前回に引き続き、hexbin プラグインを使ってもう少し遊んでみます。

          これまで 2 回にわたって、hexbin() メソッドを使った六角形の描画方法についてみてきました。でも、D3.js の醍醐味といえば、やっぱり動的なビジュアル表現ですよね。そこで今回は、マウスの位置によってリアルタイムに変化するヒートマップを作ってみます。

          下のサンプルプログラムでは、まず、ユーザ画面上でマウスが動くとマウスの位置座標を取得します (18〜19行目) 。マウスの位置座標の取得方法については、以前の記事を参照してください。次に、取得したマウス位置を中心とする正規分布に従って、平面上に800個のデータ点を生成ます (22〜27行目) 。そして最後に、データ点の密度をヒートマップとしてリアルタイムに表示しています。

          サンプルページ



          // SVGのサイズを指定
          var width = 800;
          var height = 500;
          
          // 白からロイヤルブルー(royalblue)へのグラデーション
          var color = d3.scale
            .linear()
            .domain([0, 20])
            .range(["white", "royalblue"])
            .interpolate(d3.interpolateLab);
            
          // SVGの幅と高さを指定
          var svg = d3.select("#MyGraph")
            .attr("width", width)
            .attr("height", height);
          
          // マウスの位置座標を取得
          svg.on("mousemove", function(){
            var position = d3.mouse(this);
            
            // ランダムに800個のデータ点を配置
            var points = [];
            for (var i=0; i<=800; i++){
              points.push(
                [d3.random.normal(position[0], 80)(), d3.random.normal(position[1], 80)()]
              );
            };
          
            // 半径20pxの六角形を定義    
            var hexbin = d3.hexbin()
              .radius(20);
               
            d3.selectAll(".hexagon").remove();
              
            // 領域内にデータ点を含む箇所に六角形を描画
            var heatmap = svg.append("g")
              .attr("class", "hexagon")
              .selectAll("path")
              .data(hexbin(points))
              .enter()
              .append("path")
              .attr("d", hexbin.hexagon())
              .attr("transform", function(d,i) {
                return "translate(" + d.x + "," + d.y + ")";
              })
              .style("fill", function(d){
                if (d.length > 20) return color(20);
                else return color(d.length); // 領域内のデータ点数 (d.length) によってグラデーション
              });
          });
          
           
          このエントリーをはてなブックマークに追加
          | D3.js | 23:57 | comments(0) | - | - |
          D3.js で六角形を描く (hexbin) その2
          0
            JUGEMテーマ:JavaScript

            前回につづいて、hexbin を使った基本的なヒートマップの作り方を紹介します。

            前回は hexbin() メソッドを使って、平面を六角形で分割したうえで、個々の六角形の領域内にデータ点がある場合に六角形を描画していました。今回は、個々の六角形の色を領域内のデータ点数によって変化させることで、ヒートマップを作製します。

            データ点数によって色を変化させるには、2 つの色の間を補完する interpolateLabメソッドを使います (⇒ 関連記事)。ちなみに今回は、白とロイヤルブルー (royalblue) の間で補完してみました。HTTP で使えるカラーコードについては、ここなどを参照してください。

            また、今回は個々の六角形を分かりやすく表示するため、css (あるいは html ファイルの <style>〜</style>) に以下の記述を加えて、六角形の枠線を灰色で描画することにしました。
             
              .hexagon {
                stroke: #c0c0c0;
                stroke-width: 1.5px;
              }

            前回は平面上にランダムにサンプル点を配置していましたが、今回はヒートマップ図の雰囲気を出すために、サンプル点の密度が平面の中心位置をピークとする正規分布となるようにサンプル点を配置することにしました。サンプル点の配置には、D3.js  の d3.random.normal() メソッドを使っています。このメソッドは、d3.random.normal(m, s)() とすると平均が m、分散が s の正規分布に従う乱数を生成します。

            サンプルページ


             
            // SVGのサイズを指定
            var width = 800;
            var height = 500;
            
            // 白からロイヤルブルー(royalblue)へのグラデーション
            var color = d3.scale
              .linear()
              .domain([0, 20])
              .range(["white", "royalblue"])
              .interpolate(d3.interpolateLab);
              
            // SVGの幅と高さを指定
            var svg = d3.select("#MyGraph")
              .attr("width", width)
              .attr("height", height)
              .append("g");
            
            // ランダムに400個のデータ点を配置
            var points = [];
            for (var i=0; i<=800; i++){
              points.push([d3.random.normal(width/2, 80)(), d3.random.normal(height/2, 80)()]);
            }
            
            // 半径20pxの六角形を定義    
            var hexbin = d3.hexbin()
              .radius(20);
            
            // 領域内にデータ点を含む箇所に六角形を描画
            svg.append("g")
              .attr("class", "hexagon")
              .selectAll("path")
              .data(hexbin(points))
              .enter()
              .append("path")
              .attr("d", hexbin.hexagon())
              .attr("transform", function(d,i) {
                return "translate(" + d.x + "," + d.y + ")";
              })
              .style("fill", function(d){
                if (d.length > 20) return color(20);
                else return color(d.length); // 領域内のデータ点数 (d.length) によってグラデーション
              });
            
             
            このエントリーをはてなブックマークに追加
            | D3.js | 09:51 | comments(0) | - | - |
            D3.js で六角形を描く (hexbin)
            0
              数値データをヒートマップで表現しようとしたときなどで、六角形を描画したくなることがあります。D3.js を使って六角形を描画する関数を一から自分で作ってみても良いのですが、幸いなことに D3.js には hexbin という六角形を描画するためのプラグインが用意されています。今回はこの hexbin の基本的な使い方を紹介します。

              まずは d3.hexbin.v0.min.js をダウンロードして、html ファイルに下記の 1 行を追加して d3.min.js と同じように読み込ませます。
               
              <script type="text/javascript" src="js/d3.hexbin.v0.min.js"></script>

              また、六角形の色や枠線を指定するために css (あるいは html ファイルの <style>〜</style>) に次の記述を追加しておきます。
               
                .hexagon {
                  fill: steelblue;
                  stroke: white;
                  stroke-width: 1.5px;
                }

              それでは下記のプログラムを使って、hexbin プラグインの動作を見てみましょう。

              サンプルページ



              インターネットで検索しても日本語の説明がなかなか見つからない hexbin プラグインですが、このプログラムを見てもらえれば基本的な使い方は理解できると思います。hexbin プラグインはまず、hexbin() メソッドを使って、指定された半径 (この例では 20 px) の六角形で平面を分割します (18〜19行目) 。次に、分割された個々の六角形について、その領域内にデータ点を含む場合は六角形を描画し、データ点を含まない場合は何も描画しないという処理を行います (22〜31行目) 。

              この例では、データ点としてランダムに配置した 400 個の点を使用しました (12〜15行目) 。ページをリロードするたびにデータ点の位置が変わるため、描画される六角形の位置も変化します。
               
              // SVGのサイズを指定
              var width = 800;
              var height = 500;
              
              // SVGの幅と高さを指定
              var svg = d3.select("#MyGraph")
                .attr("width", width)
                .attr("height", height)
                .append("g");
              
              // ランダムに400個のデータ点を配置
              var points = [];
              for (var i=0; i<=400; i++){
                points.push([width * Math.random(), height * Math.random()]);
              }
              
              // 半径20pxの六角形を定義    
              var hexbin = d3.hexbin()
                .radius(20);
              
              // 領域内にデータ点を含む箇所に六角形を描画
              svg.append("g")
                .attr("class", "hexagon")
                .selectAll("path")
                .data(hexbin(points))
                .enter()
                .append("path")
                .attr("d", hexbin.hexagon())
                .attr("transform", function(d,i) {
                  return "translate(" + d.x + "," + d.y + ")";
                });
              
               
              このエントリーをはてなブックマークに追加
              | D3.js | 23:29 | comments(0) | - | - |
              【D3.js】2つの色を補完する (interpolateLabメソッド)
              0
                JUGEMテーマ:JavaScript

                データの可視化をする際に、しばしばデータの数値を色の変化で表現したくなるときがあります。そんなときは、D3.js の interpolateLab() メソッドを使うと便利です。

                このメソッドは、指定した2つの色の間を自動的に補完してくれるメソッドです。このメソッドを使うと、例えば 0% から 100% までのデータに対して、数値に応じた青色 (0%) と赤色 (100%) の間の色でデータをプロットすることができます。

                例えば青と赤の間を補完するには、いちばん単純な形だと下記のようにして使うことができます。
                 
                 var color = d3.interpolateLab("blue", "red");

                この場合、関数 color() は引数として 0 から 1 までの数値を取り、color(0) が blue、color(1) が red を返します。引数として 0 と 1 の間の数値を指定すると、関数 color() はその引数に応じて blue と red の間の色を返します。

                これはこれで良いのですが、今回は引数の数値の範囲や、引数の変化と色の変化の関係 (通常は linear = 線形) などを明示的に指定することにしました。下記のサンプルプログラムでは、0 から 20 までの数値によって white から steelblue までの色を生成する関数と、blue から red までの色を生成する関数を定義しています。

                サンプルページ

                // SVGのサイズを指定
                var width = 800;
                var height = 180;
                
                // 白からスティールブルー(Steelblue)へのグラデーション
                var color = d3.scale
                  .linear()
                  .domain([0, 20])
                  .range(["white", "steelblue"])
                  .interpolate(d3.interpolateLab);
                
                // 青から赤へのグラデーション
                var color2 = d3.scale
                  .linear()
                  .domain([0, 20])
                  .range(["blue", "red"])
                  .interpolate(d3.interpolateLab);
                  
                // SVG要素の円を20個追加するための配列
                var numData = d3.range(0,20);
                
                // SVGの幅と高さを指定
                var svg = d3.select("#MyGraph")
                  .attr("width", width)
                  .attr("height", height)
                  .append("g")
                
                // 白からスティールブルー(Steelblue)へのグラデーションのテスト
                svg.append("g")
                  .selectAll("circle")
                  .data(numData)
                  .enter()
                  .append("circle")
                  .attr({
                    "cx" : function(d){return 20 + d*40},
                    "cy" : 60,
                    "r" : 20,
                    "fill-opacity" : 1,
                    "fill" : function(d){return color(d)}
                  });
                
                // 青から赤へのグラデーションのテスト
                svg.append("g")
                  .selectAll("circle")
                  .data(numData)
                  .enter()
                  .append("circle")
                  .attr({
                    "cx" : function(d){return 20 + d*40},
                    "cy" : 120,
                    "r" : 20,
                    "fill-opacity" : 1,
                    "fill" : function(d){return color2(d)}
                  });
                
                


                 
                このエントリーをはてなブックマークに追加
                | D3.js | 00:04 | comments(0) | - | - |
                【D3.js】 ローソク足チャートの作成
                0
                  JUGEMテーマ:JavaScript

                  前回まで、3回に分けて D3.js による折れ線グラフの作成方法を紹介してきました。その際に 2 月の日経平均株価データ (日毎の始値・高値・安値・終値データを含むCSVファイル) を読み込んで折れ線グラフを作成していましたが、せっかくなので D3.js を使ってローソク足チャートを作成してみました。

                  ローソク足チャート(ローソクチャートとも言う)は、株価の変動をビジュアル化する方法の一つです。ローソク足チャートでは、日毎の始値と終値を長方形で示し、その上と下にその日の高値と終値を線で示します。始値と比べて終値が高いかどうか (=株価が上がったかどうか) によって長方形の色を変えて表示することで、株価の変動が一目で把握できる仕組みになっています。

                  ローソク足チャートを描くには TechanJS という財務関係の描画に特化した JavaScript ライブラリを使う方法もありますが、ローソク足チャートを作画する程度なら D3.js で作ってしまったほうが手っ取り早いです。今回は、終値が始値よりも高い場合は青色で、低い場合は赤色で、それぞれ日毎のローソク足チャートを描画するようにしてみました。

                  サンプルページ

                  // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                  var margin = {top: 40, right: 80, bottom: 80, left: 80};
                  var width = 800 - margin.left - margin.right;
                  var height = 500 - margin.top - margin.bottom;
                   
                  // CSVファイルの読み込み
                  d3.csv("./js/nikkei.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データから時間軸の両端を抽出
                    var n = dataSet.length;
                    time_start = new Date(dataSet[0]["日付"]);
                    time_end = new Date(dataSet[n-1]["日付"]);
                    
                    // 時間軸のスケール関数を生成
                    var time_scale = d3.time.scale()
                      .domain([time_start, time_end])
                      .range([0, width]);
                    
                    // 縦軸のスケール関数を生成
                    var y_scale = d3.scale.linear()
                      .domain([14000,18000])
                      .range([height, 0]);
                  
                    // 描画するデータと色を指定
                    var label = ["始値", "高値", "安値", "終値"];
                    var labelColor = ["red", "blue", "purple", "orange"];    
                    
                    // ローソク足チャートを作成する関数
                    function box(vHajimene, vTakane, vYasune, vOwarine, date){
                        // 各ローソクの幅
                        var w = 15;
                        svg.append("rect")
                          .attr("x", time_scale(date) - w/2)
                          .attr("y", function(){
                            if (vHajimene < vOwarine) return y_scale(vOwarine);
                            else return y_scale(vHajimene);
                          })
                          .attr("width", w)
                          .attr("height", function(){
                            return Math.abs(y_scale(vHajimene) - y_scale(vOwarine));
                          })
                          // 始値<終値なら青色、始値>終値なら赤色
                          .style("fill", function(){
                            if (vHajimene < vOwarine) return "blue";
                            else return "red";
                          });
                          
                        // 高値を示す横線を描画
                        svg.append("line")
                          .attr("x1", time_scale(date) - w/2)
                          .attr("y1", y_scale(vTakane))
                          .attr("x2", time_scale(date) + w/2)
                          .attr("y2", y_scale(vTakane))
                          .style("stroke", "black");
                        // 安値を示す横線を描画
                        svg.append("line")
                          .attr("x1", time_scale(date) - w/2)
                          .attr("y1", y_scale(vYasune))
                          .attr("x2", time_scale(date) + w/2)
                          .attr("y2", y_scale(vYasune))
                          .style("stroke", "black");
                        // 高値と安値を結ぶ縦線を描画
                        svg.append("line")
                          .attr("x1", time_scale(date))
                          .attr("y1", y_scale(vTakane))
                          .attr("x2", time_scale(date))
                          .attr("y2", y_scale(vYasune))
                          .style("stroke", "black");
                    };
                    
                    // 日毎のデータをもとにローソク足チャートを描画
                    for(var i = 0; i < n-1; i++){
                      time = new Date(dataSet[i]["日付"]);
                      box(dataSet[i]["始値"],dataSet[i]["高値"],dataSet[i]["安値"],dataSet[i]["終値"],time);
                    };
                  
                    // X軸を描画
                    svg.append("g")
                      .attr("class", "axis")
                      .attr("transform", "translate(0," + height + ")")
                      .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");
                    
                    // Y軸を描画
                    svg.append("g")
                      .attr("class", "axis")
                      .call(d3.svg.axis()
                        .scale(y_scale)
                        .orient("left")
                      );
                  });
                  


                   
                  このエントリーをはてなブックマークに追加
                  | D3.js | 10:09 | comments(0) | - | - |
                  【D3.js】 折れ線グラフの作成・その3
                  0
                    JUGEMテーマ:JavaScript

                    前回は日経平均株価データ (CSVファイル) を読み込んで、始値・高値・安値・終値のそれぞれを色を変えながら折れ線グラフで描画する JavaScript プログラムを作成しました。しかし、分かりやすさを優先させたため、やってることの単純さに比べてプログラムが長く (134 行) なってしまいました。そこで今回は、前回のプログラムを改良することにします。

                    具体的には、前回は始値・高値・安値・終値のそれぞれについて、折れ線グラフを描画するプログラムを書いていました。しかし、これらはほぼ同じプログラムの繰り返しになっていました。そこで、繰り返しになっていた部分は 1 つの関数に纏めて、始値・高値・安値・終値のそれぞれの描画に必要な差分を引数で渡すことにします。

                    作成したプログラムを下記に示します。35 行目以降が、今回作成した関数になります。出力は前回と同じですが、こうして繰り返しの部分を 1 つの関数に纏めることで、プログラムの長さは 99 行まで短縮することができました。

                    // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                    var margin = {top: 40, right: 80, bottom: 80, left: 80};
                    var width = 800 - margin.left - margin.right;
                    var height = 500 - margin.top - margin.bottom;
                     
                    // CSVファイルの読み込み
                    d3.csv("./js/nikkei.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データから時間軸の両端を抽出
                      var n = dataSet.length;
                      time_start = new Date(dataSet[0]["日付"]);
                      time_end = new Date(dataSet[n-1]["日付"]);
                      
                      // 時間軸のスケール関数を生成
                      var time_scale = d3.time.scale()
                        .domain([time_start, time_end])
                        .range([0, width]);
                      
                      // 縦軸のスケール関数を生成
                      var y_scale = d3.scale.linear()
                        .domain([14000,18000])
                        .range([height, 0]);
                    
                      // 描画するデータと色を指定
                      var label = ["始値", "高値", "安値", "終値"];
                      var labelColor = ["red", "blue", "purple", "orange"];    
                      
                      // データごとに折れ線グラフを描画するための関数
                      function drawLine(i){
                        var line = d3.svg.line()
                          .x(function(d,i){
                            var tmp = new Date(d["日付"]);
                            return time_scale(tmp);
                          })
                          .y(function(d){
                            return y_scale(d[label[i]]);      
                          });
                    
                          svg.append("path")
                          .attr("d", line(dataSet))
                          .style("stroke", labelColor[i])
                          .style("fill", "none");      
                      };
                      
                      // 始値、高値、安値、終値のそれぞれについて折れ線グラフを生成
                      for (var i=0 ; i<4 ; i++){
                        drawLine(i);
                      };
                    
                      // 凡例を作成  
                      svg.selectAll("text")
                        .data(label)
                        .enter()
                        .append("text")
                        .text(function(d){
                          return d;
                        })
                        .style("fill", function(d,i){
                          return labelColor[i];
                        })
                        .attr("x", width - 40)
                        .attr("y", function(d, i){
                          return 20*(i+1);
                        });
                    
                      // X軸を描画
                      svg.append("g")
                        .attr("class", "axis")
                        .attr("transform", "translate(0," + height + ")")
                        .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");
                      
                      // Y軸を描画
                      svg.append("g")
                        .attr("class", "axis")
                        .call(d3.svg.axis()
                          .scale(y_scale)
                          .orient("left")
                        );
                    });
                    
                    
                     
                    このエントリーをはてなブックマークに追加
                    | D3.js | 21:02 | comments(0) | - | - |
                    【D3.js】 折れ線グラフの作成・その2
                    0
                      JUGEMテーマ:JavaScript

                      前回は日経平均株価データ (CSVファイル) のうち、終値の変化だけを折れ線グラフで描画してみました。でも前回読み込んだ CSV ファイルには終値だけではなく、始値・高値・安値のデータも含まれています。そこで今回は、せっかくなのでこれら4つのデータ (始値・高値・安値・終値) のそれぞれを、色を変えながら折れ線グラフで描画してみました。

                      サンプルページ


                       
                      // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
                      var margin = {top: 40, right: 80, bottom: 80, left: 80};
                      var width = 800 - margin.left - margin.right;
                      var height = 500 - margin.top - margin.bottom;
                       
                      // CSVファイルの読み込み
                      d3.csv("./js/nikkei.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データから時間軸の両端を抽出
                        var n = dataSet.length;
                        time_start = new Date(dataSet[0]["日付"]);
                        time_end = new Date(dataSet[n-1]["日付"]);
                        
                        // 時間軸のスケール関数を生成
                        var time_scale = d3.time.scale()
                          .domain([time_start, time_end])
                          .range([0, width]);
                        
                        // 縦軸のスケール関数を生成
                        var y_scale = d3.scale.linear()
                          .domain([14000,18000])
                          .range([height, 0]);
                      
                        // 始値、高値、安値、終値のそれぞれについてパスデータを生成    
                        var line_1 = d3.svg.line()
                          .x(function(d,i){
                            var tmp = new Date(d["日付"]);
                            return time_scale(tmp);
                          })
                          .y(function(d,i){
                            return y_scale(d["始値"]);      
                          });
                      
                        var line_2 = d3.svg.line()
                          .x(function(d,i){
                            var tmp = new Date(d["日付"]);
                            return time_scale(tmp);
                          })
                          .y(function(d,i){
                            return y_scale(d["高値"]);      
                          });
                      
                        var line_3 = d3.svg.line()
                          .x(function(d,i){
                            var tmp = new Date(d["日付"]);
                            return time_scale(tmp);
                          })
                          .y(function(d,i){
                            return y_scale(d["安値"]);      
                          });
                      
                        var line_4 = d3.svg.line()
                          .x(function(d,i){
                            var tmp = new Date(d["日付"]);
                            return time_scale(tmp);
                          })
                          .y(function(d,i){
                            return y_scale(d["終値"]);      
                          });
                          
                        // 折れ線グラフを生成
                        svg.append("path")
                          .attr("d", line_1(dataSet))
                          .style("stroke", "red")
                          .style("fill", "none");
                      
                        svg.append("path")
                          .attr("d", line_2(dataSet))
                          .style("stroke", "blue")
                          .style("fill", "none");
                      
                        svg.append("path")
                          .attr("d", line_3(dataSet))
                          .style("stroke", "purple")
                          .style("fill", "none");
                      
                        svg.append("path")
                          .attr("d", line_4(dataSet))
                          .style("stroke", "orange")
                          .style("fill", "none");
                      
                        // 凡例を作成  
                        var label = ["始値", "高値", "安値", "終値"];
                        var labelColor = ["red", "blue", "purple", "orange"];
                      
                        svg.selectAll("text")
                          .data(label)
                          .enter()
                          .append("text")
                          .text(function(d){
                            return d;
                          })
                          .style("fill", function(d,i){
                            return labelColor[i];
                          })
                          .attr("x", width - 40)
                          .attr("y", function(d, i){
                            return 20*(i+1);
                          });
                      
                        // X軸を描画
                        svg.append("g")
                          .attr("class", "axis")
                          .attr("transform", "translate(0," + height + ")")
                          .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");
                        
                        // Y軸を描画
                        svg.append("g")
                          .attr("class", "axis")
                          .call(d3.svg.axis()
                            .scale(y_scale)
                            .orient("left")
                          );
                      });
                      
                      
                       
                      このエントリーをはてなブックマークに追加
                      | D3.js | 22:32 | comments(0) | - | - |