D3 – 如何处理JSON数据结构?
我是D3的新手,已经花了几个小时的时间来找出处理结构化数据的任何事情,但没有积极的结果。 我想用下面的数据结构创build一个条形图。 酒吧(水平)绘制,但只为用户“吉姆”。
var data = [{"user":"jim","scores":[40,20,30,24,18,40]}, {"user":"ray","scores":[24,20,30,41,12,34]}]; var chart = d3.select("div#charts").append("svg") .data(data) .attr("class","chart") .attr("width",800) .attr("height",350); chart.selectAll("rect") .data(function(d){return d3.values(d.scores);}) .enter().append("rect") .attr("y", function(d,i){return i * 20;}) .attr("width",function(d){return d;}) .attr("height", 20);
任何人都可以指出我做错了什么?
当您通过selection.data 将数据连接到select中时 ,数据数组中元素的数量应与select中元素的数量相匹配。 你的数据数组有两个元素(对于Jim和Ray),但是你所绑定的select只有一个SVG元素。 您是否尝试创build多个SVG元素,或将Jim和Ray的分数matrix放在同一个SVG元素中?
如果要将两个数据元素都绑定到单个SVG元素,则可以将数据包装到另一个数组中:
var chart = d3.select("#charts").append("svg") .data([data]) .attr("class", "chart") …
或者,使用selection.datum ,它直接绑定数据而不计算连接:
var chart = d3.select("#charts").append("svg") .datum(data) .attr("class", "chart") …
如果你想为每个人创build多个SVG元素,那么你需要一个数据连接:
var chart = d3.select("#charts").selectAll("svg") .data(data) .enter().append("svg") .attr("class", "chart") …
第二个问题是,你不应该使用数组d3.values ; 该函数用于提取对象的值。 假设你想要每个人一个SVG元素(所以在这个例子中是两个),那么矩形的数据就是那个人的相关分数:
var rect = chart.selectAll("rect") .data(function(d) { return d.scores; }) .enter().append("rect") …
如果你还没有,我build议阅读这些教程:
- join思考
- 嵌套select
这可能会澄清嵌套的方面,除了mbostock的罚款答案。
你的数据有2度的嵌套。 你有一个2个对象的数组,每个对象都有一个int数组。 如果你想要你的最终形象来反映这些差异,你需要为每一个做一个join。
以下是一个解决scheme:每个用户都由一个g
组元素来表示,每个用户都以rect
表示。 您可以通过以下几种方法来实现:使用svg上的datum
,然后使用每个g
上的标识函数,也可以直接在g
上join数据。 使用g
上的data
更为典型,但这里有两种方法:
使用svg上的数据:
var chart = d3.select('body').append('svg') .datum(data) // <---- datum .attr('width',800) .attr('height',350) .selectAll('g') .data(function(d){ return d; }) // <----- identity function .enter().append('g') .attr('class', function(d) { return d.user; }) .attr('transform', function(d, i) { return 'translate(0, ' + i * 140 + ')'; }) .selectAll('rect') .data(function(d) { return d.scores; }) .enter().append('rect') .attr('y', function(d, i) { return i * 20; }) .attr('width', function(d) { return d; }) .attr('height', 20);
使用组( g
)元素的数据:
var chart = d3.select('body').append('svg') .attr('width',800) .attr('height',350) .selectAll('g') .data(data) // <--- attach directly to the g .enter().append('g') .attr('class', function(d) { return d.user; }) .attr('transform', function(d, i) { return 'translate(0, ' + i * 140 + ')'; }) .selectAll('rect') .data(function(d) { return d.scores; }) .enter().append('rect') .attr('y', function(d, i) { return i * 20; }) .attr('width', function(d) { return d; }) .attr('height', 20);
再次,你不需要创build这些g元素,但是现在我可以用不同的方式表示用户分数(它们与变换有不同的y),我也可以给它们不同的样式,如下所示:
.jim { fill: red; } .ray { fill: blue; }