来自JSON的D3 Multiseries折线图

时间:2014-10-10 08:25:42

标签: json d3.js

我有一个基于JSON有效负载生成的多重系列折线图的基本演示。它按预期工作,但我感觉我没有充分利用D3库来正确解析或绑定数据。

嵌套数据的最佳格式是什么?例如,对象的对象,数组的数组等?

http://jsfiddle.net/thinkin3d/nc2sgmcz/

JSON有效负载如下所示:

var data = {
    "Series 1": {
        "20141020": 3.5003987252672744,
        "20141019": 2.505802351020492,
        "20141018": 1.511804171940014},
    "Series 2": {
        "20141008": 3.386547593121662,
        "20141009": 2.1369256424188166,
        "20141010": 0.88701610875722286},
    "Series 3": {
        "20141024": 1.041445076319178,
        "20141025": 1.1241181263211502,
        "20141026": 1.38667149365412}
}

我调用d3.entries将其转换为数组:

var entries = d3.entries(data);

然后我再次调用d3.entries,每次我想访问第二层中的特定键值对:

var entry = d3.entries(d.value);

我多次打电话给我并重复自己,这就是为什么我觉得必须有一种我不知道的更好的方式。

我没有使用D3库的哪些部分?

理想情况下,我希望能够维护JSON有效负载格式,但如果在发送之前进行简单的重新排列会让D3更容易,那么我全都是耳朵!

代码:

var margin = {top: 20, right: 20, bottom: 30, left: 50},
        width = 600 - margin.left - margin.right,
        height = 400 - margin.top - margin.bottom;

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

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

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

var color = d3.scale.category20();

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

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

var area = d3.svg.area()
        .interpolate("basis")
        .x(function (d) {
            return x(parseDate(d.key));
        })
        .y0(height)
        .y1(function (d) {
            return y(d.value);
        });

var svg = d3.select("body").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 + ")");

var entries = d3.entries(data);

color.domain(entries.map(function (d) {
    return d;
}));

var minX = d3.min(entries, function (kv) {
    var entry = d3.entries(kv.value);
    return d3.min(entry, function (d) {
        return parseDate(d.key);
    })
});
var maxX = d3.max(entries, function (kv) {
    var entry = d3.entries(kv.value);
    return d3.max(entry, function (d) {
        return parseDate(d.key);
    })
});
var minY = d3.min(entries, function (kv) {
    var entry = d3.entries(kv.value);
    return d3.min(entry, function (d) {
        return d.value;
    })
});
var maxY = d3.max(entries, function (kv) {
    var entry = d3.entries(kv.value);
    return d3.max(entry, function (d) {
        return d.value;
    })
});

x.domain([minX, maxX]);
y.domain([minY, maxY]);

var element = svg.selectAll(".element")
        .data(entries)
        .enter().append("g")
        .attr("class", "element");

element.append("path")
        .attr("class", "area")
        .attr("d", function (d) {
            var entry = d3.entries(d.value);
            return area(entry);
        })
        .style("fill", function (d) {
            return color(d.key);
        });

element.append("text")
        .datum(function (d) {
            var entry = d3.entries(d.value);
            return {
                name: d.key,
                date: parseDate(entry[entry.length - 1].key),
                value: entry[entry.length - 1].value
            };
        })
        .attr("transform", function (d) {
            return "translate(" + x(d.date) + "," + y(d.value) + ")";
        })
        .attr("x", -6)
        .attr("dy", ".35em")
        .text(function (d) {
            return d.name;
        });

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)

如果首先获取所有x和y值,然后获取这些数组的范围,则可以大大简化代码。这是相对简单的,唯一需要注意的是你需要展平嵌套数组:

var allX = d3.values(data).map(d3.keys)
  .reduce(function(a,b) { return a.concat(b); }).map(parseDate);
var allY = d3.values(data).map(d3.values)
  .reduce(function(a,b) { return a.concat(b); });

x.domain(d3.extent(allX));
y.domain(d3.extent(allY));

这将获取初始数据结构中的值以及每个键或值中的值,具体取决于您是否需要x或y。然后使用.reduce()展平此嵌套数组。对于y,我们已经完成了,对于x,日期被解析。然后,您可以直接使用d3.extend()获取域的值。

完整演示here