В чем разница между данными D3 и данными?

199

Может кто-нибудь объяснить, пожалуйста, разницу между datum () и data () в D3.js? Я вижу, как используются оба, и я не уверен, почему вы должны выбрать один из других?

josephmisiti
источник

Ответы:

164

Я нашел правильный ответ здесь от самого Майка:

D3 - как бороться со структурами данных JSON?

Если вы хотите привязать ваши данные к одному элементу SVG, используйте

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

или

(...).datum(data)

Если вы хотите связать свои данные с несколькими элементами SVG

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

.....

josephmisiti
источник
Спасибо тебе за это! тот факт, что вы передаете данные ([data]) и массив, просто помог мне понять ошибку, которую я не мог обнаружить за последнюю неделю! Большое вам спасибо ... всегда такие глупые вещи, которые не так.
Адам
22
data () выполняет объединение, datum () - нет.
s3-4v
Просто имейте в виду, что если при связывании данных с массивом данных больше элементов, чем с элементами SVG enter(), d3 свяжет остальные элементы массива с вновь созданными элементами SVG.
Асланторрет
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
источник
HamsterHuey уже показал это, но это может быть полезным напоминанием о том, что «данные» являются единственными, а «данные» - множественными. Следовательно, .datum относится к информации, связанной с одним элементом.
Visio Guy
42

Вот несколько хороших ссылок:

По последнему:

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

Объединяет указанный массив данных с текущим выбором. Указанные значения - это массив значений данных, например, массив чисел или объектов, или функция, которая возвращает массив значений.

...

# selection.datum([value])

Получает или задает связанные данные для каждого выбранного элемента. В отличие от метода selection.data, этот метод не вычисляет соединение (и, следовательно, не вычисляет выборки входа и выхода).

paulsm4
источник
11
учитывая эти определения - я до сих пор не понимаю, зачем вам нужно / хотите использовать datum ()
josephmisiti
Еще один пример, который может помочь, проясняет ситуацию: ngokevin.com/blog/d3 . ЗАМЕЧАНИЯ: 1) Определение Кевина: «Данные - это данные, связанные с элементом». 2) Обратите внимание, как в примерах Кевина мы «объединяем» набор данных с «data ()» ... но мы «используем» подмножество, ссылаясь на «datum ()».
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>

Nobita
источник