Чим відрізняються дані D3 від даних?


199

Чи можете мені хтось пояснити різницю між даними () та даними () у D3.js? Я бачу, як вони використовуються, і я не впевнений, чому слід вибирати одне над іншим?

Відповіді:


164

Тут я знайшов правильну відповідь від самого Майка:

D3 - як поводитися зі структурами даних JSON?

Якщо ви хочете прив’язати свої дані до одного SVG-елемента, використовуйте

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

або

(...).datum(data)

Якщо ви хочете прив’язати свої дані до декількох елементів SVG

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

.....


Дякую за це! той факт, що ви ввели дані ([дані]), що проходять і масив, просто допоміг мені зрозуміти помилку, яку я не міг зрозуміти за останній тиждень! Дуже дякую ... завжди такі дурні речі, що неправильно.
Адам

22
data () виконує з'єднання, дата () не робить.
s3-4v

Пам’ятайте лише про те, що якщо елементів зв’язку даних більше, ніж елементів SVG, при зв’язуванні даних із enter()d3, d3 зв’яже решту елементів масиву з новоствореними SVG-елементами.
aslantorret

49

Трохи ознайомившись з цим, я виявив, що відповіді тут на SO не є повними, оскільки вони охоплюють випадок лише тоді, коли ви викликаєте selection.dataі selection.datumіз вхідним dataпараметром. Навіть у такому сценарії обидва поводяться по-різному, якщо вибір є одним елементом проти того, коли він містить кілька елементів. Більше того, обидва ці способи можна також викликати без будь-яких вхідних аргументів для того, щоб запитувати пов'язані дані / дані у виборі, і в цьому випадку вони знову поводяться по-різному і повертають різні речі.

Редагувати - я розмістив дещо детальнішу відповідь на це питання тут , але внизу публікація в значній мірі відображає всі ключові моменти щодо двох методів та те, чим вони відрізняються один від одного.

При подачі data як вхідний аргумент

  • selection.data(data)спробує виконати з'єднання даних між елементами dataмасиву з виділенням, що призведе до створення enter(), exit()і update()вибору, над яким ви згодом можете працювати. Кінцевий результат цього полягає в тому, що якщо ви переходите в масив data = [1,2,3], робиться спроба приєднати кожен окремий елемент даних (тобто дату) до вибору. Кожен елемент виділення матиме лише один dataприв'язаний до нього елемент дат .

  • selection.datum(data)взагалі обходить процес з’єднання даних. Це просто присвоює цілість dataвсім елементам відбору в цілому, не розбиваючи його, як у випадку з'єднання даних. Тож якщо ви хочете прив’язати цілий масив data = [1, 2, 3]до кожного елемента DOM у вашому selection, то 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включає 3 DOM-елементи з даними "a", "b"і "c"прив’язаний до кожного відповідно, selection.data()повертається ["a", "b", "c"]. Важливо зауважити, що якщо selectionодин елемент із (на прикладі) "a"прив’язаним до нього датою , то selection.data()він повернеться, ["a"]а не так, "a"як деякі можуть очікувати.

  • selection.datum()має сенс для одного вибору, оскільки він визначається як повернення даної, прив'язаної до першого елемента виділення. Так у наведеному вище прикладі з виділенням, що складається з елементів DOM із зв'язаною датою "a", "b"і "c", selection.datum()просто повернеться "a".

Зауважте, що навіть якщо selectionє один елемент, selection.datum()і selection.data()повертайте різні значення. Перший повертає зв'язану дату для вибору ( "a"у прикладі вище), тоді як другий повертає зв'язану дату в масиві ( ["a"]у прикладі вище).

Сподіваємось, це допомагає з’ясувати, як selection.dataі чим selection.datum()відрізняються один від одного як при наданні даних у якості вхідного аргументу, так і при запиті на зв'язану дату, не надаючи жодних вхідних аргументів.

PS - Найкращий спосіб зрозуміти, як це працює - це почати з чистого HTML-документа в Chrome і відкрити консоль і спробувати додати в документ кілька елементів, а потім почати прив'язування даних за допомогою selection.dataта selection.datum. Іноді набагато простіше "обмацувати" щось, роблячи, ніж читаючи.


HamsterHuey вже показав це, але це може бути корисним нагадуванням нагадати, що "дата" є одниною, а "дані" - множиною. Отже .datum застосовується до інформації, пов'язаної з одним елементом.
Visio Guy

42

Ось кілька хороших посилань:

За останнім:

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

Поєднує вказаний масив даних із поточним виділенням. Зазначені значення - це масив значень даних, наприклад масив чисел чи об'єктів, або функція, яка повертає масив значень.

...

# selection.datum([value])

Отримує або встановлює зв'язані дані для кожного вибраного елемента. На відміну від методу select.data, цей метод не обчислює з'єднання (і, таким чином, не обчислює вибір входу та виходу).


11
з огляду на ці визначення - я все ще плутаюсь, чому вам коли-небудь знадобиться / хочете використовувати
date

Ще один приклад, який може допомогти зробити речі зрозумілішими: ngokevin.com/blog/d3 . ПРИМІТКИ: 1) Визначення Кевіна: "Дані - це дані, прив'язані до елемента". 2) Зауважте, як у прикладах Кевіна ми "включаємо" набір даних із "data ()" ... але ми "використовуємо" підмножину шляхом посилання на "date ()".
paulsm4

5

Я думаю, що пояснення, які дав HamsterHuey, є найкращим до цих пір. Щоб розширити його і надати наочне зображення відмінностей, я створив зразок документа, який ілюструє принаймні частину відмінностей між dataі datum.

Нижченаведена відповідь - це більше думка, отримана завдяки використанню цих методів, але я рада, що мене виправлять, якщо я помиляюся.

Цей приклад можна запустити нижче або в цій скрипці .

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

Я думаю, що datumце простіше зрозуміти, оскільки він не робить з'єднання, але, звичайно, це також означає, що у нього є різні випадки використання.

Для мене одна велика різниця - хоча є і більше - це той факт, що dataце лише природний спосіб робити (в прямому ефірі) оновлення діаграми d3, оскільки вся схема введення / оновлення / виходу робить її простою, як тільки ви її отримаєте.

datumз іншого боку, мені здається, більше підходить для статичних зображень. У наведеному нижче прикладі, наприклад, я міг досягти такого ж результату, коли я переходив до оригінального масиву та отримував доступ до даних за таким індексом:

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/

Знову ж таки, я вважаю, що це легше зрозуміти, оскільки ви позбавитесь від психічного тягаря, що випливає з шаблону введення / оновлення / виходу, але як тільки вам доведеться оновити або змінити вибір, вам, безумовно, буде краще вдаватися .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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.