有没有办法为数据中的唯一组创建不同的D3轴? (d3.js)
我正在尝试为某些数据创建Multiarray 欢乐情节,但我很难制定一个适当的轴。我面临一个问题,即Joy图中的每一列都需要其特定的比例域,因为数据与其他列不同。
我编码的方式是将数据与d3.groups()分组,然后使用此方法构建欢乐图的结构。但是,使用这种方法,我可以创建图,但不能绘制轴。有没有办法实现这一目标?
我的第一个想法是,我可以将数据(将.data())映射到.call()。在.call()调用的函数中,我可以包含一些代码,这些代码在Joy图中为每个数组创建规模和轴。但是,这似乎不起作用,因为.call调用的函数 t可以访问数据。
以下是一些示例数据和生成图的图:
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();
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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论