selection.data - データを関連付ける

投稿日: / 更新日:

d3.jsのselection.data()は、要素にデータをまとめて関連付けるためのAPIです。

サンプルコード

<ul>
	<li>1つ目のLI</li>
	<li>2つ目のLI</li>
	<li>3つ目のLI</li>
	<li>4つ目のLI</li>
	<li>5つ目のLI</li>
</ul>
// 全てのli要素を選択 (5個)
d3.selectAll( "li" )

// 選択したd3.selectionオブジェクトにデータ(配列)を関連付ける (5個分)
.data( [ "1個目のLI", "2個目のLI", "3個目のLI", "4個目のLI", "5個目のLI" ] )

// 各li要素のテキストを、関連付けたデータに応じて変更する
.text( function(d) { return d ; } ) ;

デモ

仕組み

まずは、全てのli要素をselectAll()を使って選択状態にします。d3.selectionオブジェクト(selection)の中には、5個のli要素が含まれます。

<ul>
	<li>1つ目のLI</li>
	<li>2つ目のLI</li>
	<li>3つ目のLI</li>
	<li>4つ目のLI</li>
	<li>5つ目のLI</li>
</ul>
// 全てのli要素を選択 (5個)
var selection = d3.selectAll( "li" ) ;

次に、data()に配列を指定して、その配列をd3.selectionオブジェクトの各要素に関連付けます。li要素が5個含まれているので、ここでは5つの要素を持った配列を指定しました。ここまでがdata()の役割です。配列を使って、複数の要素にまとめてデータを関連付けられるのがdata()なんです。逆に個別の要素にデータを関連付けたいなら、datum()というメソッドを使って下さい。

// 選択したd3.selectionオブジェクトの各要素にデータ(配列)を関連付ける
selection.data( [ "1個目のLI", "2個目のLI", "3個目のLI", "4個目のLI", "5個目のLI" ] ) ;

// 次のようにデータが関連付けられた
// <li>1つ目のLI</li> = 1個目のLI
// <li>2つ目のLI</li> = 2個目のLI
// <li>3つ目のLI</li> = 3個目のLI
// <li>4つ目のLI</li> = 4個目のLI
// <li>5つ目のLI</li> = 5個目のLI

さて、関連付けられたデータは一体どのように活用できるのか、確認しておきましょう。5つのli要素に対して何らかの処理をします。ここでは、テキストを変更するtext()というメソッドを使いましょう。

// text()でテキストを変更する
selection.text() ;

text()は引数を指定しないとダメですよね。例えば、次のように引数に文字列を指定した場合、どうなるでしょう?答えは、5個のli要素のテキストがみんなSYNCERになります。

// 引数に文字列を指定する
selection.text( "SYNCER" ) ;

それでは、文字列ではなく関数を指定するとどうなるでしょう?答えは、その関数の戻り値が、text()の引数として指定される、です。下記の場合、関数の戻り値はSYNCERなので、先ほどと同じく、5個のli要素のテキストがみんなSYNCERになりますね。

// 引数に関数を指定する
selection.text( function() { return "SYNCER" ; } ) ;

ここが肝です。この関数は何回実行されるでしょう?答えは5回です。d3.selectionオブジェクトの中身(li要素)が5個あるからですね。最初のli要素から、最後のli要素まで、順々に関数を実行していくわけです。曖昧に「関数が全部のli要素に反映される」という捉え方ではなく、「各要素に1回ずつ関数が実行される」というのを強くイメージして下さい。

// 引数に関数を指定する
selection.text( function() { return "SYNCER" ; } ) ;

// 1個目のli要素に対して
function() { return "SYNCER" ; }

// 2個目のli要素に対して
function() { return "SYNCER" ; }

// 3個目のli要素に対して
function() { return "SYNCER" ; }

// 4個目のli要素に対して
function() { return "SYNCER" ; }

// 5個目のli要素に対して
function() { return "SYNCER" ; }

この関数は2つの引数をとります。その1つ目の引数が肝心のdata()でその要素に関連付けた値なんです。2つ目の引数はインデックス番号です。インデックス番号というのは、d3.selectionオブジェクトにおけるその要素の順番、位置ですね。テキストだと分かりにくいですが、下記を見ればピンとくるはずです。このように、data()で要素に関連付けられた値を関数で利用できるわけです。

// 引数に関数を指定する
selection.text( function( d, i ) {
	// d=その要素に関連付けられたデータ
	// i=インデックス番号
	// this=要素

	return d ;
} ) ;

// 1個目のli要素に対して
function( d, i ) {
	// d="1個目のLI"
	// i=0
}

// 2個目のli要素に対して
function( d, i ) {
	// d="2個目のLI"
	// i=1
}

// 3個目のli要素に対して
function( d, i ) {
	// d="3個目のLI"
	// i=2
}

// 4個目のli要素に対して
function( d, i ) {
	// d="4個目のLI"
	// i=3
}

// 5個目のli要素に対して
function( d, i ) {
	// d="5個目のLI"
	// i=4
}

つまり、次のように関数を指定することで、各要素に関連付いたデータを元に、別々の値を振り分けることができるんです。

// 引数に文字列を指定する
selection.text( function( d, i ) { return d ; } ) ;

// この章の例の場合、下記のように応用もできます
// selection.text( function( d, i ) { return ( i + 1 ) + "個目のLI" ; } ) ;

// li要素は次のように変わるでしょう
// <ul>
//	<li>1個目のLI</li>
//	<li>2個目のLI</li>
//	<li>3個目のLI</li>
//	<li>4個目のLI</li>
//	<li>5個目のLI</li>
// </ul>

高度な応用として、data()に指定する1つ1つの値を配列、またはオブジェクトリテラルにすることで、1つ1つの要素に複数の値を組み合わせて指定していくことができます。例えば、style()で背景色をランダムに変更する場合を考えてみましょう。下記のように1つ1つの値を配列に指定すれば、1個目は「赤か青」、2個目は「緑かピンク」、3個目は「紫か珊瑚色」というように、別々に背景色を変えることができます。

// 全てのli要素を選択 (5個)
var selection = d3.selectAll( "li" ) ;

// 配列を関連付ける
selection.data( [
	[ "red", "blue" ] ,	// 1個目のli要素に関連付ける
	[ "green", "pink" ] ,	// 2個目のli要素に関連付ける
	[ "purple", "coral" ] ,	// 3個目のli要素に関連付ける
	[ "brown", "black" ] ,	// 4個目のli要素に関連付ける
	[ "cyan", "orangered" ]	// 5個目のli要素に関連付ける
] ) ;

// スタイルを変更
selection.style( "background", function( d, i ) {
	// 1個目のli要素の場合
	// d=[ "red", "blue" ]
	// i=0

	// d3.shuffle()は、引数に指定した配列をシャッフルするメソッドです
	// シャッフルした後の第1要素を戻り値に指定しています
	return d3.shuffle( d )[0] ;
} ) ;

このコードを確認する

構文

selection = selection.data( dataSet [, function] )
引数
項目説明
dataSet第1引数に、関連付けたいデータを配列で指定する。
function省略可。第2引数に関数を指定すると、この直前の別のdata()を引数にした関数が実行される。2016年3月現在、活用方法が分からなかったので説明ができません。ご了承下さい。
戻り値
項目説明
selectionデータを関連付けたd3.selectionオブジェクトが戻り値となる。