D3 - 如何处理 JSON 数据结构?
Posted
技术标签:
【中文标题】D3 - 如何处理 JSON 数据结构?【英文标题】:D3 - how to deal with JSON data structures? 【发布时间】:2012-04-22 14:11:00 【问题描述】:我是 D3 的新手,已经花了几个小时来了解有关处理结构化数据的任何信息,但没有得到积极的结果。 我想使用下面的数据结构创建一个条形图。 绘制(水平)条形,但仅针对用户“jim”。
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);
谁能指出我做错了什么?
【问题讨论】:
【参考方案1】:这可能会澄清嵌套方面,除了 mbostock 的好答案。
您的数据有 2 度嵌套。您有一个包含 2 个对象的数组,每个对象都有一个整数数组。如果您希望最终图像反映这些差异,则需要为每个图像进行连接。
这里有一个解决方案:每个用户由一个组g
元素表示,每个分数由一个rect
表示。您可以通过以下几种方式执行此操作:在 svg 上使用 datum
,然后在每个 g
上使用身份函数,或者您可以直接加入 g
上的数据。在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);
同样,您不必创建这些 g 元素,但通过这样做,我现在可以不同地表示用户分数(它们与变换有不同的 y),我还可以为它们赋予不同的样式,如下所示:
.jim
fill: red;
.ray
fill: blue;
【讨论】:
【参考方案2】:当您通过selection.data 选择join data 时,数据数组中的元素数量应与选择中的元素数量相匹配。您的数据数组有两个元素(对于 Jim 和 Ray),但您将其绑定到的选择只有一个 SVG 元素。您是要创建多个 SVG 元素,还是将 Jim 和 Ray 的得分矩形放在同一个 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")
…
如果您想为每个人创建多个 SVG 元素,那么您需要一个数据连接:
var chart = d3.select("#charts").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "chart")
…
第二个问题是您不应该将d3.values 与数组一起使用;该函数用于提取对象的值。假设您希望每个人有一个 SVG 元素(因此,在本例中为两个),那么 rect 的数据就是该人的相关分数:
var rect = chart.selectAll("rect")
.data(function(d) return d.scores; )
.enter().append("rect")
…
如果您还没有,我建议您阅读这些教程:
Thinking with Joins Nested Selections【讨论】:
嗨,迈克,我很荣幸能得到你的帮助 :) 在这个例子中我想要的是获得一个 SVG 图像。似乎我的错误不是使用 .data([data]),而是使用 .data(data)。不幸的是,我不能立即检查它,但我今晚会检查它。我之前浏览过“嵌套选择”。这似乎没有涵盖这个主题,但既然你推荐了它,我将深入研究这些教程。我会更新这篇文章。谢谢! 很高兴我能帮上忙。如果这回答了您的问题,请添加复选标记以解决它。谢谢! 再次您好,该解决方案不起作用。这次完全没有图像了:\ 实际上,为了学习进入-更新-退出模式,我更喜欢 Mike 的“3 个小圆圈”,这是一个更新的教程,它让一切变得非常清晰。 bost.ocks.org/mike/circles @Ray 认为这是您问题的解决方案?以上是关于D3 - 如何处理 JSON 数据结构?的主要内容,如果未能解决你的问题,请参考以下文章