Jonathan Potter
Jonathan Potter

Reputation: 175

Hierarchy is returning heights and lengths that are NaN

I'm working on my first treemap and i am unable to get the rect objects to render. The console is telling me that the length and width of each rect is NaN. Here's my code for the map:

  //tree map
const drawTreeMap = (data) => {
  const hierarchy = d3.hierarchy(data)
    .sum((d) => d.value)
    .sort((a, b) => b.value - a.value);

  const treeMap = d3.treemap().size(height, width);

  const root = treeMap(hierarchy)

console.log(root.leaves())

  const map = svg
    .selectAll("g")
    .data(root.leaves())
    .enter()
    .append("g")
    .attr("transform", (item) => {
      "translate(" + item["x0"] + ", " + item["y0"] + ")";
    });

  map
    .append("rect")
    .attr("class", "tile")
    .attr("fill", (item) => {
      let category = item.data.category;
      let color = categories.filter((c, i) => {
        if (category == c) {
          return colors[i];
        }
      });
      return color;
    })
    .attr("data-name", (item) => item.data.name)
    .attr("data-category", (item) => item.data.category)
    .attr("data-value", (item) => item.data.value)
    .attr("width", (item) => item["x1"] - item["x0"])
    .attr("height", (item) => item["y1"] - item["y0"])
  
}
drawTreeMap(data);

});

I know that the json file is being read properly and I can see when I console log the root.leaves() that x1 and y1 values are NaN. I've consulted 4-5 different tutorials on treemaps and I am unable to find anything that works. I am using d3 v6.6 and the json file is here:

json file

Can anyone tell me what I'm doing wrong?

Upvotes: 2

Views: 280

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102218

Your self-answer is not the solution: both your original code and the code in your answer produce exactly the same array. You can see it here (using v5, but that doesn't matter):

const data = {
  "name": "Movies",
  "children": [{
    "name": "Action",
    "children": [{
      "name": "Avatar ",
      "category": "Action",
      "value": "760505847"
    }, {
      "name": "Jurassic World ",
      "category": "Action",
      "value": "652177271"
    }, {
      "name": "The Avengers ",
      "category": "Action",
      "value": "623279547"
    }, {
      "name": "The Dark Knight ",
      "category": "Action",
      "value": "533316061"
    }, {
      "name": "Star Wars: Episode I - The Phantom Menace ",
      "category": "Action",
      "value": "474544677"
    }, {
      "name": "Star Wars: Episode IV - A New Hope ",
      "category": "Action",
      "value": "460935665"
    }, {
      "name": "Avengers: Age of Ultron ",
      "category": "Action",
      "value": "458991599"
    }, {
      "name": "The Dark Knight Rises ",
      "category": "Action",
      "value": "448130642"
    }, {
      "name": "Pirates of the Caribbean: Dead Man's Chest ",
      "category": "Action",
      "value": "423032628"
    }, {
      "name": "Iron Man 3",
      "category": "Action",
      "value": "408992272"
    }, {
      "name": "Captain America: Civil War ",
      "category": "Action",
      "value": "407197282"
    }, {
      "name": "Spider-Man ",
      "category": "Action",
      "value": "403706375"
    }, {
      "name": "Transformers: Revenge of the Fallen ",
      "category": "Action",
      "value": "402076689"
    }, {
      "name": "Star Wars: Episode III - Revenge of the Sith ",
      "category": "Action",
      "value": "380262555"
    }, {
      "name": "The Lord of the Rings: The Return of the King ",
      "category": "Action",
      "value": "377019252"
    }, {
      "name": "Spider-Man 2",
      "category": "Action",
      "value": "373377893"
    }, {
      "name": "Deadpool ",
      "category": "Action",
      "value": "363024263"
    }, {
      "name": "Transformers: Dark of the Moon ",
      "category": "Action",
      "value": "352358779"
    }, {
      "name": "American Sniper ",
      "category": "Action",
      "value": "350123553"
    }, {
      "name": "Furious 7",
      "category": "Action",
      "value": "350034110"
    }, {
      "name": "The Lord of the Rings: The Two Towers ",
      "category": "Action",
      "value": "340478898"
    }, {
      "name": "Spider-Man 3",
      "category": "Action",
      "value": "336530303"
    }, {
      "name": "Minions ",
      "category": "Action",
      "value": "336029560"
    }, {
      "name": "Guardians of the Galaxy ",
      "category": "Action",
      "value": "333130696"
    }, {
      "name": "Batman v Superman: Dawn of Justice ",
      "category": "Action",
      "value": "330249062"
    }, {
      "name": "Transformers ",
      "category": "Action",
      "value": "318759914"
    }, {
      "name": "Iron Man ",
      "category": "Action",
      "value": "318298180"
    }, {
      "name": "Indiana Jones and the Kingdom of the Crystal Skull ",
      "category": "Action",
      "value": "317011114"
    }, {
      "name": "The Lord of the Rings: The Fellowship of the Ring ",
      "category": "Action",
      "value": "313837577"
    }, {
      "name": "Iron Man 2",
      "category": "Action",
      "value": "312057433"
    }, {
      "name": "Star Wars: Episode II - Attack of the Clones ",
      "category": "Action",
      "value": "310675583"
    }, {
      "name": "Pirates of the Caribbean: At World's End ",
      "category": "Action",
      "value": "309404152"
    }, {
      "name": "Star Wars: Episode VI - Return of the Jedi ",
      "category": "Action",
      "value": "309125409"
    }, {
      "name": "Independence Day ",
      "category": "Action",
      "value": "306124059"
    }, {
      "name": "Pirates of the Caribbean: The Curse of the Black Pearl ",
      "category": "Action",
      "value": "305388685"
    }, {
      "name": "Skyfall ",
      "category": "Action",
      "value": "304360277"
    }, {
      "name": "Inception ",
      "category": "Action",
      "value": "292568851"
    }, {
      "name": "Man of Steel ",
      "category": "Action",
      "value": "291021565"
    }, {
      "name": "Star Wars: Episode V - The Empire Strikes Back ",
      "category": "Action",
      "value": "290158751"
    }, {
      "name": "The Matrix Reloaded ",
      "category": "Action",
      "value": "281492479"
    }, {
      "name": "The Amazing Spider-Man ",
      "category": "Action",
      "value": "262030663"
    }, {
      "name": "The Incredibles ",
      "category": "Action",
      "value": "261437578"
    }, {
      "name": "Captain America: The Winter Soldier ",
      "category": "Action",
      "value": "259746958"
    }, {
      "name": "The Lego Movie ",
      "category": "Action",
      "value": "257756197"
    }, {
      "name": "Star Trek ",
      "category": "Action",
      "value": "257704099"
    }, {
      "name": "Batman ",
      "category": "Action",
      "value": "251188924"
    }, {
      "name": "Night at the Museum ",
      "category": "Action",
      "value": "250863268"
    }]
  }, {
    "name": "Drama",
    "children": [{
      "name": "Titanic ",
      "category": "Drama",
      "value": "658672302"
    }, {
      "name": "The Sixth Sense ",
      "category": "Drama",
      "value": "293501675"
    }, {
      "name": "I Am Legend ",
      "category": "Drama",
      "value": "256386216"
    }]
  }, {
    "name": "Adventure",
    "children": [{
      "name": "Shrek 2",
      "category": "Adventure",
      "value": "436471036"
    }, {
      "name": "The Hunger Games: Catching Fire ",
      "category": "Adventure",
      "value": "424645577"
    }, {
      "name": "The Lion King ",
      "category": "Adventure",
      "value": "422783777"
    }, {
      "name": "Toy Story 3",
      "category": "Adventure",
      "value": "414984497"
    }, {
      "name": "The Hunger Games ",
      "category": "Adventure",
      "value": "407999255"
    }, {
      "name": "Frozen ",
      "category": "Adventure",
      "value": "400736600"
    }, {
      "name": "Finding Nemo ",
      "category": "Adventure",
      "value": "380838870"
    }, {
      "name": "The Jungle Book ",
      "category": "Adventure",
      "value": "362645141"
    }, {
      "name": "Jurassic Park ",
      "category": "Adventure",
      "value": "356784000"
    }, {
      "name": "Inside Out ",
      "category": "Adventure",
      "value": "356454367"
    }, {
      "name": "The Hunger Games: Mockingjay - Part 1",
      "category": "Adventure",
      "value": "337103873"
    }, {
      "name": "Alice in Wonderland ",
      "category": "Adventure",
      "value": "334185206"
    }, {
      "name": "Shrek the Third ",
      "category": "Adventure",
      "value": "320706665"
    }, {
      "name": "Harry Potter and the Sorcerer's Stone ",
      "category": "Adventure",
      "value": "317557891"
    }, {
      "name": "The Hobbit: An Unexpected Journey ",
      "category": "Adventure",
      "value": "303001229"
    }, {
      "name": "Harry Potter and the Half-Blood Prince ",
      "category": "Adventure",
      "value": "301956980"
    }, {
      "name": "The Twilight Saga: Eclipse ",
      "category": "Adventure",
      "value": "300523113"
    }, {
      "name": "The Twilight Saga: New Moon ",
      "category": "Adventure",
      "value": "296623634"
    }, {
      "name": "Up ",
      "category": "Adventure",
      "value": "292979556"
    }, {
      "name": "The Twilight Saga: Breaking Dawn - Part 2",
      "category": "Adventure",
      "value": "292298923"
    }, {
      "name": "The Twilight Saga: Breaking Dawn - Part 2",
      "category": "Adventure",
      "value": "292298923"
    }, {
      "name": "Harry Potter and the Order of the Phoenix ",
      "category": "Adventure",
      "value": "292000866"
    }, {
      "name": "The Chronicles of Narnia: The Lion, the Witch and the Wardrobe ",
      "category": "Adventure",
      "value": "291709845"
    }, {
      "name": "Harry Potter and the Goblet of Fire ",
      "category": "Adventure",
      "value": "289994397"
    }, {
      "name": "Monsters, Inc. ",
      "category": "Adventure",
      "value": "289907418"
    }, {
      "name": "The Hunger Games: Mockingjay - Part 2",
      "category": "Adventure",
      "value": "281666058"
    }, {
      "name": "Gravity ",
      "category": "Adventure",
      "value": "274084951"
    }, {
      "name": "Monsters University ",
      "category": "Adventure",
      "value": "268488329"
    }, {
      "name": "Shrek ",
      "category": "Adventure",
      "value": "267652016"
    }, {
      "name": "Harry Potter and the Chamber of Secrets ",
      "category": "Adventure",
      "value": "261970615"
    }, {
      "name": "Jaws ",
      "category": "Adventure",
      "value": "260000000"
    }, {
      "name": "The Hobbit: The Desolation of Smaug ",
      "category": "Adventure",
      "value": "258355354"
    }, {
      "name": "The Hobbit: The Battle of the Five Armies ",
      "category": "Adventure",
      "value": "255108370"
    }, {
      "name": "Men in Black ",
      "category": "Adventure",
      "value": "250147615"
    }]
  }, {
    "name": "Family",
    "children": [{
      "name": "E.T. the Extra-Terrestrial ",
      "category": "Family",
      "value": "434949459"
    }]
  }, {
    "name": "Animation",
    "children": [{
      "name": "Despicable Me 2",
      "category": "Animation",
      "value": "368049635"
    }, {
      "name": "The Secret Life of Pets ",
      "category": "Animation",
      "value": "323505540"
    }, {
      "name": "Despicable Me ",
      "category": "Animation",
      "value": "251501645"
    }]
  }, {
    "name": "Comedy",
    "children": [{
      "name": "Forrest Gump ",
      "category": "Comedy",
      "value": "329691196"
    }, {
      "name": "Home Alone ",
      "category": "Comedy",
      "value": "285761243"
    }, {
      "name": "Meet the Fockers ",
      "category": "Comedy",
      "value": "279167575"
    }, {
      "name": "The Hangover ",
      "category": "Comedy",
      "value": "277313371"
    }, {
      "name": "How the Grinch Stole Christmas ",
      "category": "Comedy",
      "value": "260031035"
    }, {
      "name": "The Hangover Part II ",
      "category": "Comedy",
      "value": "254455986"
    }]
  }, {
    "name": "Biography",
    "children": [{
      "name": "The Blind Side ",
      "category": "Biography",
      "value": "255950375"
    }]
  }]
};

const height = 100, width = 100;

const hierarchy = d3.hierarchy(data)
  .sum((d) => d.value)
  .sort((a, b) => b.value - a.value);

const treeMap = d3.treemap().size([height, width]);

const root = treeMap(hierarchy)

console.log(root.leaves())
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

As you can see, there is no NaN.

The real issue is that in your original code you're not passing width and height to the size() method as an array...

const treeMap = d3.treemap().size(height, width);
//no array here ------------------^------------^

...which you are in your answer (by the way, in the reversed order):

d3.treemap().size([width, height])(hierarchy);
//array here -----^-------------^

Upvotes: 1

Jonathan Potter
Jonathan Potter

Reputation: 175

Just got it working by combining the lines:

  const treeMap = d3.treemap().size(height, width);

  const root = treeMap(hierarchy)

with one line:

  d3.treemap().size([width, height])(hierarchy);

full replacement:

    //tree map
const drawTreeMap = () => {
  
  const hierarchy = d3.hierarchy(data, (node) => node.children)
    .sum((node) => node.value)
    .sort((node1, node2) => node2.value - node1.value);

  d3.treemap().size([width, height])(hierarchy);
  
  const tiles = hierarchy.leaves();

  const block = svg
    .selectAll("g")
    .data(tiles)
    .enter()
    .append("g")
    .attr("transform", (item) => "translate(" + item.x0 + ", " + item.y0 + ")");

  block
    .append("rect")
    .attr("class", "tile")
    .attr("fill", (item) => {
      let category = item.data.category;
      console.log(item)
      let color = categories.filter((c, i) => {
        if (category == c) {
          return colors[i];
        }
      });
      return color[0];
    })
    .attr("data-name", (item) => item.data.name)
    .attr("data-category", (item) => item.data.category)
    .attr("data-value", (item) => item.data.value)
    .attr("width", (item) => item["x1"] - item["x0"])
    .attr("height", (item) => item["y1"] - item["y0"])
  
}
drawTreeMap();

});

Upvotes: 1

Related Questions