3

So I´m trying to create a hierarchical tree diagram using D3.js. It's supposed to work on top of a QtWebView, and so far, so good: it works. Now I need to tackle the data handling bit of the app. My data is stored in CSV format (not my choice, nor do I have any opinion on that matter) and is described below.

My question is: how to output JSON from this CSV?

I have been looking around for examples for a few days, but I'm stuck. I just wondered if someone could point me in the right direction, since I'm only getting examples on how to produce the tree with data in JSON format and people talking about how to use plugins to output JSON with Qt.

I have no trouble in reading from/writing to the CSV/JSON files. I just really need to know how to make an algorithm that would allow me from this data to output JSON.

This is my example CSV file (node_type and node_size are just for show):

node_id,name,node_size,node_type,parent_node
1,node1,122,4,17
2,node2,127,4,20
3,node3,64,2,5
4,node4,147,5,14
5,node5,146,5,12
6,node6,57,4,10
7,node7,149,1,20
8,node8,141,6,10
9,node9,65,5,10
10,node10,108,2,10
11,node11,97,6,2
12,node12,102,2,5
13,node13,79,6,3
14,node14,90,2,2
15,node15,129,1,8
16,node16,76,1,8
17,node17,68,6,13
18,node18,53,5,7
19,node19,112,6,20
20,node20,147,5,6

EDIT: I tried Pablo Navarro's tip and produced the following script for D3.js to handle. It's not producing any errors, but nothing is displayed. Can anyone hint on why?

EDIT2: Fixed typo in code.

    var width = 960, height = 500;
    var color = d3.scale.category20();
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);
    var nodesArray = [], edgesArray = [];

    d3.csv('nodes.csv', function(data) {
        for (var k = 0, n = data.length; k < n; k += 1) {
            nodesArray.push({name: data[k].name, size: data[k].node_size, id: data[k].node_id}),
            edgesArray.push({source: data[k].node_id, target: data[k].parent_node});       
        }
    });

    var force = d3.layout.force()
       .nodes(nodesArray)
       .links(edgesArray)
       .size([width, height])
        .start();

    var link = svg.selectAll(".link")
        .data(edgesArray)
        .enter().append("line")
        .attr("class", "link")
    var node = svg.selectAll(".node")
        .data(nodesArray)
        .enter().append("circle")
        .attr("class", "node")
        .attr("r", nodesArray.size)

EDIT3: One small detail that I thinks might be making all the difference: I'm calling this locally, and by locally I don't mean in a "localhost" webserver of sorts, but in a file. From what I read in Jerome Crukier's tutorial:

This will no longer work in a local file system (ie opening a file in the browser). The resulting file can only run on a webserver, which can be local (ie the page has a url).

I'm not sure if this is exactly the case with my code, but once more, if someone has any insight, it will be appreciated.

EDIT 4:

Ok, after some searching online, I sadly have to admit to not knowing how to use Google & Stackoverflow: I found out everything I needed to know here, ironically, explained by mbostock (of D3.js) himself. I now understand that I had no idea on what I was actually looking for, but somehow I found it.

Not really sure what to do now regarding this (still open) question.

Community
  • 1
  • 1
Joum
  • 3,189
  • 3
  • 33
  • 64
  • 1
    You can use CSV directly. See [the documentation](https://github.com/mbostock/d3/wiki/CSV). – Lars Kotthoff Apr 23 '13 at 13:57
  • Lars Kotthoff: yes I can, and I know that. The question is how to manipulate the data with D3.js having just CSV to begin with. – Joum Apr 24 '13 at 08:23
  • Have you checked [the documentation](https://github.com/mbostock/d3/wiki/CSV)? You'll get objects in D3 (just like with JSON) that you can manipulate in the same way as anything else. – Lars Kotthoff Apr 24 '13 at 08:27
  • I now realise that I might not be as clear as I would like: I know that D3.js can read from CSV and create a struture from it. My question is what does D3.js need to create the tree? I know it takes nodes and edges (or links) as input; I know they have to be in object array form. The question is - _what are the object attributes D3.js needs to build the representation_? – Joum Apr 24 '13 at 08:47
  • @sashoalm: you are right, my bad, edited it out. – Joum Apr 24 '13 at 08:48

1 Answers1

6

You can use the csv file. In order to show a tree, you will need to create an array for the nodes and another for the edges:

d3.csv('url.csv', function(data) {

    var nodes = [], edges = [];

    for (var k = 0, n = data.length; k < n; k += 1) {
        nodes.push({name: data[k].name, size: data[k].size, id: data[k].id}),
        edges.push({source: data[k].id, target: data[k].parent});       
    }
});

with this structure, you will be able to use the force layout, or convert the nodes, edges arrays to a tree structure.

Pablo Navarro
  • 8,244
  • 2
  • 43
  • 52
  • Pablo, thank you for your reply. I tried your suggestion, and produced the code I added on top. Do you have any insight on why it isn´t producing any visualisation? – Joum Apr 24 '13 at 08:22
  • 1
    You need to serve the files using a web sever. If you have the HTML and the csv file in the same directory and run the server from this directory. For instance, you can run: python -m SimpleHTTPServer. – Pablo Navarro Apr 24 '13 at 12:16
  • 2
    Actually, I found out it works without resorting to a webserver. Good tip though, Pablo! ;) – Joum Apr 24 '13 at 13:51