正确操纵JSON数据以创建D3区域图表?

时间:2016-07-24 20:05:56

标签: javascript json d3.js charts

我最挣扎的地方是D3,在将其插入现有模型之前进行适当的数据处理。我试图找出创建具有基于时间的x轴的基本D3区域图表所需的最少数据操作量。我开始使用带有date键和Date对象属性的JSON对象数组,以及用于填充图表的其他几个键值对。

例如:

[{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...]

目标是创建一个区域图表,其中沿着y轴的abc的值以及沿x的时间(date) -轴。需要过滤掉不需要的数据点,例如nothankyou

我之前使用d3.nest来操纵另一个项目中的数据,但是数据按日期组织的位置是不是太过分了?

D3区域图表本身相当简单(假设数据已经d3.nest() - 已经编辑):

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);

1 个答案:

答案 0 :(得分:0)

这是一个临时解决方案(非D3),我已经提出按照D3设置的方式构建数据。欢迎评论。

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);