I'm new to working with D3, and I'm finding it very humbling.
My goal is to make a treemap from a CSV file. I want to use CSV format because I'll be working with values in a spreadsheet, and it's easy for me to save the files that way.
I'm trying to store the data in a hierarchical format, something like this (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
And I'm using this Zoomable Treemap example.
I'd like for the tree to go arbitrarily deep, i.e. if Bart had children in my example, and to accumulate parent/child relationship accordingly based on names.
I found a great example of this for Sankey Diagrams, but I haven't found the equivalent for Zoomable Treemaps.
Is there a way to insert some code between lines 124 and 126 of Bostock's example to get my data formatted properly for a Zoomable Treemap? (I can change the layout of my CSV, but would like to keep CSV formatting). Something like this approach using nest()
, but obviously this doesn't work:
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...
I see examples and StackOverflow questions that address bits and pieces of this, but haven't been able to pull it together end-to-end. And I've been researching and hacking to no avail. I'd wele some help. Thanks!
FIDDLE HERE
/
Fiddle Notes:
- I'm looking for help near line #90 where the ments indicate
- I setup an inline variable to hold a pared down copy of flare.json
- I plan to keep the data in a separate file in real life, but for JSFiddle, it had to be pulled inline; this will, of course, be easily adaptable back to a separate data file if I can figure out the main logic.
- This example doesn't appear to work with D3 version 3.0.4, which is the current built-in version for JSFiddle. I imported v2.x for the example, since that's what works with Bostock's example. That's a potential separate question...
Update
I overcame part of my issue. I wasn't too far off with my thinking that nest()
was necessary, but I didn't update my accessors properly. Here's a very sloppy look at something that mostly works:
Main Difference(s) Between my Example and Bostock's:
- CSV gets nested after it's loaded, using
d3.nest()
. This coerces it into a hierarchical JSON object format - Many (if not all) references to "children" have been replaced by "values" because
d3.nest()
builds trees withkey
andvalues
properties instead of Treemap's expectedname
andchildren
properties. Thevalue
property, which is used for block sizing, stays intact.
Issues Remaining
- It doesn't go arbitrarily deep. I'm considering a way to reorganize my data to make better use of the
d3.nest()
capability, but haven't tried it yet. - The names of children are showing up
undefined
. I'm sure I'm just overlooking something simple, but my primary concern was to get the core features working, so I'll hack at this piece a little when I have a minute.
Note: I'm still seeking help with a clean and idiomatic approach to doing this, including advice on how best to organize the CSV for hierarchical nesting to arbitrary depths!
I'm new to working with D3, and I'm finding it very humbling.
My goal is to make a treemap from a CSV file. I want to use CSV format because I'll be working with values in a spreadsheet, and it's easy for me to save the files that way.
I'm trying to store the data in a hierarchical format, something like this (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
And I'm using this Zoomable Treemap example.
I'd like for the tree to go arbitrarily deep, i.e. if Bart had children in my example, and to accumulate parent/child relationship accordingly based on names.
I found a great example of this for Sankey Diagrams, but I haven't found the equivalent for Zoomable Treemaps.
Is there a way to insert some code between lines 124 and 126 of Bostock's example to get my data formatted properly for a Zoomable Treemap? (I can change the layout of my CSV, but would like to keep CSV formatting). Something like this approach using nest()
, but obviously this doesn't work:
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...
I see examples and StackOverflow questions that address bits and pieces of this, but haven't been able to pull it together end-to-end. And I've been researching and hacking to no avail. I'd wele some help. Thanks!
FIDDLE HERE
http://jsfiddle/KXuWD/
Fiddle Notes:
- I'm looking for help near line #90 where the ments indicate
- I setup an inline variable to hold a pared down copy of flare.json
- I plan to keep the data in a separate file in real life, but for JSFiddle, it had to be pulled inline; this will, of course, be easily adaptable back to a separate data file if I can figure out the main logic.
- This example doesn't appear to work with D3 version 3.0.4, which is the current built-in version for JSFiddle. I imported v2.x for the example, since that's what works with Bostock's example. That's a potential separate question...
Update
I overcame part of my issue. I wasn't too far off with my thinking that nest()
was necessary, but I didn't update my accessors properly. Here's a very sloppy look at something that mostly works:
http://bl.ocks/maw246/7303963
Main Difference(s) Between my Example and Bostock's:
- CSV gets nested after it's loaded, using
d3.nest()
. This coerces it into a hierarchical JSON object format - Many (if not all) references to "children" have been replaced by "values" because
d3.nest()
builds trees withkey
andvalues
properties instead of Treemap's expectedname
andchildren
properties. Thevalue
property, which is used for block sizing, stays intact.
Issues Remaining
- It doesn't go arbitrarily deep. I'm considering a way to reorganize my data to make better use of the
d3.nest()
capability, but haven't tried it yet. - The names of children are showing up
undefined
. I'm sure I'm just overlooking something simple, but my primary concern was to get the core features working, so I'll hack at this piece a little when I have a minute.
Note: I'm still seeking help with a clean and idiomatic approach to doing this, including advice on how best to organize the CSV for hierarchical nesting to arbitrary depths!
Share Improve this question edited Jun 30, 2014 at 9:01 VividD 10.5k8 gold badges66 silver badges112 bronze badges asked Nov 3, 2013 at 23:03 MarcMarc 11.6k2 gold badges39 silver badges48 bronze badges3 Answers
Reset to default 3I have been having similar frustrations while investigating the use of the treemap. The data ing from the server is flat tabular-styled data, such as:
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 }];
Yet the d3 treemap expects a hierarchical format for the javascript objects it processes. After tedious searching, I came across the mention of underscore.nest on the d3 google group. https://github./iros/underscore.nest
"Underscore.Nest is an extenstion [of the underscore js library] for converting flat data into nested tree structures".
Using this library (again, with a dependency on underscore.js) means you do not have to resort to d3.nest and worry about the key/value data format it produces.
Working Example
Here is a working example of the treemap taking a flat list of objects
that have been converted by underscore.nest into the hierarchical format the d3 treemap expects. (Original treemap without underscore.nest is from mbostock's example: http://bost.ocks/mike/treemap/ )
http://jsbin./aGIvOnEH/3
root = _.nest( myData, "thedad");
root.name = "TV Dads";
Hope this is useful.
Untested and probably not very idiomatic (javascript is not my thing), but may put you on the right track. I'm using underscore.js
because I'm lazy, do it using native loops if you care.
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);
...
From mg1075's answer, i see myData
is self-referencing data, meaning the child in one row bees a parent in another row and has children of its own. And that leads to a hierarchical structure that's variable-depth, and where the depth cannot be puted by looking at just one row; the program needs to traverse through the whole thing and establish relationships. d3.nest()
doesn't work for this.. it needs the whole ancestry going all the way to the top lined up in every individual row itself.
I still have to explore underscore.js
, but mg1075's jsbin
working example shows that it didn't actually solve the problem : Bart is ing next to Homer Simpson in the treemap and has his children there despite being Homer Simpson's child; he's also present under Homer Simpson (making him his own uncle :P) but doesn't have any kids listed under himself there (so Bart's clone uncle has stolen his kids, and poor Homer Simpson is left without any grandchildren). So basically grandchildren aren't recognized.
I had posted a question and then found a solution for this kind of variable-depth hierarchical data's visualization over here sometime back, using a library called DataStructures.Tree . I think it might help:
https://stackoverflow./a/27756744/4355695