使用2级嵌套JSON创建带有点的D3线图

时间:2017-02-27 02:17:28

标签: javascript json d3.js nested

对于我的生活,我似乎无法找到关于如何处理这个问题的明确答案。当然,我仍然是javascript和D3的新手,但我找不到任何好的例子。

我目前正在尝试使用积分创建D3多线图。我使用平坦的JSON文件取得了相当不错的成功,但是当我的JSON数据被修改为添加额外的嵌套层时,我真的开始挣扎。

我的JSON数据文件现在看起来像这样:

{
    "Model": "Model A", 
    "Data": [
        {
            "Metric": "Metric 1", 
            "Data": [
                    {"Date":"2017-2-25", "Value": "34"}, 
                    {"Date":"2017-2-26", "Value": "52"},
                    {"Date":"2017-2-27", "Value": "47"},
                    {"Date":"2017-2-28", "Value": "50"}
             ]
        }, 
        {
            "Metric": "Metric 2", 
            "Data": [
                    {"Date":"2017-2-25", "Value": "22"}, 
                    {"Date":"2017-2-26", "Value": "27"},
                    {"Date":"2017-2-27", "Value": "25"},
                    {"Date":"2017-2-28", "Value": "21"}
             ]
        }, 
        {
            "Metric": "Metric 3", 
            "Data": [
                    {"Date":"2017-2-25", "Value": "27"}, 
                    {"Date":"2017-2-26", "Value": "28"},
                    {"Date":"2017-2-27", "Value": "25"},
                    {"Date":"2017-2-28", "Value": "22"}
             ]
        }
    ]
} 

添加了这个额外的嵌套层,因此我可以按模型和指标进行过滤。

假设我的JSON文件中没有多个“模型”(因此完全按照上面的代码片段获取JSON)。如何针对每个指标(多线图)有效地绘制ValueDate?如果有人能指出我的一些工作实例,那将是一个不可思议的帮助!

1 个答案:

答案 0 :(得分:1)

根据您的数据结构,可能的解决方案是将数据(特别是外部Data数组)绑定到组:

var groups = svg.selectAll("foo")
    .data(data.Data)
    .enter()
    .append("g");

使用每个内部Data数组作为每行的数据:

var lines = groups.append("path")
    .attr("d", d => lineGen(d.Data))
    .attr("fill", "none")
    .attr("stroke", (d, i) => colors(i));

以下是使用数据对象的演示:



var data = {
    "Model": "Model A",
    "Data": [{
        "Metric": "Metric 1",
        "Data": [{
            "Date": "2017-2-25",
            "Value": "34"
        }, {
            "Date": "2017-2-26",
            "Value": "52"
        }, {
            "Date": "2017-2-27",
            "Value": "47"
        }, {
            "Date": "2017-2-28",
            "Value": "50"
        }]
    }, {
        "Metric": "Metric 2",
        "Data": [{
            "Date": "2017-2-25",
            "Value": "22"
        }, {
            "Date": "2017-2-26",
            "Value": "27"
        }, {
            "Date": "2017-2-27",
            "Value": "25"
        }, {
            "Date": "2017-2-28",
            "Value": "21"
        }]
    }, {
        "Metric": "Metric 3",
        "Data": [{
            "Date": "2017-2-25",
            "Value": "27"
        }, {
            "Date": "2017-2-26",
            "Value": "28"
        }, {
            "Date": "2017-2-27",
            "Value": "25"
        }, {
            "Date": "2017-2-28",
            "Value": "22"
        }]
    }]
};

var width = 500,
    height = 300;

var colors = d3.scaleOrdinal(d3.schemeCategory10);

var svg = d3.select("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height);

var parse = d3.timeParse("%Y-%m-%d");

var xScale = d3.scaleTime()
    .range([30, width - 20])
    .domain(d3.extent(data.Data[0].Data, d => parse(d.Date)));

var yScale = d3.scaleLinear()
    .range([height - 20, 20])
    .domain([0, 60]);

var lineGen = d3.line()
    .x(d => xScale(parse(d.Date)))
    .y(d => yScale(d.Value));

var groups = svg.selectAll("foo")
    .data(data.Data)
    .enter()
    .append("g");

var lines = groups.append("path")
    .attr("d", d => lineGen(d.Data))
    .attr("fill", "none")
    .attr("stroke", (d, i) => colors(i));

var gX = svg.append("g").attr("transform", "translate(0," + (height - 20) + ")").call(d3.axisBottom(xScale));

var gY = svg.append("g").attr("transform", "translate(30,0)").call(d3.axisLeft(yScale));

<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;