【问题标题】:Creating a D3 Line Graph with Points using 2 Level Nested JSON使用 2 级嵌套 JSON 创建带点的 D3 线图
【发布时间】:2017-02-27 02:17:27
【问题描述】:

对于我的一生,我似乎无法找到如何处理这个问题的明确答案。当然,我对 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 文件中没有多个“模型”(因此从上面的 sn-p 中完全获取 JSON)。如何有效地为每个指标绘制 ValueDate(多折线图)?如果有人也可以向我指出一些工作示例,那将是一个难以置信的帮助!

【问题讨论】:

    标签: javascript json d3.js nested


    【解决方案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>

    【讨论】:

    • 这太棒了!非常感谢您的解释!很有帮助。快速提问——代码中的箭头函数对我来说是一个错误。我可以用什么替换它以使代码仍然有效?类似 function(d) ...?
    • 将其替换为.attr("d", function (d){ return lineGen(d.Data)})
    • 谢谢!我最终不得不恢复到 d3 库的第 3 版并使用您建议的修改。我的浏览器在支持 v4 和箭头功能时出现问题。之后,我得到了要渲染的图表。
    • 我知道的唯一不支持箭头功能的浏览器是IE。你用的是 IE 吗?
    • Chrome 卡住了,这既令人惊讶又出乎意料。不可否认,是旧版本(43)。一切似乎在 Firefox 中运行良好。显然,更新更多的浏览器版本不会有这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多