D3.js:计算条形图的x轴时间刻度?
我有以下数据集:D3.js:计算条形图的x轴时间刻度?,d3.js,D3.js,我有以下数据集: 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 } ... ] 我想画一个条形图(用于空气)和
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
} ...
]
我想画一个条形图(用于空气)和线形图(用于能源),如下所示:
我的问题是,目前我使用的x标度,图表看起来是这样的-基本上,条形图位于错误的位置,最后一个条形图从图表上脱落:
下面是一个包含完整代码和工作图的JSFIDLE:
为了达到我想要的效果,我认为我需要修改x比例,以便在第一个数据点之前和最后一个数据点之后有额外的宽度,并且使所有的条都向左移动每个条宽度的一半
有人能帮我弄清楚我需要用x-scale做什么吗
我已经尝试在域中添加一个额外的月份-这会阻止最后一个条从图的末尾脱落,但它也会添加一个我不想要的额外的记号,并且它不会固定线图和记号的位置
如果可能的话,我想继续使用x轴的时间刻度,而不是顺序刻度,因为我想使用D3聪明的基于时间的刻度格式化程序和日期解析器,例如
xAxis.ticks(D3.time.weeks,2)
将您的域从数据的实际范围扩展到+1和-1个月。这将在图表的两侧填充额外的月份,然后更新条形图宽度,使数据元素的计数增加2
var barRawWidth = width / (data.length + 2);
看这把小提琴:
如果你想隐藏上下限月份,你可以这样做:只需加减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);
正如评论中指出的,我认为最好的方法是使用
d3.scale.ordinal
。请注意,使用它并不会阻止您使用d3.time
解析器,但是您需要考虑条的宽度,以便将行与条对齐
下面是一个示例解决方案:
上述解决方案的相关代码如下:
// 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())
...
请注意,在创建x刻度时,日期解析代码已上移,使
d.date
可用。除此之外,d3.time
语句根本没有被修改 我已经有了一个基本的修复,但是(1)它感觉很粗糙,(2)x轴线现在不在它应该去的地方:而且,月份是不同的宽度,正如在这个问题中:修复月份是不同的宽度问题,您应该考虑基于时间戳的月/年部分来创建轴序号,然后使用自定义格式化程序来指定嘀嗒标签。然后,您可以使用范围带来处理条形宽度:这不是有一个很大的缺点,即缺少的值不能在比例中考虑吗?例如,如果我从您的示例数据中删除二月,那么图表将直接从一月到三月。@explunit是的,这是正确的。使用顺序刻度,即使值为0,也需要传递所有数据。