D3基准与数据有何区别?


199

有人可以解释一下D3.js中datum()和data()之间的区别吗?我看到两者都被使用了,我不确定为什么要选择一个?

Answers:


164

我从迈克本人那里找到了正确答案:

D3-如何处理JSON数据结构?

如果要将数据绑定到单个SVG元素,请使用

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

要么

(...).datum(data)

如果要将数据绑定到多个SVG元素

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

.....


这次真是万分感谢!您将data([data])传递给数组和数组的事实帮助我意识到了过去一个星期我一直无法解决的错误!太谢谢你了……总是这样愚蠢的事情是错的。
亚当

22
data()执行联接,datum()不执行联接。
s3-4v 2015年

请记住,如果使用绑定数据时enter(),如果数据数组元素比SVG元素更多,则d3会将其余的数组元素与新创建的SVG元素绑定。
aslantorret

49

经过一番研究之后,我发现SO上的答案还不完整,因为它们仅涵盖调用selection.dataselection.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"分别绑定到每个DOM元素,则selection.data()返回["a", "b", "c"]。重要的是要注意,如果selection是单个元素(例如)"a"绑定了基准,则selection.data()它将返回,["a"]而不是"a"某些预期的那样。

  • selection.datum()仅对单个选择有意义,因为将其定义为返回绑定到选择的第一个元素的基准。因此,在上面的示例中,选择由具有"a""b"和的绑定基准的DOM元素组成"c"selection.datum()将简单地返回"a"

注意,即使selection只有一个元素,selection.datum()selection.data()返回不同的值。前者返回选择的绑定数据("a"在上面的示例中),而后者返回数组内的绑定数据(["a"]在上面的示例中)。

希望这有助于阐明如何selection.dataselection.datum()彼此不同既作为输入参数提供数据时和通过不提供任何输入参数查询结合的基准时。

PS-了解其工作原理的最佳方法是从Chrome中的空白HTML文档开始,打开控制台,尝试向该文档中添加一些元素,然后使用selection.data和开始绑定数据selection.datum。有时候,通过做事“读书”比读书更容易。


HamsterHuey已经显示了这一点,但是提醒您“基准”为单数而“数据”为复数可能会有所帮助。因此,.datum适用于单个元素的关联信息。
Visio Guy

42

这里有一些很好的链接:

对于后者:

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

将指定的数据数组与当前选择连接在一起。指定的值是数据值的数组,例如数字或对象的数组,或者是返回值的数组的函数。

...

# selection.datum([value])

获取或设置每个选定元素的绑定数据。与selection.data方法不同,此方法不计算联接(因此不计算输入和退出选择)。


11
鉴于这些定义-我仍然很困惑为什么您需要/想要使用datum()
josephmisiti 2012年

可能有助于使情况更清晰的另一个示例:ngokevin.com/blog/d3。注意:1)Kevin的定义:“基准是绑定到元素的数据。” 2)请注意在Kevin的示例中,如何将数据集与“ data()”结合起来,但是如何通过引用“ datum()”来“使用”子集。
paulsm4

5

我认为HamsterHuey给出的解释是迄今为止最好的。为了扩展它并给出差异的直观表示,我创建了一个示例文档,该文档至少说明了data和之间的差异datum

以下答案更多是使用这些方法得出的意见,但是如果我错了,我很乐意得到纠正。

该示例可以在下面的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}`)

我认为这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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.