2

我有嵌套数据,如下:

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 中的嵌套数据教程有任何建议,我很高兴听到这些建议。我发现的那些建议除了将它们用于图表之外,还处理了每个主题)

4

2 回答 2

2

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

在您的示例中,您将数组 ( d.values) 传递给绘图原语。这不适用于圆,因为它需要一个基准。在这种情况下,您需要的是嵌套选择,为属于同一“行”的圆圈引入分组元素。代码看起来像这样。

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代表 的元素的 s 进行子选择d.values。之后,代码再次简单明了,circle附加了 s 并以通常的方式配置。

一般来说,嵌套数据用于图表的方式高度依赖于特定的图表——可折叠树弦图不同。嵌套选择的教程值得一读,但在这种特殊情况下,这并不是嵌套数据的问题,而是不同图形元素所代表的不同事物的问题。

于 2013-11-03T11:15:18.470 回答
1

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

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

在这个辅助对象上,可以设置xy访问器,它们将决定构成线的点xy点。此对象还允许您设置线的许多其他属性(例如您想要哪种插值)。最后,这个帮助对象可以作为一个函数调用data,它将生成d路径属性所需的 DSL。

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

注意:当您再次分配调用结果时,您将覆盖line变量line。如果你这样做,JSHint 会警告你。

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

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实际上是一个date对象而不是数字,那么您可以使用time比例将其转换为漂亮的数字。

于 2013-11-03T11:16:45.277 回答