0

I am building a simple bar chart with d3.time.scale:

var data = [
    {"date": new Date("1992-05-01 00:00:00"), "value": 10}, 
    {"date": new Date("1997-05-01 00:00:00"), "value": 110}, 
    {"date": new Date("2007-05-11 00:00:00"), "value": 34}
];

var width =  300;
var height = 200;
var barWidth = width / data.length;

var x_domain = d3.extent(data, function(d) { return d.date; });

var x = d3.time.scale()
                   .domain(x_domain) 
                   .rangeRound([0, width]);

var y = d3.scale.linear()
                .domain([0, d3.max(data, function(d) { return d.value; })])
                .range([height, 0]);

var chart = d3.select(".chart")
              .attr("width", width )
              .attr("height", height )            
              .append("g")
              .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; });

var bar = chart.selectAll("g")
               .data(data)
               .enter().append("g")
               .attr("transform", function(d, i) { 
                 return "translate(" + i * barWidth + ",0)"; 
               });

bar.append("rect")
    .attr("class", "bar")
    .attr("y", function(d) { 
        return y(d.value);
    })
    .attr("height", function(d) { 
      return height - y(d.value);
    })
    .attr("width", barWidth - 1);

JSFiddle here.

One bar per date-value couple - simple. I would like to generate the dates between each one of them and assign them a 0 value. What would be the best way to do this?

Any help is welcome

pour toi
  • 1,026
  • 2
  • 13
  • 25

1 Answers1

1

Filling in the missing dates is easy, just straight javascript. Something like:

function addDays(date, days) {
    var result = new Date(date);
    result.setDate(date.getDate() + days);
    return result;
}
function fillInDates(data){
    // put current data hash for efficient retrieval
    // determine min/max of data
    var currentDates = {};
    var maxDate = new Date(-1e15);
    var minDate = new Date(1e15);
    for (var i = 0; i <= data.length; i++){
        if (data[i]['date'] > maxDate){
            maxDate =  data[i]['date'];
        }
        if (data[i]['date'] < minDate){
            minDate = data[i]['date'];
        }
        currentDates[data[i]['date']]= data[i]['value'];
    }
    // loop data and fill in missing dates
    var filledInDates = [];
    while (minDate < maxDate){
        filledInDates.push({"date":minDate, "value":currentDates[minDate] ? currentDates[minDate] : 0});  
        minDate = addDays(minDate, 1);
    }
    return filledInDates;              
}

Note addDays function from here.

Getting d3 to plot this though is a different story. You now have 5488 bars, in order for the math to work (to get bar widths that > 0), you need to increase the plot width to 10,000 pixels.

See updated fiddle.

Community
  • 1
  • 1
Mark
  • 106,305
  • 20
  • 172
  • 230