2013-11-14 48 views
3

我需要使用d3.js库建立直方图。直方图应该看起来像下面那样。这个直方图的主要目的是比较两组结果。下图显示的结果代表在一个月的同一天收集的数据,但是在两个不同的月份(例如1月1日 - 6日(绿色)和2月(蓝色))收集。多层比较直方图

我目前所拥有的直方图基本上显示了正确的数据,只是它没有覆盖它们(或者甚至并排显示它们)。相反,它显示他们按日期排序,结果代表1月的第一个(左边),以及代表2月第二个(右边)的结果。我应该怎么做才能让它们并排展示?

编辑:我在Angular环境下工作,并使用预构建指令来显示图形。

desired chart

当前的结果:

current chart

+0

你可以发布你的代码吗? –

+0

我已经更新了这个问题。我在Angular环境中工作,并使用预先构建的指令来显示图形。该指令的代码位于https://github.com/fullscale/dangle/blob/master/dist/dangle.datehisto.js 我特别会至少想知道这是否可能,使用d3。 –

+0

这当然有可能。你已经发布了脚本的实际输出结果吗?它看起来不会对我产生这种感觉。特别是,我没有看到任何可以将两组小节添加到同一个SVG的东西。 –

回答

2

这里的问题是,你正在使用的时间尺度时,它的指令代码在https://github.com/fullscale/dangle/blob/master/dist/dangle.datehisto.js

期望的结果是lcoated对于你想要做的事情应该是线性的。您不希望x偏移量根据实际日期/时间增加,而是仅在日期的date.getDate()部分。假设d.time与new Date().getTime()表示相同的东西,那么您可以将您的比例更改为线性,并仅使用该日加上本月的偏移量来确定x值。这将需要你建立某种形式的图例来表明月份。

首先改变我们使用的是规模:

// create x,y scales (x is inferred as time) 
// var x = d3.time.scale() 
// .range([0, width]); 
// 
// Use linear scale since we really care about the day portion of the date/time 
var x = d3.scale.linear() 
     .range([0, width]); 

然后计算出我们的月和日范围:

// Get the range of months so we can use the month 
// to offset the x value for overlay 
var monthExtent = d3.extent(data,function(d) { 
      var date = new Date(); 
      date.setTime(d.time.getTime()); 
      return date.getMonth(); 
     }); 

// Get the range of days for the graph 
// If you always want to display the whole month 
// var dateExtent = [0,31] 
// 
// Otherwise calculate the range 
var dateExtent = d3.extent(data,function(d) { 
      var date = new Date(); 
      date.setTime(d.time.getTime()); 
      return date.getDate(); 
     }); 

然后设置x域给我们的日子范围:

// recalculate the x and y domains based on the new data. 
// we have to add our "interval" to the max otherwise 
// we don't have enough room to draw the last bar. 
// 
//x.domain([ 
// d3.min(data, function(d) { 
//  return d.time; 
// }), 
// d3.max(data, function(d) { 
//  return d.time; 
// }) 
//]); 


// Our x domain is just the range of days 
x.domain(dateExtent); 

添加色标以区分月份:

// Set up a color scale to separate months 
var color = d3.scale.category10(); 

现在,将x属性更改为使用日期值加上月份的偏移量来创建叠加层。我在这里使用了20个像素,但是您可以轻松地将其更改为相对于条宽度的百分比。然后使用月份和颜色比例添加填充属性,以便每个月都获得它自己的颜色。

bars.enter() 
    .append('rect') 
     .attr('class', 'histo rect ') 
     .attr('cursor', 'pointer') 
     .attr('x', function(d) { 
      // Extract the day portion of the date/time 
      // and then offset the rect by it's month value 
      var date = new Date(); 
      date.setTime(d.time.getTime()); 
      return x(date.getDate()) + (date.getMonth() - monthExtent[0]) * 20; 
     }) 
     .attr("fill",function(d) { 
      var date = new Date(); 
      date.setTime(d.time); 
      return color(date.getMonth()); 
     }) 
     .attr("y", function(d) { return height }) 
     .attr('width', barWidth) 
     .transition() 
      .delay(function (d,i){ return i * 0; }) 
      .duration(500) 
       .attr('height', function(d) { return height - y(d.count); }) 
       .attr('y', function(d) { return y(d.count); }); 

最后,您可能必须更改barWidth的计算方式,以确保每天之间有适当的空间量。希望这有助于!