gpt4 book ai didi

javascript - d3 v4 从 CSV 堆叠到分组条形图

转载 作者:行者123 更新时间:2023-11-30 06:24:05 26 4
gpt4 key购买 nike

引用 Mike Bostick's Stacked to Grouped Bar Chart example ,我正在修改它以使用 CSV 文件。我已经为此工作了几个星期,并且查看了 Stack Overflow 和其他地方的无数示例,但被难住了。

堆叠条形图有效。

堆积条形图:

Stacked Bar Chart

当我转换到分组条形图时,我只遇到引用堆叠或分组的键或系列的问题。现在所有的矩形都显示在彼此之上而不是彼此相邻。

分组条形图:

Grouped Bar Chart

在函数 transitionStep2() 中,我想乘以对应于系列或键的数字。我目前在这个函数中乘以数字 1 作为占位符 .attr("x", function(d) { return x(d.data.Year) + x.bandwidth()/7 * 1; } )

<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<html><body>

<form>
<label><input type="radio" name="mode" style="margin-left: 10" value="step1" checked>1</label>
<label><input type="radio" name="mode" style="margin-left: 20" value="step2">2</label>
</form>

<svg id = "bar" width = "500" height = "300"></svg>
<script>
var svg = d3.select("#bar"),
margin = {top: 20, right: 20, bottom: 20, left: 20},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.08);

var y = d3.scaleLinear()
.range([height, 0]);

var color = d3.scaleOrdinal()
.range(["#7fc97f", "#beaed4", "#fdc086", "#ffff99"]);

d3.csv("data.csv", function(d, i, columns) {
for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
d.total = t;
return d;
}, function(error, data) {
if (error) throw error;

var keys = data.columns.slice(1);

x.domain(data.map(function(d) { return d.Year; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
color.domain(keys);

g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) { return color(d.key); })
.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.data.Year); })
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
.attr("width", x.bandwidth());

rect = g.selectAll("rect");
});

d3.selectAll("input")
.on("change", changed);

function changed() {
if (this.value === "step1") transitionStep1();
else if (this.value === "step2") transitionStep2();
}

function transitionStep1() {
rect.transition()
.attr("y", function(d) { return y(d[1]); })
.attr("x", function(d) { return x(d.data.Year); })
.attr("width", x.bandwidth())
.attr("stroke", "green");
}

function transitionStep2() {
rect.transition()
.attr("x", function(d) { return x(d.data.Year) + x.bandwidth() / 7 * 1; })
.attr("width", x.bandwidth() / 7)
.attr("y", function(d) { return y(d[1] - d[0]); })
.attr("stroke", "red");
}
</script></body></html>

和 csv 文件:

Year,A,B,C,D
1995,60,47,28,39
1996,29,56,99,0
1997,30,26,63,33
1998,37,16,48,0
1999,46,49,64,21
2000,78,88,81,57
2001,18,11,11,64
2002,91,76,79,64
2003,30,99,96,79

最佳答案

您所指的示例具有线性值以将图表分组,因此 .attr("x", function(d, i) { return x(i) + x.bandwidth()/n * this.parentNode.__data__.key; }) 工作正常。

在您的情况下,列/键 不是线性标度,而是您必须为其设置标度的序数值集:

引用simple d3 grouped bar chart

要做到这一点,即设置一个序数标度,可以执行以下操作:

var x1 = d3.scaleBand();
x1.domain(keys).rangeRound([0, x.bandwidth()]);

所以这个新比例尺的范围是 x 比例尺的带宽,域为 ["A", "B", "C", "D"]。使用此比例设置 rectx 属性以对它们进行分组:

.attr("x", function(d) { 
return x(d.data.Year) + x1(d3.select(this.parentNode).datum().key);
})

其中 d3.select(this.parentNode).datum().key 代表列名。

这是 JSFIDDLE (我已经使用 d3.csvParse 来解析数据,但我相信您会明白这里的意思。这只是您需要重置的 x 属性。

这是一个 Plunkr使用文件。

这里还有一个代码片段:

  var svg = d3.select("#bar"),
margin = {top: 20, right: 20, bottom: 20, left: 20},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.08);

var x1 = d3.scaleBand();

var y = d3.scaleLinear()
.range([height, 0]);

var color = d3.scaleOrdinal()
.range(["#7fc97f", "#beaed4", "#fdc086", "#ffff99"]);

var csv = 'Year,A,B,C,D\n1995,60,47,28,39\n1996,29,56,99,0\n1997,30,26,63,33\n1998,37,16,48,0\n1999,46,49,64,21\n2000,78,88,81,57\n2001,18,11,11,64\n2002,91,76,79,64\n2003,30,99,96,79';

var data = d3.csvParse(csv), columns = ["A", "B", "C", "D"];

data.forEach(function(d) {
for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
d.total = t;
});

var keys = columns;

x.domain(data.map(function(d) { return d.Year; }));
x1.domain(keys).rangeRound([0, x.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
color.domain(keys);

g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) { return color(d.key); })
.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.data.Year); })
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
.attr("width", x.bandwidth());

rect = g.selectAll("rect");

d3.selectAll("input")
.on("change", changed);

function changed() {
if (this.value === "step1") transitionStep1();
else if (this.value === "step2") transitionStep2();
}

function transitionStep1() {
rect.transition()
.attr("y", function(d) { return y(d[1]); })
.attr("x", function(d) { return x(d.data.Year); })
.attr("width", x.bandwidth())
.attr("stroke", "green");
}

function transitionStep2() {
rect.transition()
.attr("x", function(d) {
return x(d.data.Year) + x1(d3.select(this.parentNode).datum().key);
})
.attr("width", x.bandwidth() / 7)
.attr("y", function(d) { return y(d[1] - d[0]); })
.attr("stroke", "red");
}
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<html><body>

<form>
<label><input type="radio" name="mode" style="margin-left: 10" value="step1" checked>1</label>
<label><input type="radio" name="mode" style="margin-left: 20" value="step2">2</label>
</form>

<svg id = "bar" width = "500" height = "300"></svg>

希望有所帮助。 :)

关于javascript - d3 v4 从 CSV 堆叠到分组条形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51506513/

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