我刚接触D3,我发现它非常谦卑。
我的目标是从CSV文件制作树形图。我想使用CSV格式,因为我将使用电子表格中的值,并且我很容易以这种方式保存文件。
我正在尝试以分层格式存储数据,如下所示(hier.csv):
parent,child,value
Homer Simpson,Bart,20
Homer Simpson,Lisa,14
Homer Simpson,Maggie,6
Peter Griffin,Chris,19
Peter Griffin,Meg,12
Peter Griffin,Stewie,9
我正在使用此Zoomable Treemap example。
我希望树能够任意深入,即如果巴特在我的例子中有孩子,并根据姓名积累父母/子女的关系。
我找到了great example of this for Sankey Diagrams,但我没有找到Zoomable Treemaps的等价物。
有没有办法在Bostock's example的第124行和第126行之间插入一些代码,以便为Zoomable Treemap正确格式化数据? (我可以更改CSV的布局,但希望保留CSV格式)。使用nest()
这样的方法,但显然这不起作用:
d3.csv("./hier.csv", function(hier) {
var root = {
"name": "myrootnode",
"children": d3.nest()
.key(function (d) { return d.parent; })
.key(function (d) { return d.child; })
.entries(hier)
};
initialize(root);
accumulate(root);
layout(root);
display(root);
//etc...
我看到了一些示例和StackOverflow问题,这些问题解决了这个问题的一些部分,但是却无法将它们端到端地整合在一起。我一直在研究和黑客无济于事。我会欢迎一些帮助。谢谢!
FIDDLE HERE
小提琴笔记:
更新
我克服了部分问题。我认为nest()
是必要的,但我并没有太远,但我没有正确更新我的访问者。这是一个非常草率的看看主要工作的东西:
http://bl.ocks.org/maw246/7303963
我的例子和Bostock之间的主要区别:
d3.nest()
加载后嵌套。这会将其强制转换为分层JSON对象格式d3.nest()
使用key
和values
属性构建树,而不是Treemap的预期{{1} }和name
属性。用于块大小调整的children
属性保持不变。剩余问题
value
功能,但还没有尝试过。d3.nest()
。我确定我只是忽略了一些简单的事情,但我主要关心的是让核心功能正常工作,所以当我有一分钟的时候,我会对这篇文章进行一些修改。注意:我仍然在寻求帮助,干净且惯用的方法来这样做,包括如何最有效地组织CSV分层嵌套任意深度的意见
答案 0 :(得分:3)
在调查树形图的使用时,我一直有类似的挫败感。 来自服务器的数据是平板式样数据,例如:
var myData = [{ "thedad": "Homer Simpson", "name": "Bart", "value": 20 },
{ "thedad": "Homer Simpson", "name": "Lisa", "value": 14 },
{ "thedad": "Homer Simpson", "name": "Maggie", "value": 6 },
{ "thedad": "Peter Griffin", "name": "Chris", "value": 19 },
{ "thedad": "Peter Griffin", "name": "Meg", "value": 12 },
{ "thedad": "Peter Griffin", "name": "Stewie", "value": 16 },
{ "thedad": "Bart", "name": "Bart Junior A", "value": 77 },
{ "thedad": "Bart", "name": "Bart Junior B", "value": 32 }];
然而,d3 treemap需要为其处理的javascript对象提供分层格式。 经过繁琐的搜索,我在d3 google小组中看到了underscore.nest的提及。 https://github.com/iros/underscore.nest
“Underscore.Nest是[下划线js库]的扩展名 将平面数据转换为嵌套树结构“。
使用此库(再次,依赖于underscore.js)意味着您没有 诉诸d3.nest并担心它产生的键/值数据格式。
工作示例
下面是一个树形图的工作示例,它采用了一个平面的对象列表
已被underscore.nest转换为d3 treemap所期望的分层格式。 (没有underscore.nest的原始树形图来自mbostock的例子:http://bost.ocks.org/mike/treemap/)
<强> http://jsbin.com/aGIvOnEH/3 强>
root = _.nest( myData, "thedad");
root.name = "TV Dads";
希望这很有用。
答案 1 :(得分:1)
未经测试,可能不是非常惯用(javascript不是我的事),但可能会让你走上正轨。我正在使用underscore.js
,因为我很懒,如果你愿意,可以使用原生循环来做。
d3.csv(csv_url, function(error, data) {
var root = {
name: "Everybody",
value: 0,
children: []
};
var parents = {};
_.each(data, function(row) {
var child = {
name: row.child,
value: row.value,
children: []
};
if(parents[row.parent]) { // parent seen already
parents[row.parent]['children'].push(child);
parents[row.parent]['value'] += row.value;
} else { // new parent
parents[row.parent] = {
name: row.parent,
children: [child],
value: row.value
}
}
root.value += row.value;
});
root.children = _.values(parents);
...
答案 2 :(得分:0)
从mg1075's answer,我看到myData
是自引用数据,这意味着一行中的子项成为另一行中的父项,并且具有自己的子项。这导致了一个可变深度的层次结构,并且只能通过查看一行来计算深度;程序需要遍历整个事物并建立关系。 d3.nest()
对此不起作用..它需要整个祖先一直到顶部排列在每一行中。
我仍然需要探索underscore.js
,但是mg1075的jsbin
工作示例显示它实际上没有解决问题:Bart在树形图中接近Homer Simpson,尽管他的孩子在那里是荷马辛普森的孩子;他也出现在Homer Simpson(让他成为他自己的叔叔:P)但是没有任何孩子在他自己的名单下面(所以Bart的克隆叔叔偷了他的孩子,可怜的荷马辛普森没有任何孙子)。所以孙子孙女基本上都不被认可。
我发布了一个问题,然后使用名为DataStructures.Tree的库,在此处找到了这种可变深度分层数据可视化的解决方案。我认为这可能会有所帮助: