Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 V4 TreeMap error "Uncaught Error: missing: Comedy-Musical

With V4, the d3.layout.treemap is no longer used. So I'm trying to build a treemap with a flat array of objects using the stratify API. I've found an implementation using a flat array of objects here.

Here is the code I'm currently attempting to build the treemap with.

var treeData = d3.stratify()
    .id(function(d) { return d[relationMap.label]; })
    .parentId(function(d) { return d[relationMap.series]; })
    (chart.children);

// assign the name to each node
treeData.each(function(d) {
    d.name = d[relationMap.label];
});

var treemap = d3.treemap()
    .size([container.width, container.height]);

treemap(root);

svg.append("g").attr("class", "treemap");

var node = svg.select(".treemap")
    .selectAll("g")
    .data(root.leaves())
    .enter().append('g')
    .attr('transform', function (d) {
        return 'translate(0,0)';
    });

node.append('rect')
    // .call(position)
    .attr("x", function (d) {
        return d.x0 + "px";
    })
    .attr("y", function (d) {
        return d.y0 + "px";
    })
    .attr("width", function (d) {
        return d.x1 - d.x0 + "px";
    })
    .attr("height", function (d) {
        return d.y1 - d.y0 + "px";
    })
    .attr("fill", function (d, i) {
        return getColors(colors, i, d[relationMap.series]);
    })
    .attr("fill-opacity", .8)
    .attr("stroke", "#FFFFFF")
    .attr("stroke-width", "1");

node.append('text')
    // .call(position)
    .attr("x", function (d) {
        return d.x0 + "px";
    })
    .attr("y", function (d) {
        return d.y0 + "px";
    })
    .attr("width", function (d) {
        return d.x1 - d.x0 + "px";
    })
    .attr("height", function (d) {
        return d.y1 - d.y0 + "px";
    })
    .attr("transform", "translate(3, 13)")
    .text(function (d) {
        if (d.dy !== 0) {
            return d.children ? null : d[relationMap.label];
        }
    });


/* Don't display text if text is wider than rect */
var temp = svg.select(".treemap").selectAll("g").selectAll("text");
temp.attr("style", function (d) {
    if (this.getBBox().width >= (d.x1 - 2)) {
        return "display:none";
    }
    if (this.getBBox().height >= (d.y1 - 2)) {
        return "display:none";
    }
    });

Using this data:

[
{
    "Title": "The Wrestler",
    "MovieBudget": 6000000,
    "Genre": "Drama"
},
{
    "Title": "The Curious Case of Benjamin Button",
    "MovieBudget": 150000000,
    "Genre": "Drama"
},
{
    "Title": "An Education",
    "MovieBudget": 7500000,
    "Genre": "Drama"
},
{
    "Title": "The Tale of Despereaux",
    "MovieBudget": 60000000,
    "Genre": "Family - Animation"
},
{
    "Title": "A Simple Plan",
    "MovieBudget": 30000000,
    "Genre": "Drama"
},
{
    "Title": "Le Divorce",
    "MovieBudget": 0,
    "Genre": "Comedy - Musical"
},
{
    "Title": "The Man With the Iron Fists",
    "MovieBudget": 15000000,
    "Genre": "Action - Adventure"
},
{
    "Title": "Watchmen",
    "MovieBudget": 130000000,
    "Genre": "Action - Adventure"
},
{
    "Title": "Lords of Dogtown",
    "MovieBudget": 25000000,
    "Genre": "Drama"
},
{
    "Title": "Becoming Jane",
    "MovieBudget": 16500000,
    "Genre": "Drama"
},
{
    "Title": "As Good as It Gets",
    "MovieBudget": 50000000,
    "Genre": "Comedy - Musical"
}
]

I'm getting this error:

"d3.v4.min.js:4 Uncaught Error: missing: Drama"

And I'm not sure what to do to fix this. I've researched online and found nothing that is similar to this error. I've gotten to the drawing section but it only ever painted 1 node and it took the whole screen. I've been at it for about 2 days and could use some help. Any suggestion helps!

As a side note. If it makes it easier to use the data laid out in a tree, I still have the method to do that also.

like image 365
CStreet Avatar asked Aug 23 '16 17:08

CStreet


1 Answers

For d3.v4.js

I was stuck with the same issue for a while.

The follwing thread narrowed down the issue for me: https://github.com/d3/d3-hierarchy/issues/33

Essentially as I understand it you must have the parent nodes specified in the dataset to implement d3.stratify().

In the block you referenced, the data while being in a flat structure has the parent nodes specified for each level. Your data does not.

You have to specify the parent & child nodes yourself. This can be done with d3.nest().

This block http://bl.ocks.org/mbostock/2838bf53e0e65f369f476afd653663a2 led me to my solution and should apply to your situation.

In summary I used:

var nest = d3.nest() // allows elements in an array to be grouped into a hierarchical tree structure
         .key() // levels in the tree are specified by key functions. can have multiple keys
         .rollup() // Specifies a rollup function to be applied on each group of leaf elements. The return value of the rollup function will replace the array of leaf values in either the associative array returned by nest.map or nest.object; for nest.entries, it replaces the leaf entry.values with entry.value.

(comments source: https://github.com/d3/d3-collection)

var root = d3.hierarchy({data:nest.entries(csv_data)},function(d){return d.data;})
     .sum(function(d) {return d.value; })

treemap(root)

I hope this helps!!!!

like image 133
Lew Avatar answered Nov 20 '22 03:11

Lew