3

My post is somehow a follow-up to this question : D3 - how to deal with JSON data structures?

In short, I'm in trouble with handling complex nested JSON structures. Let me give a simple sample (that mirrors the above link) to illustrate:

var regularData = [[40,20,30,24,18,40],
                    [24,20,30,41,12,34]];

var myTable = d3.select("body").append("table")
  .selectAll("tr")
  .data(regularData, function(d) {
    return d;
  })
  .enter()
  .append("tr")
  .selectAll("td")
  .data(function(d) {
    return d;
  })
  .enter()
  .append("td") 
  .text(function(d) {
    return d;
  });

As already shown through D3's doc, this produces two lines of numbers, as expected.

But if I replace regularData by this:

var newData = [{"user":"jim","scores":[40,20,30,24,18,40]},
            {"user":"ray","scores":[24,20,30,41,12,34]}];

and adapt the myTable's construction lines 3 to 5 with this:

  .data(newData, function(d) {
    return d.scores;
  })

I would have expected to loop in the scores for each user. Instead, the second data clause is still bound to top-level objects (i.e. with properties "user" and "scores").

A brute-force approach would be to cast my data in a plain "array of arrays" adapted to each purpose. But maybe I missed something, and a more elegant way is possible ?

Thanks by advance for your help, P.

1 Answer 1

3

You have slightly misunderstood what the second argument to d3.data is meant for.

That argument is used for object constancy by providing an id for the data and not as an accessor function, as in most other functions in the d3 API.

However, when a function is passed as the first argument, as is here:

.data(function(d) {
  return d;
})

then it does behave as an accessor function.

In your case, what you want is something along these lines:

var newData = [{"user":"jim","scores":[40,20,30,24,18,40]},
            {"user":"ray","scores":[24,20,30,41,12,34]}];

var myTable = d3.select("body").append("table")
  .selectAll("tr")
  .data(regularData, function(d) {
    return d.user;
  })
  .enter()
  .append("tr")
  .selectAll("td")
  .data(function(d) {
    return d.scores;
  })
  .enter()
  .append("td") 
  .text(function(d) {
    return d;
  });

I have used the user field as the id of the data and have returned the scores in the second call to data to create the td elements.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.