'Is there a way to create different d3 axis for unique groups in the data? (d3.js)
I am trying to create multiarray joy plot for some data, but I struggle to make a proper axis. I am facing the problem that each column in the joy plot needs its specific scale domain because the data is different from the other columns.
The way I have coded the plot is to group the data with d3.groups() and then build the structure of the joy plot with this approach. However, using this approach, I can create the plot but not draw the axis. Is there a way to accomplish this?
My first thought was that I could pass the data (mapped to .data()) to .call(). In the function that .call() calls, I could include some code that creates the scale and axis for each array in the joy plot. However, this doesnt seem to work because the function that .call calls doesn
t have access to the data.
Here are some example data and the plot that generates the plot:
const width = window.innerWidth * 0.9;
const height = window.innerHeight * 0.9;
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 20,
};
const groups = 2;
const padding = 10;
const paddingZ = 200;
const gWidth = width - margin.left - margin.right;
const gHeight = height - margin.top - margin.bottom;
const histogramHeight = (padding + gHeight + padding) / groups;
const histogramWidth = (padding + gWidth + padding) / groups;
const histogramZheight = (paddingZ + histogramHeight + paddingZ) / 3;
const svg = d3
.select("body")
.append("svg")
.attr("height", height)
.attr("width", width);
const g = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const main = async () => {
data = [
{bib: 1, split: 1, course: "A", performance: 2.4},
{bib: 1, split: 1, course: "B", performance: 7},
{bib: 1, split: 2, course: "A", performance: 2.7},
{bib: 1, split: 2, course: "B", performance: 8},
{bib: 2, split: 1, course: "A", performance: 2.9},
{bib: 2, split: 1, course: "B", performance: 5.0},
{bib: 2, split: 2, course: "A", performance: 9},
{bib: 2, split: 2, course: "B", performance: 6},
{bib: 2, split: 2, course: "A", performance: 3},
{bib: 1, split: 2, course: "A", performance: 3},
{bib: 1, split: 2, course: "B", performance: 1.2},
{bib: 2, split: 1, course: "B", performance: 3},
]
const dataGrouped = d3.groups(
data,
(d) => d.day,
(d) => d.split,
(d) => d.course
);
const cellX = g
.selectAll(".cell")
.data(dataGrouped)
.join("g")
.attr("class", "cellX")
.attr("transform", (d) => console.log(d))
.attr(
"transform",
(d, i) => `translate(0, ${i * (padding + histogramHeight + padding)})`
);
const cellY = cellX
.selectAll(".cellX")
.data((d) => d[1])
.join("g")
.attr("class", "cellXY")
.attr(
"transform",
(d, i) => `translate(${i * (padding + histogramWidth + padding)},0)` //${ i * (padding + histogramWidth + padding)},0)`
);
const cellZ = cellY
.selectAll(".cellXY")
.data((d) => d[1])
.join("g")
.attr("class", "cellZ")
.attr(
"transform",
(d, i) => `translate(0, ${i <= 2 ? i * paddingZ : i * (paddingZ)})` //(0, ${i * (paddingZ + histogramZheight + paddingZ)})`
);
const path = cellZ
.selectAll(".lo")
.data((d) => d)
.join("path")
.attr("d", (d) => {
const xScale = d3
.scaleLinear()
.domain([-3, 40])
.range([0, histogramWidth]);
console.log(xScale.domain());
const bingenerator = d3
.bin()
.domain(xScale.domain())
.value((d) => d.performance);
const binnedData = bingenerator(d);
const topHistogramYscale = d3
.scaleLinear()
.domain(d3.extent(binnedData, (d) => d.length))
.range([histogramZheight, 0]);
const xAxis = d3.axisBottom().scale(xScale);
const topHistogramLineGenerator = d3
.area()
.x((d) => xScale(d.x0))
.y0(histogramZheight)
.y1((d) => topHistogramYscale(d.length))
.curve(d3.curveBasis);
return topHistogramLineGenerator(binnedData);
})
}
main();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|