【问题标题】:How can I perform this d3.js magic (Grouped Bar Chart) with JSON rather than CSV?如何使用 JSON 而不是 CSV 执行这个 d3.js 魔术(分组条形图)?
【发布时间】:2013-01-11 04:17:18
【问题描述】:

我试图效仿这个例子:http://bl.ocks.org/3887051

但是,我有一个 JSON 对象,而不是 CSV。

现在,我发现我可以按照此处的说明将 JSON 转换为 CSV:How to convert JSON to CSV format and store in a variable

这感觉就像是一个黑客攻击。

这是我的 JSON:

[{"YEAR":2012,"MONTH":1,"MMM":"JAN","Total_Flights":30,"Completed":21,"Canceled":7,"Aborted":2},
{"YEAR":2012,"MONTH":2,"MMM":"FEB","Total_Flights":54,"Completed":28,"Canceled":20,"Aborted":6},
{"YEAR":2012,"MONTH":3,"MMM":"MAR","Total_Flights":39,"Completed":25,"Canceled":12,"Aborted":2},
{"YEAR":2012,"MONTH":4,"MMM":"APR","Total_Flights":27,"Completed":21,"Canceled":6,"Aborted":0},
{"YEAR":2012,"MONTH":5,"MMM":"MAY","Total_Flights":35,"Completed":21,"Canceled":12,"Aborted":2},
{"YEAR":2012,"MONTH":6,"MMM":"JUN","Total_Flights":15,"Completed":10,"Canceled":4,"Aborted":1},
{"YEAR":2012,"MONTH":7,"MMM":"JUL","Total_Flights":42,"Completed":18,"Canceled":21,"Aborted":3},
{"YEAR":2012,"MONTH":8,"MMM":"AUG","Total_Flights":43,"Completed":29,"Canceled":8,"Aborted":6},
{"YEAR":2012,"MONTH":9,"MMM":"SEP","Total_Flights":28,"Completed":20,"Canceled":8,"Aborted":0},
{"YEAR":2012,"MONTH":10,"MMM":"OCT","Total_Flights":43,"Completed":24,"Canceled":18,"Aborted":1},
{"YEAR":2012,"MONTH":11,"MMM":"NOV","Total_Flights":35,"Completed":18,"Canceled":17,"Aborted":0},
{"YEAR":2012,"MONTH":12,"MMM":"DEC","Total_Flights":45,"Completed":9,"Canceled":32,"Aborted":4},
{"YEAR":2013,"MONTH":1,"MMM":"JAN","Total_Flights":49,"Completed":4,"Canceled":43,"Aborted":2}]

我的游戏计划是让图表显示每个月的四个条形图:总计、已完成、已取消和已中止。

如何转换此示例代码以处理我的 JSON?

我将在此处浏览 d3.js 教程:https://github.com/mbostock/d3/wiki/Tutorials,直到我弄清楚或有人明智地向我展示了绳索。

我会定期更新这篇文章的进度。

更新 #1:任何来这里的人都应该查看这些天赐教程:http://alignedleft.com/tutorials/d3/

我还在努力。这么强大的图书馆。我会在几个小时内再次报告。

【问题讨论】:

    标签: json csv d3.js


    【解决方案1】:

    在对 D3 的文档和我之前链接的优秀教程进行了几天的深入研究之后,我终于创建了我的第一个图表。

    // Make a JSON object out of the data.d string receieved.
    json_data = jQuery.parseJSON(data.d)
    
    // width = 960 - 40 - 20 = 900
    // height = 500 - 20 - 30 = 450
    var margin = { top: 20, right: 20, bottom: 30, left: 40 },
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;
    
    //  Information on ordinal scales can be found at: https://github.com/mbostock/d3/wiki/Ordinal-Scales
    //  An ordinal scale that sets the output range from the specified continuous interval (that is, [0, width]).
    //  The array interval contains two elements representing the min and max numeric values.
    //  This interval is subdivided into n evenly-spaced bands, where n is the number of (unique) values in the domain.
    //  The bands may be offset from the edge of the interval and other bands according to the specifided padding, 
    //      which defaults to zero.
    //  The padding is typically in the range [0,1] (0.1 in this example) and corrseponds to the amount of space
    //      in the range interval to allocate to padding.
    //  A value of 0.5 means that the band width will be equal to the padding width.
    var x0 = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);
    
    //  Constructs a new ordinal scale with an empty domain and an empty range.
    //  The ordinal scale is invalid (always returning undefined) until an output range is specified).
    var x1 = d3.scale.ordinal();
    
    //  Information on linear scales can be found at: https://github.com/mbostock/d3/wiki/Quantitative-Scales
    //  Quantitative scales have a continuous domain, such as the set of real numbers, or dates.
    //  Linear scales are a type of quantitative scale.
    //  Linear scales are the most common scale, and a good default choice to map a continuous input domain to a
    //      continous output range.
    //  The mapping is linear in that the output range value y can be expressed as a linear function of the
    //      input domain value x: y = mx + b.
    //  The input domain is typically a dimension of the data that you want to visualize, such as the height of
    //      students (measured in meters) in a sample population.
    //  The output range is typically a dimension of the desired output visualization, such as the height of bars
    //      (measured in pixels) in a histogram.
    
    //  This will set up our y height scale.
    var y = d3.scale.linear()
        .range([height, 0]);
    
    // Colors of the graph.
    //
    // First    : Total flights #097054 (green)
    // Second   : Completed flights #6599FF (blue)
    // Third    : Cancelled flights #FFDE00 (yellow)
    // Fourth   : Aborted flights #FF9900 (orange)
    var color = d3.scale.ordinal()
        .range(["#097054", "#6599FF", "#FFDE00", "#FF9900"]);
    
    //  Set up the xAxis to use our x0 scale and be oriented on the bottom.
    var xAxis = d3.svg.axis()
        .scale(x0)
        .orient("bottom");
        // We don't worry about tickFormat here, as the ticks will be determined by the data.
    
    //  Set up the yAxis to use our y scale and be oriented on the left.
    //      Additionally, set the tick format to display appropriate labels on the axis (taking out for now).
    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");
    //    .tickFormat(d3.format(".2s"));
    
    // Set up the svg canvas with the width and height we calculated earlier.
    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 + ")");
    // Move it to the right margin.left pixels, and move it down margin.top pixels
    
    
    // Our JSON looks like:
    //               [{ "YEAR": 2012, "MONTH": 1,  "MMM": "JAN", "Total": 36, "Completed": 21, "Canceled": 10,  "Aborted": 5 },
    //                { "YEAR": 2012, "MONTH": 2,  "MMM": "FEB", "Total": 60, "Completed": 30, "Canceled": 21, "Aborted": 9 }]
    
    //                data = d3.nest()
    //                    .key(function (d) { return d.MMM + " " + d.YEAR; })
    //                    .entries(json_data)
    data = json_data
    
    
    // seriesNames = "Total", "Completed", "Canceled" and "Aborted"               See, we're filtering out "YEAR", "MONTH" and "MMM"
    var seriesNames = d3.keys(data[0]).filter(function (key) { return (key !== "YEAR") && (key !== "MONTH") && (key !== "MMM"); });
    //                alert(JSON.stringify(seriesNames));
    //                alert(seriesNames);
    
    data.forEach(function (d) {
        d.Flights = seriesNames.map(function (name) { return { name: name, value: +d[name] }; });
        //alert("hi --- " + JSON.stringify(d.Flights));
    });
    
    //alert(JSON.stringify(data));
    
    //x0.domain(data.map(function (d) { return d.State; }));
    // Change State to be MMM, YEAR (for example: "Jan 2012") Could change this to Jan '12
    x0.domain(data.map(function (d) { return d.MMM + " " + d.YEAR; }));
    //alert(JSON.stringify(data.map(function (d) { return d.MMM + " " + d.YEAR; })));
    
    //                //x1.domain(seriesNames).rangeRoundBands([0, x0.rangeBand()]);
    x1.domain(seriesNames).rangeRoundBands([0, x0.rangeBand()]);
    
    //                //y.domain([0, d3.max(data, function (d) { return d3.max(d.ages, function (d) { return d.value; }); })]);
    //                // Make the y domain go from 0 up to the max of d.Total (Total flights)
    //                y.domain([0, d3.max(data, function (d) { return d3.max(d.Total); })]);
    y.domain([0, (10 + d3.max(data, function (d) { return d3.max(d.Flights, function (d) { return d.value; }); }))]);
    
    
    // The axis business
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
    
    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
    .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("# of Flights");
    
    
    // From this point to...
    
    //var state = svg.selectAll(".state")
    //    .data(data)
    //.enter().append("g")
    //    .attr("class", "g")
    //    .attr("transform", function (d) { return "translate(" + x0(d.State) + ",0)"; });
    
    var state = svg.selectAll(".state")
        .data(data)
    .enter().append("g")
        .attr("class", "g")
        .attr("transform", function (d) { return "translate(" + x0(d.MMM + " " + d.YEAR) + ",0)"; });
    
    //alert(JSON.stringify(d.Flights[0]));
    state.selectAll("rect")
        .data(function (d) { return d.Flights; })
    .enter().append("rect")
        .attr("width", x1.rangeBand())
        .attr("x", function (d) { return x1(d.name); })
        .attr("y", function (d) { return y(d.value); })
        .attr("height", function (d) { return height - y(d.value); })
        .style("fill", function (d) { return color(d.name); });
    
    
    var legend = svg.selectAll(".legend")
        .data(seriesNames.slice().reverse())
    .enter().append("g")
        .attr("class", "legend")
        .attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"; });
    
    legend.append("rect")
        .attr("x", width - 18)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", color);
    
    legend.append("text")
        .attr("x", width - 24)
        .attr("y", 9)
        .attr("dy", ".35em")
        .style("text-anchor", "end")
        .text(function (d) { return d; })
        .on("click", function (d) {
            alert(d);
            //state.selectAll("rect")
            //.update()
    
            //                        .exit().transition()
            //                            .attr("height", 0)
            //                            .remove();
    
            //state.selectAll("rect")
            //.update()
    
    
            //state.selectAll("rect").exit().transition().attr("height", 0).remove();
        });
    

    在这个图之后,很容易制作多个圆环图以及堆叠图。

    【讨论】:

    • 你能提供你的输入数据集吗?你在代码中的什么地方加载了它?
    • 这对我有很大帮助。我不知道如何在没有 csv 的情况下解析它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 2017-04-14
    • 2017-01-03
    • 2021-04-10
    • 1970-01-01
    相关资源
    最近更新 更多