D3.js v4/v5 コンター図の作成 (d3.contours 使い方)
D3でコンター図(contours plot)の作り方を紹介します。
サンプルデモ
サンプルプログラム
| 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | <!DOCTYPE html> <html> <head>   <meta charset="utf-8">   <title>D3 Contours Plot</title>   <script src="https://d3js.org/d3.v5.min.js"></script> <!--   <script src="https://d3js.org/d3.v4.min.js"></script> --> <!--   <script src="https://d3js.org/d3-hsv.v0.1.min.js"></script> --> <!--   <script src="https://d3js.org/d3-contour.v1.min.js"></script> --> </head> <body>   <script>   // 1. データの準備   var width = 800; // グラフの幅   var height = 600; // グラフの高さ   function himmelblaus(x, y) {     return(x * x + y - 11) * (x * x + y - 11) + (x + y * y - 7) * (x + y * y - 7);   }   var n = 240;   var m = 125;   var k = 0;   var values = new Array(n * m);   for(var j = 0; j < m; ++j) {     for(var i = 0; i < n; ++i) {       var x = i / (n - 1) * 10 - 5;       var y = j / (m - 1) * 10 - 5;       values[k] = himmelblaus(x, y);       ++k;     }   }   // 2. SVG領域の設定   var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);   // 3. しきい値の設定   var thresholds = d3.range(0, 20).map(function(p) { return 7*p; });   // 4. データ変換   var contours = d3.contours()     .size([n, m])     .thresholds(thresholds);   // 5. カラースケールの設定   var color = d3.scaleSequential(function(t){return d3.hsl(t*230, 1, 0.5) + ""}).domain([140,0]);   // 6. コンター用SVG要素の設定   svg.selectAll("path")     .data(contours(values))     .enter()     .append("path")     .attr("d", d3.geoPath(d3.geoIdentity().scale(width / n)))     .attr("fill", function(d) { return color(d.value); })     .attr("stroke","white")     .attr("stroke-width","0.5");   </script> </body> </html> | 
解説
d3.contourはv5から追加された機能ですが、v4でもHTMLファイルのヘッダー部分で下記を記載してモジュールを呼び出せば使うことができます。
| 1 2 | <script src="https://d3js.org/d3-hsv.v0.1.min.js"></script> <script src="https://d3js.org/d3-contour.v1.min.js"></script> | 
1. データの準備
コンター用のデータを準備します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |   function himmelblaus(x, y) {     return(x * x + y - 11) * (x * x + y - 11) + (x + y * y - 7) * (x + y * y - 7);   }   var n = 240;   var m = 125;   var k = 0;   var values = new Array(n * m);   for(var j = 0; j < m; ++j) {     for(var i = 0; i < n; ++i) {       var x = i / (n - 1) * 10 - 5;       var y = j / (m - 1) * 10 - 5;       values[k] = himmelblaus(x, y);       ++k;     }   } | 
この部分は、コンター用のサンプルデータvalues[]の作成です。こちらのHimmelblau's functionを参考にさせて頂きました。コンター用のデータ(values)はn(x方向の配列要素数) × m(y方向の配列要素数)の要素数をもつ一次元配列として設定する必要があります。
2. SVG領域の設定
SVGタグを設定します。
| 1 |   var svg = d3.select("body").append("svg").attr("width", width).attr("height", height); | 
3. しきい値の設定
しきい値を設定する一次元の配列(thresholds)を定義します。
| 1 |   var thresholds = d3.range(0, 20).map(function(p) { return 7*p; }); | 
ここでは、D3のメソッドを使って配列を作成しました。d3.range(a,b)はaからbまでの連続値の配列を作成します([0,1,2,..])。.mapメソッドは各配列の値を設定した関数に応じて変更するものです。今回は[0,7,14,...]の配列を作成し、これをコンター図のしきい値とします。
4. データ変換
コンター図用に用意したデータを変換するための関数をメソッドのd3.contoursを使って設定します。
| 1 2 3 |   var contours = d3.contours()     .size([n, m])     .thresholds(thresholds); | 
.sizeでは、データの要素数n(x方向の配列要素数) × m(y方向の配列要素数)のサイズを、.thresholdsではしきい値設定用の配列を指定します。
5. カラースケールの設定
コンター図の色分け用のカラースケールをD3のメソッドを使って設定します。
| 1 |   var color = d3.scaleSequential(function(t){return d3.hsl(t*230, 1, 0.5) + ""}).domain([140,0]); | 
d3.scaleSequential(function(t){}).domain([,])は、domainで設定した範囲を0.0~1.0に線形変換して内部の関数に渡し、内部の関数の返り値を出力する関数をcolorに設定します。d3.hslは、HSL色空間のRGB値を算出してくれるものです。d3.hslの一つ目の変数が角度に相当するものですが、0~230度に設定するとサンプルのような色使いになります。カラースケールの作り方についてはこちらを参照ください。
6. コンター用SVG要素の設定
SVG要素を設定します。
| 1 2 3 4 5 6 7 8 |   svg.selectAll("path")     .data(contours(values))     .enter()     .append("path")     .attr("d", d3.geoPath(d3.geoIdentity().scale(width/n)))     .attr("fill", function(d) { return color(d.value); })     .attr("stroke","white")     .attr("stroke-width","0.5"); | 
dataに設定したデータ変換関数によって変換したデータを設定し、"path"要素でコンター図を描きます。"d"属性にはコンター図用に変換するd3.geoPath()を用います。引数として設定したd3.geoIdentity().scale(width/n)は、スケールを変換するもので、デフォルトではm×n pxで描かれますので所望の大きさに変換します。
まとめ
D3のv5にはカラーテーマが複数用意されていますので、あわせて使えば様々なシチュエーションに対応できます。




