如何使这个D3水平条形图工作



最近我开始学习D3.js v5,我必须制作不同种类的图。其中一张图是堆叠的水平条形图。我遵循了Udemy的教程,但我无法使这个图表发挥作用。

有人能帮我吗?

所以,我知道d3使用堆栈生成器来生成堆栈条形图。我使用了它,并在控制台中检查了值,看起来数据格式很好,可以开始生成堆叠条形图,但我似乎不明白为什么它不起作用。

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

<script type="text/javascript">
var Margin = {top: 30, right: 20, bottom: 40, left: 110};
var InnerWidth = 432 - Margin.left - Margin.right;
var InnerHeight = 432 - Margin.top - Margin.bottom;
var diff_variant=[{Missense_Mutation: 5, Silent: 4, Splice_Site: 0},
{Missense_Mutation: 8, Splice_Site: 0, Silent: 0},
{Splice_Site: 4, Missense_Mutation: 4, Silent: 0},
{Missense_Mutation: 4, Silent: 1, Splice_Site: 0},
{Missense_Mutation: 5, Splice_Site: 0, Silent: 0},
{Missense_Mutation: 5, Splice_Site: 0, Silent: 0},
{Missense_Mutation: 4, Splice_Site: 0, Silent: 0},
{Missense_Mutation: 4, Splice_Site: 0, Silent: 0},
{Silent: 1, Missense_Mutation: 1, Splice_Site: 0},
{Missense_Mutation: 1, Splice_Site: 0, Silent: 0}];
var data1=[{name: "Missense_Mutation", count: 41},
{name: "Silent", count: 6},
{name: "Splice_Site", count: 4}];
var variant_name=["Missense_Mutation", "Splice_Site", "Silent"];
var stack = d3.stack().keys(variant_name);
var x = d3.scaleLinear()
.domain([0, d3.max(data1, function(d){return d.count;})])
.range([0,InnerWidth]);
var x_axis = d3.scaleLinear()
.domain([0, d3.max(data1, function(d){return d.count;})])
.range([0,InnerWidth]);
var y_axis = d3.scaleLinear()
.domain([0, data1.length])
.range([0,InnerWidth]);
var y = d3.scaleBand()
.domain(data1.map(function(d){return d.name;}))
.rangeRound([0,InnerHeight])
.padding(0.1);
var svg5 = d3.select("body").append("svg")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", `0 0 ${InnerWidth + Margin.left + Margin.right} ${InnerHeight + Margin.top + Margin.bottom}`)
.style("background","lightblue")
.append("g")
.attr("transform", "translate(" + Margin.left + "," + Margin.top + ")");
svg5.append("g").style("font", "12px sans").call(d3.axisLeft(y));
svg5.append("g").attr('transform', `translate(0, ${InnerHeight})`).style("font", "12px times").call(d3.axisBottom(x_axis));

var series = svg5.selectAll("g").data(stack(diff_variant))
.enter().append("g")
.style("fill", (d,i)=>d3.schemeSet3[i]);
series.selectAll("rect").data(function(d){return d;})
.enter().append("rect")
.attr("height", 25)
.attr("width", function(d){return x(d[1]) - x(d[0]);})
.attr("x", function(d){return x(d[0]);})
.attr("y", function(d,i){return i*40;});
</script>
</html>

当您执行此操作时。。。

var series = svg5.selectAll("g")//etc...

您正在选择SVG(两个轴(中已经存在的<g>元素,并将数据绑定到它们。这就是为什么你的输入选择是空的。

您可以选择null(点击此处了解更多信息(:

var series = svg5.selectAll(null)

或者,您可以通过类进行选择,稍后在输入选择中设置:

var series = svg5.selectAll(".foo")

然而,最好的解决方案是将轴的组移到底部:这不仅可以解决您的问题,还可以在矩形上方绘制轴。

这是您更改后的代码:

<html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<body></body>
<script type="text/javascript">
var Margin = {
top: 30,
right: 20,
bottom: 40,
left: 110
};
var InnerWidth = 432 - Margin.left - Margin.right;
var InnerHeight = 432 - Margin.top - Margin.bottom;
var diff_variant = [{
Missense_Mutation: 5,
Silent: 4,
Splice_Site: 0
},
{
Missense_Mutation: 8,
Splice_Site: 0,
Silent: 0
},
{
Splice_Site: 4,
Missense_Mutation: 4,
Silent: 0
},
{
Missense_Mutation: 4,
Silent: 1,
Splice_Site: 0
},
{
Missense_Mutation: 5,
Splice_Site: 0,
Silent: 0
},
{
Missense_Mutation: 5,
Splice_Site: 0,
Silent: 0
},
{
Missense_Mutation: 4,
Splice_Site: 0,
Silent: 0
},
{
Missense_Mutation: 4,
Splice_Site: 0,
Silent: 0
},
{
Silent: 1,
Missense_Mutation: 1,
Splice_Site: 0
},
{
Missense_Mutation: 1,
Splice_Site: 0,
Silent: 0
}
];
var data1 = [{
name: "Missense_Mutation",
count: 41
},
{
name: "Silent",
count: 6
},
{
name: "Splice_Site",
count: 4
}
];
var variant_name = ["Missense_Mutation", "Splice_Site", "Silent"];
var stack = d3.stack().keys(variant_name);
var x = d3.scaleLinear()
.domain([0, d3.max(data1, function(d) {
return d.count;
})])
.range([0, InnerWidth]);
var x_axis = d3.scaleLinear()
.domain([0, d3.max(data1, function(d) {
return d.count;
})])
.range([0, InnerWidth]);
var y_axis = d3.scaleLinear()
.domain([0, data1.length])
.range([0, InnerWidth]);
var y = d3.scaleBand()
.domain(data1.map(function(d) {
return d.name;
}))
.rangeRound([0, InnerHeight])
.padding(0.1);
var svg5 = d3.select("body").append("svg")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", `0 0 ${InnerWidth + Margin.left + Margin.right} ${InnerHeight + Margin.top + Margin.bottom}`)
.style("background", "lightblue")
.append("g")
.attr("transform", "translate(" + Margin.left + "," + Margin.top + ")");
var series = svg5.selectAll("g").data(stack(diff_variant))
.enter().append("g")
.style("fill", (d, i) => d3.schemeSet3[i]);
series.selectAll("rect").data(function(d) {
return d;
})
.enter().append("rect")
.attr("height", 25)
.attr("width", function(d) {
return x(d[1]) - x(d[0]);
})
.attr("x", function(d) {
return x(d[0]);
})
.attr("y", function(d, i) {
return i * 40;
});
svg5.append("g").style("font", "12px sans").call(d3.axisLeft(y));
svg5.append("g").attr('transform', `translate(0, ${InnerHeight})`).style("font", "12px times").call(d3.axisBottom(x_axis));
</script>
</html>

最新更新