web-dev-qa-db-ja.com

D3データムとデータの違いは何ですか?

誰かがD3.jsのdatum()とdata()の違いを説明できますか?両方が使用されているのがわかりますが、なぜどちらを選択する必要があるのか​​分かりませんか?

183
josephmisiti

マイク自身から正しい答えを見つけました。

D3-JSONデータ構造の処理方法

データを単一のSVG要素にバインドする場合は、使用します

(...).data([data])

または

(...).datum(data)

データを複数のSVG要素にバインドする場合

(...).data(data).enter().append("svg")

.....

155
josephmisiti

ここにいくつかの良いリンクがあります:

後者ごと:

# selection.data([values[, key]])

指定されたデータの配列を現在の選択と結合します。指定された値は、数値やオブジェクトの配列などのデータ値の配列、または値の配列を返す関数です。

...

# selection.datum([value])

選択された各要素の連結データを取得または設定します。 selection.dataメソッドとは異なり、このメソッドは結合を計算しません(したがって、入力および終了選択を計算しません)。

37
paulsm4

これを少し調べた後、SOの答えは、入力dataパラメーターを使用してselection.dataおよびselection.datumを呼び出す場合のみを対象としているため、完全ではないことがわかりました。そのシナリオでも、選択が単一の要素である場合と複数の要素が含まれる場合の2つの動作は異なります。さらに、これらのメソッドの両方は、選択範囲内のバインドされたデータ/データを照会するために入力引数なしで呼び出すこともできます。その場合、これらは再び異なる動作をし、異なるものを返します。

編集-私はこの質問に対するもう少し詳細な答えを投稿しました here 、しかし、以下の投稿は2つの方法とそれらがどのように異なるかに関するすべての重要なポイントをほとんどキャプチャします。

指定時data as 入力引数

  • selection.data(data)は、data配列の要素間でデータ結合を実行しようとしますが、選択するとenter()exit()update()の選択が作成され、それらを後で操作できます。この最終結果は、配列data = [1,2,3]を渡すと、個々のデータ要素(つまりデータム)を選択に結合する試みが行われます。選択の各要素には、dataのデータ要素が1つだけバインドされます。

  • selection.datum(data)は、データ結合プロセスを完全にバイパスします。これは、データ結合の場合のように分割することなく、選択範囲内のすべての要素にdata全体を単に割り当てます。したがって、配列data = [1, 2, 3]selection内のすべてのDOM要素にバインドする場合、selection.datum(data)はこれを実現します。

警告:selection.datum(data)selection.data([data])と同等であると信じていますが、これはselectionの場合にのみ当てはまります単一の要素を含むselectionに複数のDOM要素が含まれている場合、selection.datum(data)は、data全体を選択範囲内のすべての要素にバインドします。対照的に、selection.data([data])data全体をselectionの最初の要素にのみバインドします。これは、selection.dataのデータ結合動作と一致しています。

data入力引数を指定しない場合

  • selection.data()は、選択範囲内の各要素のバインドされたデータを取得し、それらを結合して返される配列にします。したがって、selectionにデータ"a""b"、および"c"がそれぞれバインドされた3つのDOM要素が含まれている場合、selection.data()["a", "b", "c"]を返します。 selectionが(例として)データム"a"がバインドされた単一の要素である場合、selection.data()は一部の人が期待するように["a"]ではなく"a"を返すことに注意することが重要です。

  • selection.datum()は、選択のデータム最初の要素にバインドを返すように定義されているため、単一の選択に対してのみ意味があります。したがって、"a""b"、および"c"のバインドされたデータムを含むDOM要素で構成される選択の上記の例では、selection.datum()は単に"a"を返します。

selectionに単一の要素がある場合でも、selection.datum()selection.data()は異なる値を返すことに注意してください。前者は選択範囲のバインドされたデータム(上の例では"a")を返し、後者は配列内のバインドされたデータム(上の例では["a"])を返します。

これは、入力引数としてデータを提供する場合と、入力引数を提供しないことでバインドされたデータを照会する場合の両方でselection.dataselection.datum()がどのように異なるかを明確にするのに役立ちます。

PS-これがどのように機能するかを理解する最良の方法は、Chromeの空のHTMLドキュメントから開始し、コンソールを開いてドキュメントにいくつかの要素を追加し、selection.dataおよびselection.datumを使用してデータのバインドを開始することです。時々、読むよりも行うことで何かを「グロッキング」する方がずっと簡単です。

34
HamsterHuey

HamsterHueyの説明はこれまでのところ最高だと思います。それを拡張し、違いを視覚的に表現するために、dataname__とdatumname__の違いの少なくとも一部を示すサンプルドキュメントを作成しました。

以下の答えは、これらの方法を使用することから得られた意見の詳細ですが、間違っている場合は修正できてうれしいです。

この例は、以下または このFiddleで で実行できます。

const data = [1,2,3,4,5];
const el = d3.select('#root');

 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node => data: ${d}`);

const join= el
.selectAll('div.b')
.data(data);

join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)

datumname__は結合を行わないため、把握するのが簡単だと思いますが、もちろん、これは異なるユースケースがあることも意味します。

私にとって大きな違いは-さらにありますが、dataname__がd3チャートで(ライブ)更新を行う自然な方法であるという事実です。

一方、datumname__は静的な表現により適しているようです。たとえば、次の例では、元の配列でループし、次のようにインデックスでデータにアクセスすると同じ結果が得られます。

data.map((n, i) => {
 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node-${n} => data: ${d[i]}`);
});

ここで試してください: https://jsfiddle.net/gleezer/e4m6j2d8/6/

繰り返しになりますが、enter/update/exitパターンによる精神的な負担から解放されるので、これは把握しやすいと思いますが、選択を更新または変更する必要があるとすぐに、きっと.data()に頼る方が良いでしょう。

const data = [1,2,3,4,5];
const el = d3.select('#root');

 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node => data: ${d}`);

const join= el
.selectAll('div.b')
.data(data);

join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
/* Ignore all the css */
html {
  font-family: arial;
}

.l {
  width: 20px;
  height: 20px;
  display: inline-block;
  vertical-align: middle;
  margin: 10px 0;
}
.l-a {
  background: #cf58e4;
}
.l-b {
  background:  #42e4e4;
}

.a {
  border-bottom: 2px solid #cf58e4;
}

.b {
  border-bottom: 2px solid #42e4e4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>


<div style="margin-bottom: 20px;">
  <span class="l l-a"></span> .datum() <br />
  <span class="l l-b"></span> .data()
</div>

<div id="root"></div>
1
Nobita