2つの年代のデータをCSVファイルから読み込む

      2つの年代のデータをCSVファイルから読み込む はコメントを受け付けていません

「D3でCSVファイルを読み込む」では、CSVファイルからデータを読み込んで表示することができました。ここではもう少し複雑なデータの視覚化を行ってみます。

1945年と2019年の1年間の気温の変化を可視化する

365日の気温の変化を色で可視化してみます。既に作成したcsv_import.htmlファイルを改変します。

CSVファイルは以下のデータを使用します。htmlファイルと同じ階層(testServerフォルダ内)に置いてください。

このファイルは気象庁のサイトからダウンロードしています。

CSVファイルが2枚入っているので、Excelで2枚とも開き、以下のように片方のファイルにコピーしましょう。1945年と2019年はたまたま閏年がある歳なので、日数が一致しています。2種のデータを扱い際は必ず個数が同じものを選びます。


3行目までは削除し、4行目を「date2019, temp2019, date1945, temp1945」に変更します。


このファイルの文字コードは必ず「UTF-8」で保存してください。ファイル名は「temp_tokyo_1945_2019.csv」としておきます。このように、データを作成する場合には列の先頭にアフファベットで列名(カラム名)を記入してください。

366日分のバーを表示する必要があるので、表示画面の幅を1500ピクセルにします。また、最初に表示する年を1945年に設定します。

var w = 1500;
var h = 300;
var year = 1945;


CSVファイルのリンクを変更します。

d3.csv("temp_tokyo_1945_2019.csv").then(function(dataset){


xScaleとyScaleを決めます。この際、1945年と2019年の両方の年での最低気温と最高気温を決める必要があるため、以下のコードに変更します。

var xScale = d3.scaleBand()
   .domain(d3.range(dataset.length))   //datasetの数を計算
   .rangeRound([0, w])  //range()と同じ機能だが、整数値にする
   .paddingOuter(0.5);  //バーの外側のpadding

//1945年と2019年の1番低い温度を検索する
var min1945 = d3.min(dataset, function(d) {
   return parseFloat(d.temp1945);
});   
var min2019 = d3.min(dataset, function(d) {
   return parseFloat(d.temp2019);
});
//1945と2019の両方で一番低い気温を決定
var min = d3.min([min1945, min2019]); 

//1945年と2019年の1番高い温度を検索する
var max1945 = d3.max(dataset, function(d) {
   return parseFloat(d.temp1945);
});
var max2019 = d3.max(dataset, function(d) {
   return parseFloat(d.temp2019);
});
//1945と2019の両方で一番高い気温を決定            
var max = d3.max([max1945, max2019]);

//最低気温と最高気温に基づいてスケールを作成
var yScale = d3.scaleLinear()
      .domain([min, max])
      .rangeRound([0, h]);


rectのy属性とheight属性を変更します。さらに、このサンプルのバーは青一色にします。

svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
      return xScale(i);
})
.attr("y", function(d) {
      //1945年の温度をyScaleで変換
      return h - yScale(parseFloat(d.temp1945));
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
   return yScale(parseFloat(d.temp1945));
})
.attr("fill", "blue")


mouseoverのツールチップのラベルを変更します。

.on("mouseover", function(event, d) {

   d3.select(this)
      .attr("fill", "red");

      //選択されたDOM要素(ここではdiv)の座標を取得。
      var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.bandwidth() / 2;
      var yPosition = parseFloat(d3.select(this).attr("y")) + 14;

   //tooltipラベルを作成
   d3.select("#tooltip")
      .style("top", yPosition + "px")
      .style("left", xPosition + "px")
      .select(".date")
      .text(function(){
         if(year == 1945){
            return d.date1945;
         }else{
            return d.date2019;
         }
      });

   d3.select("#tooltip")
      .select(".temp")
      .text(function(){
         if(year == 1945){
            return d.temp1945 + "度";
         }else{
            return d.temp2019 + "度";
         }
      });

   //tooltipを表示
   d3.select("#tooltip").classed("hidden", false);
})


マウスアウトのイベントを以下のように変更します。

.on("mouseout", function(d) {

   d3.select(this)
      .attr("fill", "blue");

   //tooltippを隠す
   d3.select("#tooltip").classed("hidden", true);
});

ボタンで2つの年代の気温を交互に表示する

rectのマウスアウトの下に、ボタンが押された時のイベントを定義します。

//ボタンをクリックして新しいデータに更新
d3.selectAll("button")  //selectAllにすることが重要
   .on("click", function() {

      //ボタンのidを取得
      var buttonID = d3.select(this).attr("id");

      if (buttonID == "button1945") {  //1945年ボタンの場合、
         year = 1945;
      }else{  //それ以外(2019年ボタン)
         year = 2019;
      }

      svg.selectAll("rect")
         .data(dataset)
         .transition()
         .duration(1000)
         .attr("y", function(d) {
            if(year == 1945){
               return h - yScale(parseFloat(d.temp1945));
            }else{
               return h - yScale(parseFloat(d.temp2019));
            }
         })
         .attr("height", function(d) {
            if(year == 1945){
               return yScale(parseFloat(d.temp1945));
            }else{
               return yScale(parseFloat(d.temp2019));
            }
         });
   });


ツールチップのdivの下にボタンを定義します。

<div id="tooltip" class="hidden">
   <p><strong class="date">Label Name</strong></p>
   <p><span class="temp">0</span></p>
</div>

<button type="button" id="button1945">1945年</button>
<button type="button" id="button2019">2019年</button>


ボタンのマウスオーバー用とrectの枠線の定義をCSSで行います。

button:hover {
   background-color: #deb887;   /*ボタンのマウスオーバー時の色*/
}

svg{
   display: block; /*ボタンに対して下にレイアウト*/
}

rect{
   stroke:white;
}


ボタンを押すと、1945年と2019年の気温が入れ替わります。2019年の方が全体的に暑い日が増えていることが分かります。

折れ線グラフを追加する

ツールチップの表示の後でボタンイベントの前に以下のコードを追加します。

svg.append("path")
      .datum(dataset)
      .attr("fill", "none")
      .attr("stroke", "red")
      .attr("stroke-width", 1)
      .attr("d", d3.line()
      .x(function(d, i) { return xScale(i); })
      .y(function(d){
            //1945年の温度をyScaleで変換
            return h - yScale(parseFloat(d.temp1945));
      })); 


1945年の折れ線グラフが表示されます。ボタンを押すことによって2つの年代の気温を交互に表示するため、ボタンアクションの末尾にpathを追加します。

//ボタンをクリックして新しいデータに更新
d3.selectAll("button")  //selectAllにすることが重要
   .on("click", function() {

   //ボタンのidを取得
   var buttonID = d3.select(this).attr("id");

   if (buttonID == "button1945") {  //1945年ボタンの場合、
      year = 1945;
   }else{  //それ以外(2019年ボタン)
      year = 2019;
   }

   svg.selectAll("rect")
      .data(dataset)
      .transition()
      .duration(1000)
      .attr("y", function(d) {
         if(year == 1945){
            return h - yScale(parseFloat(d.temp1945));
         }else{
            return h - yScale(parseFloat(d.temp2019));
         }
      })
      .attr("height", function(d) {
         if(year == 1945){
            return yScale(parseFloat(d.temp1945));
         }else{
            return yScale(parseFloat(d.temp2019));
         }
   });

   svg.selectAll("path")
      .datum(dataset)
      .transition()
      .duration(500)
      .attr("fill", "none")
      .attr("stroke", "red")
      .attr("stroke-width", 1)
      .attr("d", d3.line()
      .x(function(d, i) { return xScale(i); })
      .y(function(d){    
         if(year == 1945){
            return h - yScale(parseFloat(d.temp1945));
         }else{
            return h - yScale(parseFloat(d.temp2019));
         }
   }));   //svg.selectAll("path") 
});   //d3.selectAll("button")


アニメーションによって、折れ線グラフが動きます。

参考:以下のサンプルは、温度を明暗に変換しています。他のサンプルに比べるとちょっと難しいですが、参考にしてみてください。

また、以下のサンプルは色をつけたものです。