Reputation: 175
I'm trying to create a circle pack graph using nest()
and .rollup
. I'm getting the following errors:
Error: Invalid value for <g> attribute transform="translate(undefined,undefined)"
Error: Invalid value for <circle> attribute r="NaN"
I want the circles to be sized according to the number of companies in each country. I'm attempting to adapt Mike Bostock's Flare circle-pack example.
If anyone could point me in the direction of any information, I'd be very grateful.
JS code:
var diameter = 960,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(2,2)");
//Get data
d3.json("data/countriesNested.php", function(error, data){
var submissionsByCountry = d3.nest()
.key(function(d) { return d.Country; })
.key(function(d) { return d.Organisation; })
.rollup(function(leaves) { return leaves.length; })
.entries(data);
var node = svg.datum(data).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.cx + "," + d.cy + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle")
.attr("r", function(d) { return d.r; });
});
d3.select(self.frameElement).style("height", diameter + "px");
</script>
Data file (from MySQL using PHP script):
[
{
"Country":"USA",
"ID":4,
"Organisation":"Company 1"
},
{
"Country":"USA",
"ID":5,
"Organisation":"Company 2"
},
{
"Country":"USA",
"ID":6,
"Organisation":"Company 3"
},
{
"Country":"FRANCE",
"ID":19,
"Organisation":"Company 4"
},
{
"Country":"FRANCE",
"ID":24,
"Organisation":"Company 5"
},
{
"Country":"GERMANY",
"ID":10,
"Organisation":"Company 6"
},
{
"Country":"ITALY",
"ID":7,
"Organisation":"Company 7"
},
.....
Thanks for reading.
Upvotes: 1
Views: 889
Reputation: 21578
There are a few errors in your code that need to be fixed:
You need to set the accessor functions for children and values on your pack layout:
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.children(function(d) {
return d.values; // accessor for children
})
.value(function(d) {
return d.values; // accessor for values
});
Your d3.nest()
returns an array but d3.pack()
requires you to supply a root object containing the hierarchy. You have to create a root object and put your nested array inside:
var countryRoot = {
key: "root",
values: submissionsByCountry
};
In your code you nest your data into submissionsByCountry
but you are not using this variable anywhere else. So you obviously have to refer to it when binding data to your svg
. This is accomplished by the above mentioned root object which is later on bound to the svg
.
var node = svg.datum(countryRoot).selectAll(".node")
The attributes the pack layout is adding to your data nodes include values x
and y
, whereas you refered to them as cx
and cy
which are attributes to <svg:circle>
but are not present in your data. Hence, you got your transform="translate(undefined,undefined)"
error messages. You should use these attributes as such:
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
I put together a working plunk.
Upvotes: 4
Reputation: 108517
So, you want a parent circle (let's call it the world), with child circles representing each country sized with a count of entries in your JSON array?
d3.json("data/countriesNested.php", function(error, data) {
var submissionsByCountry = d3.nest()
.key(function(d) {
return d.Country;
})
.rollup(function(leaves) {
return leaves.length;
})
.entries(data);
var root = {
"key": "world",
"children": submissionsByCountry
};
...
This will give you something closely resembling the flare.json
.
Next, you need to give d3 the right accessor for your circle size.
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) {
return d.values; //<-- this comes from your roll-up and is the count.
});
Finally it looks like you changed the example code to access non-exist cx
and cy
attributes in the resulting nodes data:
var node = svg.datum(root).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) {
return d.children ? "node" : "leaf node";
})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; //<-- this is .x, .y
});
Here's an example.
Upvotes: 1