gpt4 book ai didi

javascript - D3 分组条形图不沿 x 比例分布

转载 作者:行者123 更新时间:2023-12-05 04:53:47 26 4
gpt4 key购买 nike

我正在尝试按城市创建一个包含 3 个类别的分组条形图,但它只绘制了一个组,而所有其他组都处于相同的位置,因此它们彼此重叠。它不会占用整个宽度,也不会沿 x 比例展开。我的 x0 和 x1 秤有问题。如果我理解正确,x0 是图表中矩形的开始位置,x1 比例是矩形的结束位置?你能解释一下我在这里做错了什么吗?

这是问题的一个片段:

const groupedBarChartData = {
dataset: [
{
City: 'York',
'Sales': 20000,
'Returns': 25000,
'Total': 22000,
},
{
City: 'London',
'Sales': 40000,
'Returns': 43000,
'Total': 45000,
},
{
City: 'Manchester',
'Sales': 40000,
'Returns': 7000,
'Total': 19999,
}]}


// svg dimensions
const width = 1192;
const height = 610;
const colorScale = d3
.scaleOrdinal()
.range(['red', 'blue', 'green', 'orange']);


const svg = d3.select('body').append('svg');

// shape data
const data = groupedBarChartData.dataset;

// get categories
const keys = Object.keys(data[0]).slice(1);

// x axis
const x0Scale = d3.scaleBand().rangeRound([0, width]);
const x1Scale = d3.scaleBand();

// set x0 - cities
x0Scale.domain(data.map((d) => d['City']));

// set x1 - categories
x1Scale.domain(keys).rangeRound([0, x0Scale.bandwidth()]);

// y axis
const yScale = d3.scaleLinear().range([height, 0]);

// equal to Math.round(data.map((x) => Math.max(...keys.map((el) => x[el]))).sort((a, b) => b - a)[0])
yScale.domain([
0,
Math.round(d3.max(data, (d) => d3.max(keys, (key) => d[key]))),
]);

// draw chart
svg
.selectAll('rect')
.data(data)
.enter()
.selectAll('rect')
.data((d) =>
keys.map((key) => {
return { key: key, value: d[key] };
})
)
.enter()
.append('rect')
.attr('x', (d, i) => x1Scale(d.key))
.attr('y', (d) => yScale(d.value))
.attr('width', x1Scale.bandwidth() - 15)
.attr('height', (d) => height - yScale(d.value))
.attr('fill', (d) => colorScale(d.key));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

它给我的结果是:

rect position

最佳答案

发生这种情况是因为您仅基于 x1Scale 定位矩形,而 x1Scale 仅基于类别定位:

  .attr('x', (d, i) => x1Scale(d.key))

你没有根据城市定位。

最常见的解决方案是使用父级 g 表示和定位父级城市,然后定位表示类别的条形:

    svg
.selectAll('rect')
.data(data)
.enter()
.append("g")
.attr("transform", d=>`translate(${x0Scale(d.City)},0)`)
.selectAll('rect')
...

这给了我们:

const groupedBarChartData = {
dataset: [
{
City: 'York',
'Sales': 20000,
'Returns': 25000,
'Total': 22000,
},
{
City: 'London',
'Sales': 40000,
'Returns': 43000,
'Total': 45000,
},
{
City: 'Manchester',
'Sales': 40000,
'Returns': 7000,
'Total': 19999,
}]}


// svg dimensions
const width = 1192;
const height = 610;
const colorScale = d3
.scaleOrdinal()
.range(['red', 'blue', 'green', 'orange']);


const svg = d3.select('body').append('svg').attr("width",width).attr("height",height);

// shape data
const data = groupedBarChartData.dataset;

// get categories
const keys = Object.keys(data[0]).slice(1);

// x axis
const x0Scale = d3.scaleBand().rangeRound([0, width]);
const x1Scale = d3.scaleBand();

// set x0 - cities
x0Scale.domain(data.map((d) => d['City']));

// set x1 - categories
x1Scale.domain(keys).rangeRound([0, x0Scale.bandwidth()]);

// y axis
const yScale = d3.scaleLinear().range([height, 0]);

// equal to Math.round(data.map((x) => Math.max(...keys.map((el) => x[el]))).sort((a, b) => b - a)[0])
yScale.domain([
0,
Math.round(d3.max(data, (d) => d3.max(keys, (key) => d[key]))),
]);

// draw chart
svg
.selectAll('rect')
.data(data)
.enter()
.append("g")
.attr("transform", d=>`translate(${x0Scale(d.City)},0)`)
.selectAll('rect')
.data((d) =>
keys.map((key) => {
return { key: key, value: d[key]};
})
)
.enter()
.append('rect')
.attr('x', (d, i) => x1Scale(d.key))
.attr('y', (d) => yScale(d.value))
.attr('width', x1Scale.bandwidth() - 15)
.attr('height', (d) => height - yScale(d.value))
.attr('fill', (d) => colorScale(d.key));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

或者,如果您不想要嵌套元素,您可以将城市信息传递给每个条形图的数据,并使用它来定位条形图和类别:

  .selectAll('rect')
.data((d) =>
keys.map((key) => {
return { key: key, value: d[key], city: d.City };
})
)
.enter()
.append('rect')
.attr('x', (d, i) => x1Scale(d.key)+x0Scale(d.city))
...

const groupedBarChartData = {
dataset: [
{
City: 'York',
'Sales': 20000,
'Returns': 25000,
'Total': 22000,
},
{
City: 'London',
'Sales': 40000,
'Returns': 43000,
'Total': 45000,
},
{
City: 'Manchester',
'Sales': 40000,
'Returns': 7000,
'Total': 19999,
}]}


// svg dimensions
const width = 1192;
const height = 610;
const colorScale = d3
.scaleOrdinal()
.range(['red', 'blue', 'green', 'orange']);


const svg = d3.select('body').append('svg').attr("width",width).attr("height",height);

// shape data
const data = groupedBarChartData.dataset;

// get categories
const keys = Object.keys(data[0]).slice(1);

// x axis
const x0Scale = d3.scaleBand().rangeRound([0, width]);
const x1Scale = d3.scaleBand();

// set x0 - cities
x0Scale.domain(data.map((d) => d['City']));

// set x1 - categories
x1Scale.domain(keys).rangeRound([0, x0Scale.bandwidth()]);

// y axis
const yScale = d3.scaleLinear().range([height, 0]);

// equal to Math.round(data.map((x) => Math.max(...keys.map((el) => x[el]))).sort((a, b) => b - a)[0])
yScale.domain([
0,
Math.round(d3.max(data, (d) => d3.max(keys, (key) => d[key]))),
]);

// draw chart
svg
.selectAll('rect')
.data(data)
.enter()
.selectAll('rect')
.data((d) =>
keys.map((key) => {
return { key: key, value: d[key], city: d.City };
})
)
.enter()
.append('rect')
.attr('x', (d, i) => x1Scale(d.key)+x0Scale(d.city))
.attr('y', (d) => yScale(d.value))
.attr('width', x1Scale.bandwidth() - 15)
.attr('height', (d) => height - yScale(d.value))
.attr('fill', (d) => colorScale(d.key));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

关于javascript - D3 分组条形图不沿 x 比例分布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65952477/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com