SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

データサイエンス基礎を高校数学から復習

データサイエンス基礎を高校数学から復習しよう! D3.jsでデータを表現する

データサイエンス基礎を高校数学から復習しよう 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

D3を使ってグラフを書く準備をする

 D3の実行方法とSVGの関係が分かったところで、ここからはD3が持つ数値データをグラフ化していくための、基本的な部分を説明していきます。

D3でグラフの軸を表示する

 図11の通り、数学などでよく使うXY軸をD3の機能を使って描写します。

図11:左下を(0,0)とした場合のXY軸の描写
図11:左下を(0,0)とした場合のXY軸の描写

 これを実現するためのコードがリスト3です。

[リスト3]D3を使った簡単なサンプル(js/basic/BasicController.jsの抜粋)
const ele =  document.getElementById("canvas");

// (1) X軸と画面上の位置の関係
const x = d3.scaleLinear()
	.domain([0, 300])
	.range([40, 900 - 20]); // 余白を考慮

// (2) Y軸と画面上のY位置の関係
const y = d3.scaleLinear()
	.domain([0, 100])
	.range([600 - 30, 20]); // 余白を考慮

const contents = d3.select(ele);
const svg = contents.append("svg")
	.attr("width", 900)
	.attr("height", 600);

// (3) X軸を配置する
svg.append("g")
	.attr("transform", `translate(0,${600 - 30})`) // 余白を考慮
	.call(d3.axisBottom(x));

// (4) Y軸を配置する
svg.append("g")
	.attr("transform", `translate(${40},0)`) // 文字列内変数の利用である{}を使った表記はあえて(3)とあわせている
	.call(d3.axisLeft(y));

 この処理では非常に基本的な考え方が含まれるので図12で説明します。

図12:左下を(0,0)として場合のXY軸の描写
図12:左下を(0,0)とした場合のXY軸の描写

 (1)ではX軸のデータ上の範囲と画面上の範囲を考慮したスケールを作成しています。同様に(2)ではY軸のデータ上の範囲と画面上の範囲を考慮したスケールを作成しています。スケールとは、データ上の値から画面上の位置を示す値を求める関数です。

 domainとはデータ範囲、rangeとは画面上の範囲を示します。X軸では、データの0~300を画面範囲を40~880へと変換するという意味になります。

 ここで気をつけるべきは、Y軸の場合、データは0〜100に対して、画面範囲は570〜20と反対向きになることです。例えば、リスト4のようにすれば、実際の位置を計算できます。

[リスト4]スケール関数を使った画面位置の求め方
x(58); // X軸の58の位置は 202.39999999999998
y(40); // Y軸の40の位置は 350

 また、scaleLinearの「Linear」は比例という意味で、数学では一般的な軸がこのLinear軸です。これ以外にも数学では対数軸時間軸などを使ってきたと思います。

 そして(3)(4)で実際の軸をどの場所に配置するかを決めています。また、axisBottomは、グラフ下に配置する場合の表示に適した軸を作る処理になります。

 g要素とは、配下の要素のグループ化のことであり、HTMLであればdivタグのようなものと捉えてもらって問題ありません。そして、transformでその位置移動を行います。X軸は(40,0)、Y軸は(0,570)に移動しています。

 また、callは指定された処理を実行し、その親要素(この場合には新たに作成したg要素)内に追加します。axisBottomは指定されたスケールを用いて、ラベルが下部分、メモリが上に向いている軸を作る処理であり、その処理をcallを通じて実行し、そして、それらを包括した親要素であるg要素に対してtransformにて移動するという一連の流れになります。同様に、axisLeftは左側表示用の軸になります。

軸の位置を変える

 続いて、先ほどの例の応用として図13のように、軸の移動と値の位置をわかりやすくするグリッドを描写する例を考えます。

図13:マイナス値も考慮したXY軸とグリッドの表示
図13:マイナス値も考慮したXY軸とグリッドの表示

 表示する画面サイズは変更しない前提で、実際のデータ範囲を変える場合にはリスト4のように軸のデータ範囲が変わります。

[リスト4]D3を使った簡単なサンプル(js/basic/BasicController.jsの抜粋)
const ele =  document.getElementById("canvas");
// (1) X軸と画面上の位置の関係
const x = d3.scaleLinear()
	.domain([-150, 150])
	.range([40, 900 - 20]);

// (2) Y軸と画面上のY位置の関係
const y = d3.scaleLinear()
	.domain([-100, 100])
	.range([600 - 30, 20]);

// (省略)

//  (3) (0,0)の位置を求める
const x_zero = x(0);
const y_zero = y(0);

//  (4) X軸を配置する
svg.append("g")
	.attr("transform", `translate(0,${y_zero})`)
	.call(d3.axisBottom(x));

// (5) Y軸を配置する
svg.append("g")
	.attr("transform", `translate(${x_zero},0)`)
	.call(d3.axisLeft(y));

// (6) グリッド表示する為のg(グループ)要素を作成する
const grid = svg.append("g")
	.attr('class','-grid');

// (7) X軸用のグリッドを表示する
for(let yy = -100; yy <= 100; yy += 20){
	grid.append("line")
		.attr("x1", x(-150)).attr("y1", y(yy)).attr("x2", x(150)).attr("y2", y(yy));
}
//  (8) Y軸用のグリッドを表示する
for(let xx = -140; xx <= 140; xx += 20){
	grid.append("line")
		.attr("x1", x(xx)).attr("y1", y(-100)).attr("x2", x(xx)).attr("y2", y(100));
}

// (9) 背景を表示する
grid.append("rect").attr('class','-grid-bg')
	.attr("x",x(-150)).attr("y",y(100))
	.attr("width",x(150) - x(-150)).attr("height",y(-100) - y(100));

 (1)(2)で変わった部分はdomain範囲のみです。(3)では、作成したスケールを使って、座標(0,0)の位置を求めておきます。そして、(4)ではX軸をy(0)の位置に、(5)ではY軸をx(0)の位置に配置します。(6)ではグリッド用のグループ(g)を作成しています。

 これ以降は、D3の便利機能は使わず、SVGの要素を記述しています。(7)(8)でのグリッド用の縦線と横線を記述するには、SVGでのline要素を使います。このline要素は始点(x1,y1)と終点(x2,y2)を指定して線を描写します。

 そして(9)でデータ領域をすべてカバーする四角形(rect)を用いて描写しています。SVG要素内でも色なども指定できますが、CSSで変更する事が可能ですので、ここではclass属性を使っています。

最後に

 筆者は中学生ぐらいからBASICという言語でプログラミングを始めました。当時は、数学とプログラムの関係について何も感じていませんでした。しかし、高校数学において関数の和を示すΣ(シグマ記号)を学んだ時に、これはプログラムでいうFOR文と同じだと感じました。そのときから、Σを見ると何か分からないルールが「繰り返し」処理されるといったイメージを持つようになりました。

 「詳細はよく理解できないけれど、なんとなくイメージとして分かった気になれる」ことは、プログラムにおいて非常に大切だと思います。特に現在の開発では最初から最後まですべて理解することは不可能になりつつあります。理解できない複雑な部分を自分が知っている簡単なルールに置き換えてイメージすることができれば、データ分析やAIといった難しい処理の応用もわかりやすくなるのではないかと思います。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/21068 2025/03/14 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング