Quelle est la différence entre les données D3 et les données?

199

Quelqu'un peut-il expliquer la différence entre datum () et data () dans D3.js? Je vois que les deux sont utilisés et je ne sais pas pourquoi vous devriez choisir l'un plutôt que l'autre?

josephmisiti
la source

Réponses:

164

J'ai trouvé la bonne réponse ici de Mike lui-même:

D3 - comment gérer les structures de données JSON?

Si vous souhaitez lier vos données à un seul élément SVG, utilisez

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

ou

(...).datum(data)

Si vous souhaitez lier vos données à plusieurs éléments SVG

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

.....

josephmisiti
la source
Merci pour ça! le fait que vous ayez mis des données ([data]) en cours de passage et un tableau m'a aidé à réaliser un bug que je n'ai pas pu découvrir la semaine dernière! Merci beaucoup ... toujours des choses stupides qui ne vont pas.
Adam
22
data () effectue une jointure, datum () non.
s3-4v
Gardez à l'esprit que, s'il existe plus d'éléments de tableau de données que d'éléments SVG lors de la liaison de données avec enter(), d3 liera le reste des éléments du tableau avec les éléments SVG nouvellement créés.
aslantorret
49

Après y avoir examiné un peu, j'ai trouvé que les réponses ici sur SO ne sont pas complètes car elles ne couvrent le cas que lorsque vous invoquez selection.dataet selection.datumavec un dataparamètre d' entrée . Même dans ce scénario, les deux se comportent différemment si la sélection est un seul élément par rapport à lorsqu'elle contient plusieurs éléments. De plus, ces deux méthodes peuvent également être appelées sans aucun argument d'entrée afin d'interroger les données / données liées dans la sélection, auquel cas elles se comportent à nouveau différemment et renvoient des choses différentes.

Edit - J'ai posté une réponse un peu plus détaillée à cette question ici , mais le post ci-dessous capture à peu près tous les points clés concernant les deux méthodes et comment ils diffèrent l'un de l'autre.

Lors de la fourniture data comme argument d'entrée

  • selection.data(data)tentera d'effectuer une données jonction entre les éléments du datatableau avec la sélection aboutissant à la création de enter(), exit()et les update()sélections que vous pouvez ensuite opérer. Le résultat final de ceci est que si vous passez dans un tableau data = [1,2,3], une tentative est faite pour joindre chaque élément de données individuel (c'est-à-dire la donnée) avec la sélection. Chaque élément de la sélection ne sera datalié qu'à un seul élément de référence .

  • selection.datum(data)contourne complètement le processus de jointure de données. Cela affecte simplement l'intégralité de datatous les éléments de la sélection dans son ensemble sans la diviser comme dans le cas des jointures de données. Donc, si vous souhaitez lier un tableau entier data = [1, 2, 3]à chaque élément DOM de votre selection, cela selection.datum(data)sera possible.

Avertissement: Beaucoup de gens pensent que celaselection.datum(data)équivaut àselection.data([data])mais cela n'est vrai que s'il selection contient un seul élément . Siselectioncontient plusieurs éléments DOM, alorsselection.datum(data)liera l'intégralité dedatachaque élément de la sélection. En revanche,selection.data([data])ne lie l'intégralité dudata premier élément deselection. Ceci est cohérent avec le comportement de jointure de données deselection.data.

Lorsque vous ne fournissez aucun dataargument d'entrée

  • selection.data()prendra la donnée liée pour chaque élément de la sélection et les combinera dans un tableau qui est retourné. Donc, si votre selectioncomprend 3 éléments DOM avec les données "a", "b"et "c"lié à chacun respectivement des selection.data()rendements ["a", "b", "c"]. Il est important de noter que si selectionest un élément unique avec (à titre d'exemple) la donnée qui lui est "a"liée, alors selection.data()reviendra ["a"]et pas "a"comme certains peuvent s'y attendre.

  • selection.datum()n'a de sens que pour une seule sélection car elle est définie comme renvoyant la donnée liée au premier élément de la sélection. Donc, dans l'exemple ci-dessus avec la sélection composée d'éléments DOM avec la donnée liée de "a", "b"et "c", selection.datum()reviendrait simplement "a".

Notez que même s'il selectiona un seul élément, selection.datum()et selection.data()retournez des valeurs différentes. La première renvoie la donnée liée pour la sélection ( "a"dans l'exemple ci-dessus) tandis que la seconde renvoie la donnée liée dans un tableau ( ["a"]dans l'exemple ci-dessus).

Espérons que cela aide à clarifier les différences selection.dataet à les selection.datum()différencier à la fois lors de la fourniture de données en tant qu'argument d'entrée et lors de l'interrogation de la donnée liée en ne fournissant aucun argument d'entrée.

PS - La meilleure façon de comprendre comment cela fonctionne est de commencer avec un document HTML vierge dans Chrome et d'ouvrir la console et d'essayer d'ajouter quelques éléments au document, puis de commencer à lier les données à l'aide de selection.dataet selection.datum. Parfois, il est beaucoup plus facile de "grogner" quelque chose en faisant qu'en lisant.

HamsterHuey
la source
HamsterHuey l'a déjà montré, mais il pourrait être utile de rappeler que "datum" est singulier et "data" est pluriel. Par conséquent, .datum s'applique aux informations associées à un seul élément.
Visio Guy
42

Voici quelques bons liens:

Selon ce dernier:

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

Joint le tableau de données spécifié à la sélection actuelle. Les valeurs spécifiées sont un tableau de valeurs de données, tel qu'un tableau de nombres ou d'objets, ou une fonction qui renvoie un tableau de valeurs.

...

# selection.datum([value])

Obtient ou définit les données liées pour chaque élément sélectionné. Contrairement à la méthode selection.data, cette méthode ne calcule pas une jointure (et donc ne calcule pas les sélections d'entrée et de sortie).

paulsm4
la source
11
étant donné ces définitions - je ne comprends toujours pas pourquoi vous auriez besoin / souhaitez utiliser datum ()
josephmisiti
Un autre exemple qui pourrait aider à rendre les choses plus claires: ngokevin.com/blog/d3 . REMARQUES: 1) Définition de Kevin: "La donnée est les données liées à l'élément." 2) Notez comment dans les exemples de Kevin nous "incorporons" l'ensemble de données avec "data ()" ... mais nous "utilisons" un sous-ensemble en référençant un "datum ()".
paulsm4
5

Je pense que l'explication donnée par HamsterHuey est la meilleure jusqu'à présent. Pour le développer et donner une représentation visuelle des différences, j'ai créé un exemple de document qui illustre au moins une partie des différences entre dataet datum.

La réponse ci-dessous est plus une opinion dérivée de l'utilisation de ces méthodes, mais je suis heureux d'être corrigé si je me trompe.

Cet exemple peut être exécuté en dessous ou dans ce violon .

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

Je pense que datumc'est plus simple à comprendre car il ne fait pas de jointure, mais bien sûr cela signifie également qu'il a des cas d'utilisation différents.

Pour moi, une grande différence - bien qu'il y en ait plus - est le fait que datac'est juste la façon naturelle de faire des mises à jour (en direct) sur un graphique d3, car l'ensemble du modèle d'entrée / mise à jour / sortie le rend simple, une fois que vous l'avez obtenu.

datumen revanche me semble plus adapté aux représentations statiques. Dans l'exemple ci-dessous par exemple, je pourrais obtenir le même résultat en bouclant sur le tableau d'origine et en accédant aux données par index comme ceci:

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

Essayez-le ici: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Encore une fois, je pense que c'est beaucoup plus facile à saisir car vous vous libérez de la charge mentale provenant du modèle d'entrée / mise à jour / sortie, mais dès que vous devrez mettre à jour ou modifier la sélection, vous ferez sûrement mieux de recourir à .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>

Nobita
la source