一次関数の表示
続いて、先ほどのプロットしたグラフの上に、図3のように一次関数の直線を引いてみます。

この直線は、プロットした値を生成するために用いた一次関数 y=2x+10 のグラフです。
実際にはこの数式から導き出された値にランダム値を加えたものが、先ほどのCSVのデータになります。D3では、リスト5のように指定した点(ここでは2点)を結ぶ線として直線を描画できます。
// (省略) // (1) 2点のデータを作る const data = [ { x : 0, y : 10}, { x : 100 , y : 210} ]; // (2) SVGでのパス要素を作成 const path = svg.append("path"); // (3) 線を結ぶための関数を作成 const line = d3.line().x(function (d){ return xScale(d.x); }).y(function(d){ return yScale(d.y); }); // (4) path要素内のd属性の値を作成する path.datum(data) .attr('fill','none') .attr('stroke','#666666') .attr('d',line);
(1)で始点と終点を指定します。このサンプルではxの範囲0~100としたため、y=2x+10で求めたyの範囲が10~210になっています。
(2)でSVGのパス要素を作成します。続いて(3)のようにd3.line()を用いて線を引くための関数を作成します。
最後に(4)datum関数を使ってpath要素におけるd属性を自動作成します。先ほどのプロットではdata関数を使いましたが、ここでは1つのpath要素のd属性にdataで指定した配列を使って値を作成します。
ここが先ほどのdata関数とdatum関数で大きく違うのでご注意ください。また、このコードで作成されたSVG要素はリスト6のようになります。
<path fill="none" stroke="#666666" d="M150,702L750,142"></path>
前回は、SVGのline要素を使って2点間の線を記述しましたが、D3では(1)で値を複数設定すれば隣り合う2点での線を引くための値を自動で作成します。
2点間だとメリットがわかりにくいですが、折れ線データを表示する場合や後述する二次関数などでも同じやり方で記述できます。応用範囲が非常に広い記法です。
一次関数の平行移動
今回の例ではあらかじめ答えが分かっている直線を引きました。しかし、実際にはこの直線の妥当性がわからないのが一般的です。そこで、この直線の妥当性について検証してみます。
グラフの線を左右に10ほど移動し、図4のように幅を持たせた範囲を作成します。このように範囲を持たせるとプロットした点がそれらの幅内に収まっているかどうかを判断することができるようになります。

一次関数の平行移動について図5を学んだことを覚えている方もいるでしょう。このように平行移動を使えば非常に簡単に線に幅を持たせられます。

そして、この線の幅内にどの程度の割合が含まれているかを調べることで、おおよその正しさがわかります(あくまで簡易的な確認です)。
例えば、指定した幅内に100個中90個含まれていれば90%、100個中50個含まれていれば50%、といった形で導けます。
ただし、実際にはランダム値のため、ノイズといわれる本来取り除くべきデータも含まれてしまっています。そのため、このままでは100%になること=正答率が正しいとは限らない点に注意してください(※)。
※実際には、このノイズデータを除去する必要があります。実際の分析ではノイズデータをどのように除去する方法が多様にあり、またサンプルデータの特性にあったノイズ除去を採用する必要があります。
実際の問題では、正解の式(例えば y=2x+10)は分かりませんが、グラフ上の任意の2点があれば、簡単に直線の式を求めることができます。つまり、このようにして予測の良さを測る基準(評価方法)を作ることができれば、あとはその評価方法を使って、どの式がもっとも精度が高いかの判断ができます。
さらに、ランダムにいくつかのデータを選んで同じ計算を繰り返し、その中で最も評価の高い式を採用すれば、正解に近い式を自動的に見つけることも可能です。
今回は非常に荒い方法を紹介しましたが、このように評価方法がわかれば、実際にはいろいろと試行錯誤してより適した解を求めることができます。
また、統計ライブラリなどを使い、自分が計算過程をあまりよく把握できない方法で解を求めたときに、その解が正しそうかを確認したいケースがあります。その際には、このような荒い方法であっても助けになるはずです。