3

我有以下数据集:

var data = [
  {
    "air_used": 0.660985, 
    "datestr": "2012-12-01 00:00:00", 
    "energy_used": 0.106402
  }, 
  {
    "air_used": 0.824746, 
    "datestr": "2013-01-01 00:00:00", 
    "energy_used": 0.250462
  } ...
]

我想绘制一个条形图(用于 air_used)和折线图(用于 energy_used),如下所示:

在此处输入图像描述

我的问题是,目前,使用我使用的 x 比例,图表看起来像这样 - 基本上条形图的位置错误,最后一个条形图从图表上掉下来:

在此处输入图像描述

这是一个带有完整代码和工作图的 JSFiddle:http: //jsfiddle.net/aWJtJ/4/

为了实现我想要的,我我需要修改 x 比例,以便在第一个数据点之前和最后一个数据点之后有额外的宽度,并且条形图都向左移动了一半的宽度每个酒吧。

谁能帮我弄清楚我需要用 x-scale 做什么?

我已经尝试在域中添加一个额外的月份 - 这可以阻止最后一个条从图表的末尾掉下来,但它也添加了一个我不想要的额外刻度,并且它不能修复线的位置图表和刻度。

如果可能的话,我想继续使用 x 轴的时间刻度,而不是序数刻度,因为我想使用 D3 聪明的基于时间的刻度格式化程序和日期解析器,例如xAxis.ticks(d3.time.weeks, 2).

4

2 回答 2

4

将您的域从您的数据的实际范围扩展到 +1 和 -1 个月。这将在图表的任一侧用额外的月份填充,然后更新条形宽度以将 2 添加到数据元素的计数中。

var barRawWidth = width / (data.length + 2);

看到这个小提琴:http: //jsfiddle.net/reblace/aWJtJ/6/

如果你想隐藏上下边界月份,你可以像这样破解它:http: //jsfiddle.net/reblace/aWJtJ/7/只需加减 20 天而不是整个月,但可能有更优雅的方式来做到这一点。

var xExtent = d3.extent(data, function(d) { return d.date; });
var nxExtent = [d3.time.day.offset(xExtent[0], -20), d3.time.day.offset(xExtent[1], 20)];
x.domain(nxExtent);
于 2013-09-17T16:17:43.467 回答
0

正如评论中所指出的,我认为最好的方法是使用d3.scale.ordinal. 请注意,使用它不会阻止您使用d3.time解析器,但您需要考虑条形宽度以将线条与条形对齐。

一个示例解决方案在这里:http: //jsfiddle.net/jcollado/N8tuR/

上述解决方案的相关代码如下:

// Map data set to dates to provide the whole domain information
var x = d3.scale.ordinal()
    .domain(data.map(function(d) {
        return d.date;
    }))
    .rangeRoundBands([0, width], 0.1);

...

// Use x.rangeBand() to align line with bars
var line = d3.svg.line()
    .x(function(d) { return x(d.date) + x.rangeBand() / 2; })
    .y(function(d) { return y(d.energy_used); });

...

// Use x.rangeBand() to set bar width
bars.enter().append("rect")
    .attr("class", "air_used")
    .attr("width", x.rangeBand())
    ...

请注意,日期解析代码已上移,以便d.date在创建 x 比例时可用。除此之外,d3.time声明根本没有被修改。

于 2014-02-20T12:49:51.300 回答