Monday, 1 April 2019

How do I position subgroups of small multiples together on the page?

I have a dataset with a column called CategoryLevel1 which contains the names of groups. I applied the nest function to Categorylevel1 and generated a series of svgs based on the keys. I then created rectangles representing items in the entire dataset and repeated the rectangles in each svg. I applied a filter to each svg, so that only the dataset items with the key of that svg can be seen.

My real dataset is bigger than the toy dataset represented here. The result of the above code is a long webpage of svgs - very confusing. To make things more clear, I would like svgs to be grouped according to a column called CategoryLevel2. Here is the effect I am after:

enter image description here

Here's what I have so far:

var doc = `Manual       Name    CategoryLevel1  CategoryLevel2
DOG     "General Furry, Program and Subject Files"      Average Quantity and Planning   Edibles
TR      Senate Committee on animal Standards    Bowl and Plate Design   Edibles
TR      Published Canine        Bowl and Plate Design   Edibles
TR      Canine case files       Bowl and Plate Design   Edibles
DOG     Canine Files    Avoiding Neck Strain    Edibles
DOG     Canine Files    Drooling        Edibles
DOG     Canine Files    Drooling        Edibles
DG      ADVERTISING     At home At home
DG      PROMOTIONS      At home At home
DG3     Publications    At home At home
TR      Public and Information Services At home At home
TR      Petting Services        Getting special treats  At home
TR      Petting Services        Getting special treats  At home
TR      Petting Services        Getting special treats  At home
TR      Petting Services        Getting special treats  At home
TR      Petting Services        Getting special treats  At home
TR      Petting Services        Getting special treats  At home
DG      DEVELOPMENT     Optimal time of day - walking   Walks and outings
DG      INCOME AND REVENUE      Optimal time of day - walking   Walks and outings
TR      Fundraising     Optimal time of day - walking   Walks and outings
TR      Fundraising     Optimal time of day - walking   Walks and outings
DG      DEVELOPMENT     Optimal time of day - walking   Walks and outings
DG      INCOME AND REVENUE      Optimal time of day - walking   Walks and outings
TR      Wishbone        Protective Measures     Walks and outings
TR      Wishbone        Protective Measures     Walks and outings
DG      Wishbone        Observant of Limps Etc  Walks and outings
DOG     Wishbone        Observant of Limps Etc  Walks and outings
TR      Wishbone        Observant of Limps Etc  Walks and outings`;

const data = d3.tsvParse(doc, function(d) {
  return {
    Manual: d.Manual,
    Name: d.Name,
    CategoryLevel1: d.CategoryLevel1,
    CategoryLevel2: d.CategoryLevel2
  };
});


var nest = d3.nest()
  .key(function(d) {
    return d.CategoryLevel1;
  })
  .entries(data);

var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0)

var height = 100,
  width = 300;

var color = d3.scaleOrdinal(["#edf8fb", "#b3cde3", "#8c96c6", "#88419d"]);

/* var svg = d3.select("body").append("svg").attr("height", "100%").attr("width", "100%");

var g = d3.select("svg").attr("height", "100%").attr("width", "100%"); */



var svgs = d3.select("body")
  .selectAll("svg")
  .data(nest)
  .enter()
  .append('svg')
  .attr("width", width)
  .attr("height", height + 20);

svgs.append("text")
  .attr('class', 'label')
  .data(nest)
  .attr('x', width / 2)
  .attr('y', height)
  .text(function(d) {
    return d.key;
  })
  .attr('text-anchor', 'middle')

svgs.selectAll("rect")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .filter(function(d, i) {
    const x = d3.select(this.parentNode).datum();
    return x.key == d.CategoryLevel1 ? 1 : 0;
  })
  .attr("height", function(d) {
    return 50;
  })
  .attr("width", "5")
  .attr("x", function(d, i) {
    return i * 10;
  })
  .attr("y", 0)

  .attr("fill", function(d) {
    return color(d.Manual)
  })

  .on("mouseover", function(d, i) {
    div.transition()
      .duration(200)
      .style("opacity", .9);
    div.html(`${d.Name}`)
      .style("left", (d3.event.pageX) + "px")
      .style("top", (d3.event.pageY - 50) + "px");
  })
  .on("mouseout", function(d) {
    div.transition()
      .duration(500)
      .style("opacity", 0);
  });
.page {
  width: 90%;
  margin: auto;
}

.menu {
  height: 100px;
  background-color: #B2D6FF;
  /* Medium blue */
}

.sidebar {
  height: 50px;
  width: 15%;
  background-color: #F09A9D;
  float: inline-start;
  display: block;
  margin: 0.1%;
  /* Red */
}

.title {
  width: 100%;
  background-color: none;
  display: inline-block;
  float: inline-start;
  /* Yellow */
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: auto;
  height: auto;
  padding: 3px;
  font: 12px sans-serif;
  border: 0px;
  border-radius: 3px;
  pointer-events: none;
  background: lightgrey;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Mapping Dog Care Manuals</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
</head>


</html>

What I have tried:

I tried creating svgs representing CategoryLevel2, then appending an "innerSVG" and running a code that would generate CategoryLevel1 svgs. The problem is in the filter line - it doesn't access the correct parent of CategoryLevel1:

.filter(function(d, i) {
    const x = d3.select(this.parentNode).datum();
    return x.key == d.CategoryLevel1 ? 1 : 0;
  })

I also tried using the "transform, translate" function to separate the rectangles based on Categorylevel1, but rejected this because it would be tricky to move the text associated with CategoryLevel1.

I'm now working on trying to use one of the d3.hierarchy layouts. The problem is that once I apply d3.stratify to the dataset, the results cannot be used to generate a series of svgs. That is to say, nothing shows up in the DOM when the following code is applied: (FYI I also replaced treeData with root.descendants() etc -

var treeData = d3.stratify()
  .id(function(d) { return d.CategoryLevel1; })
  .parentId(function(d) { return d.CategoryLevel2; })
  (data);

  var svgs = d3.select("chart")
    .selectAll("svg")
    .data(treeData)
    .enter()
    .append('svg')
    .attr("width", width)
    .attr("height", height + 20);



from How do I position subgroups of small multiples together on the page?

No comments:

Post a Comment