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:
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