我是D3的新手,我遇到了一些问题.想知道是否有人可以提供帮助.
我正在尝试使用d3创建分组堆栈图表.图的性质是每个组有2个条,第二个的值取决于第一个条.我希望第二个栏能够分解我在第一个栏上的内容.一个简单的例子就是如果说第一个柱上的值{x: 0, y: 3, y0: 0},那么第二个柱应该是{x: 0, y: 1, y0: 0}, {x: 0, y: 1, y0: 1}, {x: 0, y: 1, y0: 2}
因此,对于将为第一个条形图绘制的数据:
{
"series": "A",
"values": [{
"x": 0,
"y": 1,
},
{
"x": 1,
"y": 2,
},
{
"x": 2,
"y": 3,
},
{
"x": 3,
"y": 1,
},
{
"x": 4,
"y": 3,
}
]},
{
"series": "B",
"values": [{
"x": 0,
"y": 3,
},
{
"x": 1,
"y": 1,
},
{
"x": 2,
"y": 1,
},
{
"x": 3,
"y": 5,
},
{
"x": 4,
"y": 1,
}]
}
Run Code Online (Sandbox Code Playgroud)
我会将第二个堆积条形图的值设为:
{
"series": "A",
"values":
[ { x: 0, y: 1, y0: 0 },
{ x: 1, y: 1, y0: 0 },
{ x: 1, y: 1, y0: 1 },
{ x: 2, y: 1, y0: 0 },
{ x: 2, y: 1, y0: 1 },
{ x: 2, y: 1, y0: 2 },
{ x: 3, y: 1, y0: 0 },
{ x: 4, y: 1, y0: 0 },
{ x: 4, y: 1, y0: 1 },
{ x: 4, y: 1, y0: 2 }]
},
{
"series": "B",
"values":
[
{ x: 0, y: 1, y0: 1 },
{ x: 0, y: 1, y0: 2 },
{ x: 0, y: 1, y0: 3 },
{ x: 1, y: 1, y0: 1 },
{ x: 2, y: 1, y0: 1 },
{ x: 3 y: 1, y0: 1 },
{ x: 3, y: 1, y0: 2 },
{ x: 3, y: 1, y0: 3 },
{ x: 3, y: 1, y0: 4 },
{ x: 3, y: 1, y0: 5 },
{ x: 4, y: 1, y0: 1 },
]
}
Run Code Online (Sandbox Code Playgroud)
我使用了一些代码,我可以从我看到的示例中找到并尝试使其工作.这是我到目前为止所能做到的:
我将不胜感激任何帮助.谢谢
这是我使用您提供的数据整理的小提琴:https://jsfiddle.net/thatoneguy/nrjt15aq/8/
数据 :
var data = [
{ x: 0, y: 1, yheight: 0 },
{ x: 1, y: 1, yheight: 0 },
{ x: 1, y: 1, yheight: 1 },
{ x: 2, y: 1, yheight: 0 },
{ x: 2, y: 1, yheight: 1 },
{ x: 2, y: 1, yheight: 2 },
{ x: 3, y: 1, yheight: 0 },
{ x: 4, y: 1, yheight: 0 },
{ x: 4, y: 1, yheight: 1 },
{ x: 4, y: 1, yheight: 2 }
];
Run Code Online (Sandbox Code Playgroud)
需要对这些数据进行排序,以便可以将其正确地输入到堆叠条形图中。例如,从此链接:https://bl.ocks.org/mbostock/3886208您可以看到数据如下所示(我将其转换为 json):
{
"State": "WA",
"Under 5 Years": 433119,
"5 to 13 Years": 750274,
"14 to 17 Years": 357782,
"18 to 24 Years": 610378,
"25 to 44 Years": 1850983,
"45 to 64 Years": 1762811,
"65 Years and Over": 783877
}
Run Code Online (Sandbox Code Playgroud)
你的地方是分开的。所以,我编辑了你的(目前是手工编辑的,但可以编写一个函数来做到这一点)。所以你的数据现在看起来像这样:
var data = [
{ x: 0, yHeight0: 1, yHeight1: 0, yHeight2: 0 },
{ x: 1, yHeight0: 1, yHeight1: 1, yHeight2: 0 },
{ x: 2, yHeight0: 1, yHeight1: 1, yHeight2: 2 },
{ x: 3, yHeight0: 1, yHeight1: 0, yHeight2: 0 },
{ x: 4, yHeight0: 1, yHeight1: 1, yHeight2: 2 }
]
Run Code Online (Sandbox Code Playgroud)
注意不同的yHeights. 这些代表了数据中的不同高度,但我已将它们全部分组。根据具有相同的 x 值对它们进行分组。
现在我需要一些时间来解释一切,但我会解释基础知识。
请记住,我已经脱离了上面链接的示例。该示例具有以下颜色域:
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
Run Code Online (Sandbox Code Playgroud)
他们知道他们将拥有多少个不同的堆栈。我暂时保留了这些,但可以更改。然后使用该比例赋予数据更多属性:
color.domain(d3.keys(data[4]).filter(function(key) {
return key !== "x";
}));
Run Code Online (Sandbox Code Playgroud)
上面的函数是返回所有不同的堆栈(在您的情况下是 yHeights )。下面的函数使用这些属性,并为您提供有助于确定这些堆栈的高度和 y 位置的属性。
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {
name: name,
y0: y0,
y1: y0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].y1;
});
Run Code Online (Sandbox Code Playgroud)
现在绘制它们:
var firstRects = state.selectAll("firstrect")
.data(function(d) {
return d.ages;
})
.enter().append("rect")
.attr("width", x.rangeBand() / 2)
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.style('stroke', 'black');
Run Code Online (Sandbox Code Playgroud)
这只为您提供了一个简单的堆积条形图,但您想要另一个带有数字的图表。因此,我通过将另一个条形图附加到同一轴来做到这一点,如下所示:
var secondRects = state.selectAll("secondrect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", barWidth)
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) {
if (y(d.y0) - y(d.y1)) d.barHeight = y(d.y0) - y(d.y1); //this sets a height variable to be used later
return y(d.y0) - y(d.y1);
})
.style("fill", 'white')
.style('stroke', 'black')
.attr("transform", function(d) {
return "translate(" + (x.rangeBand() / 2) + ",0)";
});
Run Code Online (Sandbox Code Playgroud)
现在来看一下这方面的数字:
var secondRectsText = state.selectAll("secondrecttext")
.data(function(d) {
for (i = 0; i < d.ages.length; i++) {
if (isNaN(d.ages[i].y0) || isNaN(d.ages[i].y1)) {
d.ages.splice(i--, 1);
}
}
console.log('dages', d.ages);
return d.ages;
})
.enter().append("text")
.attr("width", barWidth)
.attr("y", function(d) {
return y(d.y1);
})
.attr("transform", function(d) {
if(d.barHeight){ //if it hasnt got barheight it shouldnt be there
return "translate(" + (barWidth + barWidth / 2) + "," + d.barHeight/2 + ")";
} else {
return "translate(" + 5000 + "," + 5000 + ")";
}
})
.text(function(d, i) {
return i;
});
Run Code Online (Sandbox Code Playgroud)
检查数据设置以使其不使用任何空值。我可以继续解释我所做的事情,但希望您能够足够理解代码以将其实现到您的代码中。
从这里我将继续创建一个组织数据的函数,即将所有具有相同 x 值的值分组,这样您就不必手动编辑。
希望有帮助,再次为很长的答案道歉:P
这是所有代码,以防小提琴故障:
var data = [
{ x: 0, y: 1, yheight: 0 },
{ x: 1, y: 1, yheight: 0 },
{ x: 1, y: 1, yheight: 1 },
{ x: 2, y: 1, yheight: 0 },
{ x: 2, y: 1, yheight: 1 },
{ x: 2, y: 1, yheight: 2 },
{ x: 3, y: 1, yheight: 0 },
{ x: 4, y: 1, yheight: 0 },
{ x: 4, y: 1, yheight: 1 },
{ x: 4, y: 1, yheight: 2 }
];
Run Code Online (Sandbox Code Playgroud)
{
"State": "WA",
"Under 5 Years": 433119,
"5 to 13 Years": 750274,
"14 to 17 Years": 357782,
"18 to 24 Years": 610378,
"25 to 44 Years": 1850983,
"45 to 64 Years": 1762811,
"65 Years and Over": 783877
}
Run Code Online (Sandbox Code Playgroud)
var data = [
{ x: 0, yHeight0: 1, yHeight1: 0, yHeight2: 0 },
{ x: 1, yHeight0: 1, yHeight1: 1, yHeight2: 0 },
{ x: 2, yHeight0: 1, yHeight1: 1, yHeight2: 2 },
{ x: 3, yHeight0: 1, yHeight1: 0, yHeight2: 0 },
{ x: 4, yHeight0: 1, yHeight1: 1, yHeight2: 2 }
]
Run Code Online (Sandbox Code Playgroud)
编辑 :
这是小提琴,它可以从提供的图像中准确地为您提供所需的内容(有点hacky,但它有效:)): https: //jsfiddle.net/thatoneguy/nrjt15aq/10/
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
Run Code Online (Sandbox Code Playgroud)
color.domain(d3.keys(data[4]).filter(function(key) {
return key !== "x";
}));
Run Code Online (Sandbox Code Playgroud)
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {
name: name,
y0: y0,
y1: y0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].y1;
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
601 次 |
| 最近记录: |