I have two javascript functions that generate a D3 Stream graph. I feel I may be excessively and unnecessarily iterating over my dataset to get it into the desired form.How might I optimize or simplify this?     d3.json(/sleeps, function(d) {            sleepStream(d);        });        function sleepStream(d) {            var divheight   = $(document).height()               , divwidth    = $(document).width()              , margin      = { top: 20 , right: 20 , bottom: 20 , left: 10 }              , width       = divwidth - margin.left - margin.right              , height      = (divheight / 8) - margin.top - margin.bottom;            var colorrange  = [#80B2B7, #4B98B1, #1C7BAC, #235AA0, #453485]              , datearray   = []              , strokecolor = '#FFF';            var x = d3.time.scale().range([0, width])              , y = d3.scale.linear().range([height, 0])              , z = d3.scale.ordinal().range(colorrange);            var xAxis = d3.svg.axis()                .scale(x)                .orient(bottom)                .ticks(d3.time.months);            var yAxis = d3.svg.axis().scale(y);            var nest = d3.nest()                .key(function (d) { return d.key; });            /*               * Helper function to extract (subset) Jawbone results.              * Iterates through data and returns desired groups and             * values.             */            function getData(d) {                var _data = [];                var parseDate = d3.time.format(%Y%m%d).parse;                for (var i = 0; i < d.length; i++) {                    var _date = parseDate(d[i].date.toString());                    _data[i] = {                        'date' : _date                         , 'light': Math.round(d[i].details.light / 60)                        // Make it a calculated value due to some dirty data                        // that screws up path vals                        , 'deep' : Math.round((d[i].details.duration - (d[i].details.light + d[i].details.awake)) /60)                        , 'awake': Math.round(d[i].details.awake / 60)                        , 'duration': Math.round(d[i].details.duration / 60)                    };                };                return _data;            };            var tmpdata = getData(d);            var data = [];            /*              * RFORMAT tmpdata JSON FOR D3 STREAM              */            tmpdata.forEach(function (e) {                for (var key in e) {                    if (key !== 'date')                        data.push({                            key: key                            , date: e.date                            , value: e[key]                        });                }            });            /*             * Pad missing values             */            assignDefaultValues(data); //data.forEach(function(d){ console.log(d); });            var stack = d3.layout.stack()                .offset(silhouette)                .values(function (d) { return d.values; })                .x(function (d) { return d.date; })                .y(function (d) { return d.value; });            var layers = stack(nest.entries(data));            var area = d3.svg.area()                .interpolate(basis)                .x(function (d) { return x(d.date); })                .y0(function (d) { return y(d.y0); })                .y1(function (d) { return y(d.y0 + d.y); });            var svg = d3.select(#sleep-stream-chart).append(svg)                .attr(width, width - margin.left - margin.right)                .attr(height, height + margin.top + margin.bottom)                .append(g)                .attr(transform, translate( + margin.left + , + margin.top + ));                x.domain(d3.extent(data, function (d) { return d.date; }));                y.domain([0, d3.max(data, function (d) { return d.y0 + d.y; })]);                svg.selectAll(.layer)                    .data(layers)                    .enter().append(path)                    .attr(class, layer)                    .attr(d, function (d) { return area(d.values); })                    .attr(transform, translate(8, 0))                    .style(fill, function (d, i) { return z(i); });                svg.append(g)                    .attr(class, x axis)                    .attr(transform, translate(8, + height + ))                    .attr(class, axis)                    .attr(fill, #fff)                    .call(xAxis);            var tooltip = d3.select(#sleep-stream-chart)                    .append(div)                    .attr(class, remove)                    .style(position, absolute)                    .style(z-index, 20)                    .style(visibility, hidden)                    .style(top, (height / 2) + px)                    .style(left, (width / 3) + px);            svg.selectAll(.layer)                .attr(opacity, .5)                .on(mouseover, function (d, i) {                    svg.selectAll(.layer).transition()                        .duration(250)                        .attr(opacity, function (d, j) {                            return j != i ? 0.5 : 1;                        })                })                .on(mousemove, function (d, i) {                    mousex = d3.mouse(this);                    mousex = mousex[0];                    var invertedx = x.invert(mousex);                    invertedx = invertedx.getMonth() + invertedx.getDate();                     var selected = (d.values);                    for (var k = 0; k < selected.length; k++) {                        datearray[k] = selected[k].date;                        datearray[k] = datearray[k].getMonth() + datearray[k].getDate();                    }                    _mousedate = datearray.indexOf(invertedx);                    _tmpdate = x.invert(mousex);                    pro = d.values[_mousedate].value;                    d3.select(this)                        .classed(hover, true)                        .attr(stroke, strokecolor)                        .attr(stroke-width, 0.5px);                    tooltip.html(<p> + _tmpdate +   + pro +   + d.key +</p>)                        .style(visibility, visible)                        .style(color, white);                })                .on(mouseout, function (d, i) {                    svg.selectAll(.layer)                        .transition()                        .duration(250)                        .attr(opacity, 1);                    d3.select(this)                        .classed(hover, false)                        .attr(stroke-width, 0px)                    tooltip.html(<p> + _tmpdate +   + pro +   +  d.key +</p>)                        .style(visibility, hidden);                })            /*             * A vertical white bar that tracks horizontal mouse movement.             * It aids visual inspection if substreams by aligning a point             * with the x axis.             */            var vertical = d3.select(#sleep-stream-chart)                .append(div)                .attr(class, remove)                .style(position, absolute)                .style(z-index, 19)                .style(width, 1px)                .style(height, divheight)                .style(top, 10px)                .style(bottom, 0px)                .style(left, 0px)                .style(background, #fff);            d3.select(#sleep-stream-chart)                .on(mousemove, function () {                    mousex = d3.mouse(this);                    vertical.style(left, (mousex[0]) + px)                })                .on(mouseover, function () {                    mousex = d3.mouse(this);                    vertical.style(left, (mousex[0]) + px)                });            /*             * Turn off the Loading Spinner             */            spinner4.stop();        };         function assignDefaultValues(dataset) {            defaultValue = 0;            keys = ['Group1', 'Group2', 'Group3', 'Group4'];            hadData = [true, true, true, true];            newData = [];            previousdate = new Date();            sortByDate = function (a, b) {                return a.date > b.date ? 1 : -1;            };            dataset.sort(sortByDate);            dataset.forEach(function (row) {                if (row.date.valueOf() !== previousdate.valueOf()) {                    for (var i = 0; i < keys.length; ++i) {                        if (hadData[i] === false) {                            newData.push({                                key: keys[i]                                , value: defaultValue                                , date: previousdate                            });                        }                        hadData[i] = false;                    }                    previousdate = row.date;                }                hadData[keys.indexOf(row.key)] = true;            });            for (i = 0; i < keys.length; ++i) {                if (hadData[i] === false) {                    newData.push({                        key: keys[i]                        , value: defaultValue                        , date: previousdate                    });                }            }            return dataset.concat(newData).sort(sortByDate);        }
Optimizing D3 Stream Graph Code
javascript;node.js;json;d3.js