LATEST ENTRIES
CATEGORIES
ARCHIVES
SPONSORED LINK
MOBILE
qrcode
LINKS
PROFILE
OTHERS

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

Agata's Blog

MATLABやPythonとともにD3.jsを使ってデータ解析とデータビジュアライゼーションに挑戦する某エンジニアのBlog
D3 v4 を使って地震データの一覧表を作成する
0

    これまでD3を使ってSVGを操作してきましたが、D3を使って操作できるのはSVGだけではありません。同じように select() メソッドを使って、他のDOM要素を JavaScript 側から操作することも可能です。そこで今回は、米国地質調査所 (USGS: United States Geological Survey) が公開している過去4.5ヶ月分の地震データをもとに、<div>~</div> 要素を操作して一覧表を作成するプログラムを作成しました。

     

    2行目で、まずUSGSが JSON 形式で公開している、過去4.5ヶ月分の世界の地震データ最新版のURLを設定しています。これにより、この JavaScript プログラムが呼び出されるたびに、表示されるテーブルの内容は自動的に最新版の地震データになるというわけです。7~24行目では、テーブルのヘッダー行を作成しています。ヘッダー行の背景色や文字のスタイルは CSS 側で自由に設定できるように、<div> 要素にはそれぞれクラス名を与えています。

     

    26行目以下は、いよいよ USGS のサーバーから JSON 形式の公開データを取得して、必要な情報を整理してテーブルで表示する部分です。この例では受領したデータから、個別の地震の情報のうち .泪哀縫船紂璽鼻↓発生場所の名称、H生日時、USGSの詳細情報ページのURL、の4つの情報を抽出して表示することにしています。USGSが公開しているデータにはこれ以外にも、震源地の緯度・経度や震源の深さ、発生した国の名称など多くの情報が記録されています。詳細については、USGSによる説明を参照してください。

     

    42~48行目では、データに含まれるマグニチュードの最大値と最小値を求めて、マグニチュードの数値によりテーブルの行の色が変わるようにカラーグラデーションを設定しています (関連記事:D3 v4でオリジナルのカラーマップを作成する方法)。

     

    今回は JavaScript だけでなく、CSS側でも色々な設定をしています。それぞれの内容は、下記のタブを切り替えることで確認することができます。

     

     

     

    過去の関連記事

    D3 v4でオリジナルのカラーマップを作成する方法

    D3 v4で「レ・ミゼラブル」の人物関係を可視化する

    D3で過去30日間に世界で発生した地震を可視化する

     

    JUGEMテーマ:JavaScript

    このエントリーをはてなブックマークに追加
    | 応用 | 21:23 | comments(0) | - | - |
    D3.js v4で「レ・ミゼラブル」の人物関係を可視化
    0

      今回はちょっと応用編です。

       

      インターネットで公開されているデータセットをいろいろ見ていると、文豪ヴィクトル・ユゴーの名作『レ・ミゼラブル』の人間関係というデータがありました。JSON形式で公開されているこのデータ、内容がどこまで正しいのかは良く分かりませんが、D3.js でJSON形式のファイルを読み込んで可視化する練習にちょうど良い手ごろなサイズなので、SVGのrect要素とtext要素だけを使って可視化してみました。

       

       

       

      JUGEMテーマ:JavaScript

      このエントリーをはてなブックマークに追加
      | 応用 | 19:57 | 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(); }); };

         
        このエントリーをはてなブックマークに追加
        | 応用 | 00:15 | 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"); })
          このエントリーをはてなブックマークに追加
          | 応用 | 11:08 | 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")
                );
            });
            


             
            このエントリーをはてなブックマークに追加
            | 応用 | 10:09 | comments(0) | - | - |
            【D3.js】SVGにドロップシャドウをかけて立体的にする
            0
              JUGEMテーマ:JavaScript

              SVG では filter 要素を使って、画像をぼかしたり色を変えたりすることができます。この filter 要素をうまく使うと、画像の背後に影をつけて、あたかも背景から浮かび上がったような視覚的効果を出すことができます。今回は D3.js を使って、この「ドロップシャドウ」(drop-shadow) と呼ばれる効果を試してみました。

              とはいえ、ただ単純に SVG 要素にドロップシャドウ効果を加えるだけでは D3.js を使う意味がないので、filter 要素のパラメータを変化させて SVG 要素が背景から徐々に浮かび上がるようなアニメーションにしてみました。
              var width = 800;
              var height = 500;
              
              svg = d3.select("#MyGraph")
                .attr("width", width)
                .attr("height", height);
              
              // #drop-shadow という ID のフィルタを定義
              var filter = svg.append("defs")
                .append("filter")
                .attr("id", "drop-shadow")
                .attr("height", "130%");
              
              // 元となるSVG要素をぼかして影を作る
              var feGaussianBlur = filter.append("feGaussianBlur")
                  .attr("in", "SourceAlpha")
                  .attr("stdDeviation", 3)
                  .attr("result", "blur");
              
              // 作った影の表示位置を少しずらす
              var feOffset = filter.append("feOffset")
                  .attr("in", "blur")
                  .attr("dx", 5)
                  .attr("dy", 5)
                  .attr("result", "offsetBlur");
              
              // 2つの入力画像 (元のSVG要素と影) を重ねて表示    
              filter.append("feBlend")
                .attr("in", "SourceGraphic")
                .attr("in2", "blurOut")
                .attr("mode", "normal");
               
              var item = svg.append("rect")
                .attr("x", 100)
                .attr("y", 100)
                .attr("width", width/4)
                .attr("height", height/4)
                .style("fill", "white")
                .style("filter", "url(#drop-shadow)");
              
              var item2 = svg.append("circle")
                .attr("cx", 500)
                .attr("cy", 300)
                .attr("r", 50)
                .style("fill", "white")
                .style("filter", "url(#drop-shadow)");
              
              // 影の位置とぼかしの強さを変化させて、SVG要素が画面から浮かび上がるようにアニメーション
              var dest_min = 0, dest_max = 5, dest = dest_min;
              var std_min = 0, std_max = 5, std = std_min;
              
              var floater = function() {
                if (dest == dest_min) {
                  dest = dest_max;
                  std = std_max;
                }
                else {
                  dest = dest_min;
                  std = std_min;
                }
                feOffset.transition()
                  .duration(3000)
                  .attr("dx", dest)
                  .attr("dy", dest);
                feGaussianBlur.transition()
                  .duration(3000)
                  .attr("stdDeviation", std)
                  .each("end", floater);
              };
              
              floater();
              

              サンプルページ

              このエントリーをはてなブックマークに追加
              | 応用 | 08:17 | comments(0) | - | - |