访问嵌套数据以创建图表

时间:2013-11-03 10:26:45

标签: javascript d3.js

我有嵌套数据,如下所示:

data  
    > key
    > values
       > date
       > reldif
       > absdif

线图中一切正常:

var line = svg.selectAll(".lines")
  .data(data, function(d) { return d.key; })
  .enter()
  .append("g")
  .attr("class", "lines")
  .append("path")
  .attr("class", "line")
  .attr("d", function(d) { return line(d.values); })
  .style("stroke", function(d) { return color(d.key); })
  .style("stroke-width", 4)

然而,尝试对圆圈使用相同的技术,我失败了。据我所知,我需要x,y和r(可以是绝对的,就像5左右)。 X应该是日期,Y应该是reldif。我如何访问这些值?如果我只是使用d.values它会移交一个我无法用这种方式处理的数组。

(一般情况下 - 如果您对D3中嵌套数据的教程有任何建议,我很高兴听到这些建议。我发现除了将它们用于图表之外的所有主题)

2 个答案:

答案 0 :(得分:2)

线条和圆圈之间存在根本区别 - 线条代表点的集合,而圆圈代表单个点。实际上,这意味着用于创建线的数据元素是一个数组,而它只是一个圆的单个数据点。

在您的示例中,您将数组(d.values)传递给绘图基元。这对圆圈不起作用,因为它需要单个数据。你需要的是nested selections,它为属于同一“行”的圆圈引入了一个分组元素。代码看起来像这样。

svg.selectAll("g")
   .data(data, function(d) { return d.key; })
   .enter()
   .append("g")
   .selectAll("circle")
   .data(function(d) { return d.values; })
   .enter()
   .append("circle")
   .attr("cx", function(d) { return x(d.date); })
   // etc

代码的第一部分是相同的,但在添加g元素后,您正在为代表circle元素的d.values进行子选择。之后,代码很简单,并且以通常的方式附加circle并进行配置。

一般情况下,嵌套数据用于图表的方式高度依赖于特定图表 - collapsible treechord diagram不同。有关嵌套选择的教程值得一读,但在这种特殊情况下,它不是嵌套数据的问题,而是不同图形元素所代表的不同问题。

答案 1 :(得分:1)

要处理嵌套数据,您可以创建nested selections。这里令人困惑的是lines不需要任何嵌套选择。

这种绘制线条的方式在D3中有点特殊,因为它是使用path SVG元素绘制的。 path元素有一个属性d accepts a DSL。这个字符串有点麻烦,因此D3提供了辅助对象d3.svg.line

在此辅助对象上,可以设置x and y accessors,它将决定构成该行的xy点。此对象还允许您设置线的许多其他属性(如您想要的插值类型)。最后,可以将此辅助对象称为函数data,它将生成路径的d属性所需的DSL。

这是您在此处粘贴的示例中使用的方式:.attr("d", function(d) { return line(d.values); })。在之前的某个地方,此line对象是通过调用d3.svg.line创建的,可能x访问者设置为.x(function (d) { return d.date; })y访问者设置为{{1 }}

注意:当您再次分配呼叫结果.y(function (d) { return d.reldif; }时,您将覆盖line变量。如果你这样做,JSHint会警告你。

现在line元素相当简单。在这里,您不需要任何辅助函数,因为正如您所指出的,您可以直接设置circlexy属性而无需中间DSL。因此,你会看起来像这样:

r

如果var circles = svg.selectAll(".circles") .data(data, function(d) { return d.key; }) .enter() .append("g") .attr("class", "circles") .selectAll(".circle") .data(function (d) { return d.values; }) .enter() .append("circle") .attr("class", "circle") .attr("cx", function(d) { return d.date; }) .attr("cy", function(d) { return d.reldif; }) .attr("r", 5) .style("stroke", function(d) { return color(d.key); }) .style("stroke-width", 4) 实际上是d.values.date个对象而不是数字,那么您可以使用time scale将其转换为不错的数字。