Qual è la differenza D3 datum vs data?


199

Qualcuno può spiegare la differenza tra datum () e data () in D3.js? Vedo entrambi in uso e non sono sicuro del motivo per cui dovresti scegliere uno rispetto all'altro?

Risposte:


164

Ho trovato la risposta corretta qui dallo stesso Mike:

D3 - come gestire le strutture dati JSON?

Se si desidera associare i dati a un singolo elemento SVG, utilizzare

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

o

(...).datum(data)

Se si desidera associare i dati a più elementi SVG

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

.....


Grazie per questo! il fatto che tu abbia inserito dati ([data]) e array mi ha aiutato a realizzare un bug che non sono riuscito a capire la scorsa settimana! Grazie mille ... sempre cose così stupide che sono sbagliate.
Adam,

22
data () esegue un join, datum () no.
s3-4v,

Tieni a mente, nel caso in cui ci siano più elementi dell'array di dati rispetto agli elementi SVG quando si associano i dati con enter(), d3 collegherà il resto degli elementi dell'array con elementi SVG appena creati.
aslantorret,

49

Dopo aver esaminato un po 'questo, ho scoperto che le risposte qui su SO non sono complete in quanto coprono il caso solo quando invochi selection.datae selection.datumcon un dataparametro di input . Anche in quello scenario, i due si comportano diversamente se la selezione è un singolo elemento rispetto a quando contiene più elementi. Inoltre, entrambi questi metodi possono anche essere invocati senza alcun argomento di input al fine di interrogare i dati / datum associati nella selezione, nel qual caso si comportano nuovamente in modo diverso e restituiscono cose diverse.

Edit - Ho inviato una risposta un po 'più dettagliata a questa domanda qui , ma il post qui sotto praticamente cattura tutti i punti chiave per quanto riguarda i due metodi e come si differenziano gli uni dagli altri.

Quando si fornisce data come argomento di input

  • selection.data(data)tenterà di eseguire un data-giunzione tra gli elementi della datamatrice con la selezione conseguente creazione di enter(), exit()e update()selezioni che si può successivamente operare. Il risultato finale di questo è se si passa in un array data = [1,2,3], si tenta di unire ogni singolo elemento di dati (cioè datum) con la selezione. Ogni elemento della selezione avrà solo un singolo elemento di riferimento dataassociato ad esso.

  • selection.datum(data)ignora del tutto il processo di unione dei dati. Ciò assegna semplicemente l'insieme dataa tutti gli elementi della selezione nel suo insieme senza dividerlo come nel caso dei join di dati. Quindi, se vuoi associare un intero array data = [1, 2, 3]ad ogni elemento DOM nel tuo selection, allora selection.datum(data)raggiungerai questo obiettivo.

Avvertenza: molte persone credono cheselection.datum(data)sia equivalenteselection.data([data])ma questo è vero solo se selection contiene un singolo elemento . Seselectioncontiene più elementi DOM,selection.datum(data)associerà l'interodataa ogni singolo elemento nella selezione. Al contrario,selection.data([data])lega solo l'interodata al primo elemento inselection. Ciò è coerente con il comportamento di unione dei dati diselection.data.

Quando non viene fornito alcun dataargomento di input

  • selection.data()prenderà il dato associato per ciascun elemento nella selezione e li combinerà in un array che viene restituito. Quindi, se il vostro selectioncomprende 3 elementi DOM con i dati "a", "b"e "c"tenuto a ciascun rispettivamente selection.data()i rendimenti ["a", "b", "c"]. È importante notare che se selectionè un singolo elemento con (a titolo esemplificativo) il dato "a"associato ad esso, allora selection.data()ritornerà ["a"]e non "a"come alcuni potrebbero aspettarsi.

  • selection.datum()ha senso solo per una singola selezione in quanto è definita come la restituzione del riferimento associato al primo elemento della selezione. Quindi nell'esempio sopra con la selezione composta da elementi DOM con dato associato di "a", "b"e "c", selection.datum()ritornerebbe semplicemente "a".

Si noti che anche se selectionha un singolo elemento selection.datum()e selection.data()restituisce valori diversi. Il primo restituisce il dato associato per la selezione ( "a"nell'esempio sopra) mentre il secondo restituisce il dato associato all'interno di un array ( ["a"]nell'esempio sopra).

Si spera che ciò aiuti a chiarire come selection.datae selection.datum()differire l'uno dall'altro sia quando si forniscono dati come argomento di input sia quando si esegue una query per l'origine associata non fornendo alcun argomento di input.

PS: il modo migliore per capire come funziona è iniziare con un documento HTML vuoto in Chrome e aprire la console e provare ad aggiungere alcuni elementi al documento e quindi iniziare a legare i dati usando selection.datae selection.datum. A volte, è molto più facile "brontolare" qualcosa facendo piuttosto che leggendo.


HamsterHuey lo ha già dimostrato, ma potrebbe essere un utile promemoria per ricordare che "datum" è singolare e "data" è plurale. Quindi .datum si applica alle informazioni associate a un singolo elemento.
Visio Guy,

42

Ecco alcuni buoni link:

Per quest'ultimo:

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

Unisce la matrice di dati specificata con la selezione corrente. I valori specificati sono una matrice di valori di dati, ad esempio una matrice di numeri o oggetti o una funzione che restituisce una matrice di valori.

...

# selection.datum([value])

Ottiene o imposta i dati associati per ciascun elemento selezionato. A differenza del metodo selection.data, questo metodo non calcola un join (e quindi non calcola le selezioni di entrata e uscita).


11
date quelle definizioni - sono ancora confuso perché mai avresti bisogno / vuoi usare datum ()
josephmisiti,

Un altro esempio che potrebbe aiutare a chiarire le cose: ngokevin.com/blog/d3 . NOTE: 1) Definizione di Kevin: "Il dato è il dato associato all'elemento." 2) Nota come negli esempi di Kevin "incorporiamo" il set di dati con "data ()" ... ma "utilizziamo" un sottoinsieme facendo riferimento a "datum ()".
paulsm4,

5

Penso che la spiegazione fornita da HamsterHuey sia la migliore finora. Per espanderlo e dare una rappresentazione visiva delle differenze, ho creato un documento di esempio che illustra almeno parte delle differenze tra datae datum.

La risposta che segue è più un'opinione derivata dall'uso di questi metodi, ma sono felice di essere corretto se sbaglio.

Questo esempio può essere eseguito sotto o in questo violino .

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}`)

penso che datum sia più semplice da capire poiché non fa un join, ma ovviamente questo significa anche che ha diversi casi d'uso.

Per me una grande differenza - anche se ce ne sono altre - è il fatto che dataè solo il modo naturale di fare (live) aggiornamenti su un grafico d3, poiché l'intero schema enter / update / exit lo rende semplice, una volta ottenuto.

datumd'altra parte mi sembra più adatto per le rappresentazioni statiche. Nell'esempio seguente, ad esempio, ho potuto ottenere lo stesso risultato il mio looping sull'array originale e l'accesso ai dati per indice in questo modo:

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

Provalo qui: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Ancora una volta, penso che questo sia molto più facile da capire mentre ti liberi dall'onere mentale derivante dal modello di invio / aggiornamento / uscita, ma non appena dovrai aggiornare o modificare la selezione, sarà sicuramente meglio ricorrere a .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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.