5

I've read a number of questions on similar subjects, but none of the answers seem to work for my use case (or I'm just really confused).

I have a csv file dump from a database and I want to show the data's hierarchy using the Dendrogram example found here http://mbostock.github.com/d3/ex/cluster.html

My csv file looks like this:

groupGenre,basicGenre,value
Maps,Atlases (Geographic),10
Catalogs,Auction catalogs,28
No larger group,Academic dissertations,451
No larger group,Account books,1
No larger group,Acrostics,56
No larger group,Addresses,62
No larger group,Advertisements,790
No larger group,Allegories,35
No larger group,Almanacs,3401
No larger group,Alphabets,100
No larger group,Anagrams,4
No larger group,Anthologies,133
No larger group,Anti-slavery literature,1

where value is the number of books published in that genre.

Here is the code I've adapted and now revised based on suggestions below It can also be found at http://dev.stg.brown.edu/projects/Egan/Vis/tree/tree.html

var width = 960,
    height = 2000;

var tree = d3.layout.tree()
    .size([height, width - 160]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });

var vis = d3.select("#chart").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(40, 0)");

d3.csv("../data/genreNested.csv", function(csv) {

  var nodes = tree.nodes(makeTree(csv));

  var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);

  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .attr("dx", function(d) { return d.values ? -8 : 8; })
      .attr("dy", 3)
      .attr("text-anchor", function(d) { return d.values ? "end" : "start"; })
      .text(function(d) { return d.key; });
});

//NEW Function to Build Tree from CSV data
function makeTree(nodes) {
    var nodeByGenre = {};

    //index nodes by genre in case they are out of order
    nodes.forEach(function(d) {
        nodeByGenre[d.basicGenre] = d;
    });

    //Lazily compute children.
    nodes.forEach(function(d) {
        var groupGenre = nodeByGenre[d.groupGenre];
        if (groupGenre.children) groupGenre.children.push(d);
        else groupGenre.children = [d]
    });

    return {"name": "genres", "children": nodes[0]}
}
paxRoman
  • 2,064
  • 3
  • 19
  • 32
Jean Bauer
  • 233
  • 1
  • 4
  • 9
  • Did you see the [Tree Layout from CSV](http://bl.ocks.org/2949981) example in response to [this question](http://stackoverflow.com/questions/11088303/how-to-convert-to-d3s-json-format)? – mbostock Aug 20 '12 at 21:15

1 Answers1

4

The first issue looks to be that you are passing a function to entries instead of an array which it is expecting as per the docs. Try passing the parameter csv to the entries method instead.

function makeTree(csv) {
   var data = d3.nest()
        .key(function(d) {return d.genre; })
        .key(function(d) {return d.groupGenre; })
        .entries(csv);

   return data;
}

The second issue is that your makeTree function is not returning a tree structure like tree.nodes is expecting, see docs here. You want to create an object like the following with your makeTree method.

 var root = 
 {
 "basicGenre": "Maps",
 "value" : 5,
 "children": [
  {
   "basicGenre": "Atlases (Geographic)",
   "value" : 10
   "children": [
    {
     "basicGenre": "Atlases 1",
     "children": []
    },
    {
     "basicGenre": "Atlases 2",
     "children": []
    }
   ]
  }
 ]
}

Basically you need to create a tree like heiarchary based on the groupGenre and basicGenre all underneath some all encompassing root node.

You may also want to look at the this SO question as it deals with creating a proper object to pass to tree.nodes.

Here is a working JSFiddle using your updated code.

Community
  • 1
  • 1
Brant Olsen
  • 5,628
  • 5
  • 36
  • 53
  • 1
    Thanks for the quick response! Your suggestion got rid of the error message, but the visualization still isn't displaying. I looked in the console, and it doesn't look like the data is loading. Any other thoughts? – Jean Bauer Aug 20 '12 at 18:44
  • I've tried adapting that code (results above). It still isn't loading the data, and I'm not sure why. Perhaps I should mention that there are no values shared between the columns of data. groupGenre is a different sent of strings than basicGenre, so indexing based on shared values isn't going to work . . . Thanks so much for your time! – Jean Bauer Aug 21 '12 at 18:19
  • I added a JSFiddle with your updated code that is working. Not exactly sure what your issue is since I cannot see all of your data. – Brant Olsen Aug 22 '12 at 15:51