json - 如何使用 JSON 而不是 CSV 执行这个 d3.js 魔术(分组条形图)?

标签 json csv d3.js

我正在尝试遵循以下示例: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}]

我的游戏计划是让图表显示每个月的四个条形图:Total、Completed、Cancelled 和 Aborted。

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

我将在这里浏览 d3.js 教程:https://github.com/mbostock/d3/wiki/Tutorials直到我弄明白或者聪明的人告诉我绳索。

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

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

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

最佳答案

经过几天的 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();
    });

在这张图之后,很容易制作多个 donut chart 以及堆叠图。

关于json - 如何使用 JSON 而不是 CSV 执行这个 d3.js 魔术(分组条形图)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14551653/

相关文章:

java - 如何发送带有 json 正文和 url 参数的 http 帖子?

python - 在 Python 中使用分隔符对 CSV 文件进行排序

Python 将 csv 数据导出到文件中

javascript - D3 将文本附加到内圆

javascript - D3.js 与维基百科的集成

javascript - 使用 ajax 传递数据时,NVD3 折线图不显示 - data.map 不是函数

java - 如何通过android调用json webservice

javascript - 如何在 jquery 中查找 Json 嵌套数组的索引?

javascript - 如何将嵌套的 JSON 数据结构缩减为 map JavaScript

python - 在 python for 循环中一次运行 3 个变量。