2016-07-24 9 views
0

Wo ich am meisten mit D3 kämpfe ist die richtige Datenmanipulation, bevor ich es in bestehende Modelle einstecke. Ich versuche herauszufinden, wie wenig Datenmanipulation erforderlich ist, um ein grundlegendes D3-Flächendiagramm mit einer zeitbasierten X-Achse zu erstellen. Ich beginne mit einem JSON-Array von Objekten mit einer date Schlüssel- und Date-Objekteigenschaft zusammen mit mehreren anderen Schlüssel/Wert-Paaren, um das Diagramm zu füllen.Richtige Manipulation von JSON-Daten, um D3-Flächendiagramm zu erstellen?

Zum Beispiel:

[{date: Wed Jul 20 2016 00:00:00 GMT-1000 (HST), a: 5, b: 1, c: 9, nothankyou: 90}, 
{date: Wed Jul 21 2016 00:00:00 GMT-1000 (HST), a: 7, b: 2, c: 10, nothankyou: 70}, 
{date: Wed Jul 22 2016 00:00:00 GMT-1000 (HST), a: 6, b: 5, c: 3, nothankyou: 50}, 
...etc...] 

Das Ziel ist, ein Flächendiagramm mit den Werten für a, b und c entlang der y-Achse und die Zeit (date) entlang der x-Achse zu schaffen. Sie müssen unerwünschte Datenpunkte ausfiltern, z. B. nothankyou.

Ich habe zuvor d3.nest verwendet, um Daten in einem anderen Projekt ähnlich zu manipulieren, aber ist es nicht übertrieben, wo die Daten bereits nach Datum organisiert sind?

Der Bereich D3 Chart selbst recht einfach ist (es die Daten übernimmt hat d3.nest gewesen() - ed bereits):

var format = d3.time.format("%Y-%m-%d"); 

var margin = {top: 20, right: 30, bottom: 30, left: 40}, 
    width = 450 - margin.left - margin.right, 
    height = 300 - margin.top - margin.bottom, 
    delay = 500, 
    duration = 750; 

var x = d3.time.scale() 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height, 0]); 

var z = d3.scale.category20c(); 

var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .ticks(d3.time.months); 

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

var stack = d3.layout.stack() 
    .offset("zero") 
    .values(function(d) { return d.values; }) 
    .x(function(d) { return d.date; }) 
    .y(function(d) { return d.value; }); 

var nest = d3.nest() 
    .key(function(d) { return d.key; }); 

var area = d3.svg.area() 
    .interpolate("cardinal") 
    .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(".areaChart") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    totalCrimeData.forEach(function(d) { 
    d.date = format.parse(d.date); 
    d.value = +d.value; 
    }); 

    var layers = stack(nest.entries(data)); 
    console.log("layers",layers); 

    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); }) 
     .style("fill", function(d, i) { return z(i); }); 

    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 

Antwort

0

Hier eine Zwischenlösung ist (nicht D3), die ich bin gekommen, mit um die Daten so zu strukturieren, wie die D3 es einrichten will. Kommentare willkommen.

var data = [ {}, {}, {}, ... ] // see above 
var dataSets = ["a","b","c"] 
var newArr = []; 

data.map(function(a) { 
    var prop; 
    var _this = this; 

    dataSets.map(function(k) { 
    prop = a.date+"|"+k; 
    if (!_this[prop]) { 
     _this[prop] = { 
     key: k, 
     value: 0, 
     date: a.date 
     }; 
     newArr.push(_this[prop]); 
     } 
     if (prop === a.date+"|"+k) { 
     _this[prop].value += parseInt(a[k]); 
     } 
    }); 
    }, Object.create(null)); 

console.log("reduced data", newArr);