porkpiehat
porkpiehat

Reputation: 13

Create D3-friendly JSON out of Parent Child table of data

I'm trying to build a D3 visualization which partitions out data based on a parent child relationship.
http://blog.luzid.com/2013/extending-the-d3-zoomable-sunburst-with-labels/ The JSON that is used in these examples, follows a pattern similar to this:

var flare = {
    "name": "family",
    "size": 2000,
    "children": [{
        "name": "kidWithoutKids",
        "size": 100
    }, {
        "name": "kidWithKids",
        "size": 1900,
        "children": [{
            "name": "grandkidWithoutKids",
            "size": 100
        }, {
            "name": "grandkidWithKids",
            "size": 1900,
            "children": [...and so on...]
        }]
    }]
}

What I need to do is take a set of data that is tabular and convert it into a JSON object in that format. So, the data I have coming in (which I can't change) looks like this:

var arrayChildParent = [
    [{"thisText":"family"},{"thisText":"-"},{"thisNum":2000}],
    [{"thisText":"kidWithoutKids"},{"thisText":"family"},{"thisNum":100}],
    [{"thisText":"kidWithKids"},{"thisText":"family"},{"thisNum":1900}],
    [{"thisText":"grandkidWithoutKids"},{"thisText":"kidWithKids"},{"thisNum":100}],
    [{"thisText":"grandkidWithKids"},{"thisText":"kidWithKids"},{"thisNum":1800}],
  ..... and so on
]

So, you can think of it as a table with Child | Parent | Size. Obviously, it would be great to have a function which worked like this:

var flare = createJSON(arrayChildParent);

The data can come in in any order so I've been having a tough time building a recursive function that loops through the data and creates the JSON tree, but sometimes I could have a child whose parent has a parent which has not been created yet. I also tried looping first to create an index of parents or parents with parents, and it got very difficult to manage.

Now, I'm wondering if I'm going about this the wrong way. Is there an easier way to simply take that arrayed data set I have and load it into D3 for use in a tree structure?

Any help would be greatly appreciated. Thanks!

Upvotes: 1

Views: 2433

Answers (1)

jshanley
jshanley

Reputation: 9128

Here's one way you could accomplish this.

The first step would be to clean up the data a bit so it's sensible enough to work with. You could use Array.map() to iterate through the data and make each datum an object:

var cleanData = arrayChildParent.map(function(d) {
  return {
    name: d[0].thisText,
    parent: d[1].thisText,
    size: d[2].thisNum
  };
});

Then you need a function that finds all datapoints whose parent is a given name, and then recursively finds their children. This is easily done by using Array.filter() in tandem with Array.map():

function getChildren(name) {
  return cleanData.filter(function(d) { return d.parent === name; })
    .map(function(d) {
      return {
        name: d.name,
        size: d.size,
        children: getChildren(d.name)
      };
    })
}

Your flare variable is then simply the first result from calling getChildren on -

var flare = getChildren('-')[0];

EDIT:

Or, formatted as the single function you mentioned in your question:

var flare = createJSON(arrayChildParent);

function createJSON(yuckyData) {

  var happyData = yuckyData.map(function(d) {
    return {
      name: d[0].thisText,
      parent: d[1].thisText,
      size: d[2].thisNum
    };
  });

  function getChildren(name) {
    return happyData.filter(function(d) { return d.parent === name; })
      .map(function(d) {
        return {
          name: d.name,
          size: d.size,
          children: getChildren(d.name)
        };
      });
  }

  return getChildren('-')[0];
}

Upvotes: 1

Related Questions