我正在try 为性能测试结果创建分组条形图.这是我第一次使用D3.
X轴应该显示parallelism
,这是使用的线程数和Y图表持续时间(毫秒).如果有多条记录对应于相同的X值(相同的并行度),则它们应该相邻出现,最好是按持续时间排序,但这并不重要.
我的灵感来自以下代码:https://observablehq.com/@d3/grouped-bar-chart/2?intent=fork
我花了一个多小时摆弄它,但我仍然没有正确地进行分组.这个问题当然是由我如何定义fx
和x
函数以及如何分配.attr("x", d => marginLeft+fx(d.duration))
引起的.我try 了许多不同的版本,但都没有效果.
const runData = [
{"duration":74950.52171194553,"parallelism":1},
{"duration":88687.86499893665,"parallelism":0,"exitCode":0},
{"duration":60000,"parallelism":1,"exitCode":0},
{"duration":90000,"parallelism":0,"exitCode":0},
{"duration":90000,"parallelism":0,"exitCode":0}
];
const width = 700;
const height = 400;
const marginTop = 10;
const marginRight = 10;
const marginBottom = 20;
const marginLeft = 40;
// Create the SVG container.
const svg = d3.select("#ca")
.append("svg")
.attr("width", width)
.attr("height", height);
const paralelismSet = new Set(runData.map(x=>x.parallelism));
const paralelismList = runData.map(x=>x.parallelism);
paralelismList.sort();
const durationSet = new Set(runData.map(x=>x.duration));
const minDuration = Math.min(...durationSet);
const maxDuration = Math.max(...durationSet);
// I am trying here to sort by duration but group by parallelism
const fx = d3.scaleBand()
.domain(durationSet)
.rangeRound([marginLeft, width - marginRight])
.paddingInner(0.1);
const x = d3.scaleBand()
.domain(paralelismList)
.rangeRound([0, fx.bandwidth()])
.padding(0.05);
const color = d3.scaleLinear([minDuration, maxDuration], ["green", "red"]);
// Y encodes the height of the bar.
const y = d3.scaleLinear()
.domain([0, maxDuration]).nice()
.rangeRound([height - marginBottom, marginTop]);
svg.append("g")
.selectAll()
.data(d3.group(runData, d => d.parallelism))
.join("g")
.attr("transform", ([paralelism]) => `translate(${x(paralelism)},0)`)
.selectAll()
.data(([, d]) => d)
.join("rect")
// I tried various combinations of subtracting fx from x and vice versa
.attr("x", d => marginLeft+fx(d.duration))
.attr("y", d => y(d.duration))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.duration))
.attr("fill", d => color(d.duration));
// The horizontal axis does not work well either, it is too short
svg.append("g")
.attr("transform", `translate(${marginLeft},${height - marginBottom})`)
.call(d3.axisBottom(x));
// This code works fine
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(d3.axisLeft(y).ticks(null, "s"))
.call(g => g.selectAll(".domain").remove());
<div id="ca">
</div>
<script src="https://d3js.org/d3.v6.min.js"></script>