我试图用D3.js的这个streamgraph布局做一些例子。我的数据有这种格式。因此,我的对象具有国家名称的对象,而在这些对象中,我有几个每月具有不同值的数组和每个月的日期(" Datum")
{
"Irak": {
"Asylberechtigt": [
65,
60,
54,
47,
47,
30,
25,
21,
12,
6
],
"EntscheidungenInsgesamt": [
8645,
7559,
6533,
5425,
4351,
3336,
2643,
2022,
1270,
645
],
"InsgesamtMonat": [
1086,
1026,
1108,
1074,
1015,
693,
621,
752,
625,
645
],
"Datum": [
"2015-10-01",
"2015-09-01",
"2015-08-01",
"2015-07-01",
"2015-06-01",
"2015-05-01",
"2015-04-01",
"2015-03-01",
"2015-02-01",
"2015-01-01"
]
},
"Mazedonien": {
"Asylberechtigt": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"EntscheidungenInsgesamt": [
4734,
4091,
3527,
3268,
2715,
2238,
1923,
1489,
1094,
604
],
"InsgesamtMonat": [
643,
564,
259,
553,
477,
315,
434,
395,
490,
604
],
"Datum": [
"2015-10-01",
"2015-09-01",
"2015-08-01",
"2015-07-01",
"2015-06-01",
"2015-05-01",
"2015-04-01",
"2015-03-01",
"2015-02-01",
"2015-01-01"
]
}
}
对于流程图,我需要.values,我理解它必须返回一些x和y值我用这个函数访问(0例如是Irak,但最后我必须遍历所有国家) 。我认为这不是永久的解决方案。但是我的数据一般应该是什么样的,因为我意识到嵌套对我来说非常混乱。 那么需要什么结构才能使用这些函数来显示流图?
var stack = d3.layout.stack()
.offset("wiggle")
.values(function(d){
for (var i = 0; i < d[countries[0]].Datum.length; i++) {
var dx = d[countries[0]].Datum[i];
var dy = d[countries[0]].InsgesamtMonat[i];
//console.log("Countries with InsgesamtMonat "+ countries[i]+" "+test);
dStack[i] = { x: dx, y: dy};
}
return dStack;
});
//.values(function(d) { return d[countries[0]].values; })
.x(function(d) { return d[countries[0]].Datum; })
.y(function(d) { return d[countries[0]].InsgesamtMonat; });
我还需要.x和.y吗?
这是我的完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing Streamgraph</title>
<link rel="stylesheet" href="main.css">
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<!--Place all DOM elements here -->
<script>
d3.json("data.json", function(error, data){
console.log(data)
plot(data);
//console.log(data);
})
function plot(data) {
var dStack = [];
var w = 800;
var h = 450;
var margin = {
top: 100,
bottom: 0,
left: 80,
right: 40
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dateParser = d3.time.format("%Y-%m-%d").parse;
var colorScale = d3.scale.category20();
var n = Object.keys(data).length;
var m = 10 // number of samples per layer
//console.log(data[Object.keys("Asylberechtigt")[13]])
//var test = Object.keys(data).Asylberechtigt;
var countries = Object.keys(data);
console.log(countries);
var stack = d3.layout.stack()
.offset("wiggle")
.values(function(d){
for (var i = 0; i < d[countries[0]].Datum.length; i++) {
var dx = d[countries[0]].Datum[i];
var dy = d[countries[0]].InsgesamtMonat[i];
//console.log("Countries with InsgesamtMonat "+ countries[i]+" "+test);
dStack[i] = { x: dx, y: dy};
}
return dStack;
});
//.values(function(d) { return d[countries[0]].values; })
.x(function(d) { return d[countries[0]].Datum; })
.y(function(d) { return d[countries[0]].InsgesamtMonat; });
var nest = d3.nest()
.key(function(d) { return d.countries });
console.log(nest);
var area = d3.svg.area()
.interpolate("cardinal")
.x(function(d){
var xStack = []
for (var i = 0; i < d[countries[0]].Datum.length; i++) {
var dx = d[countries[0]].Datum[i];
xStack[i] = dx;
}
return xStack })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var layers = stack(nest.countries(data)); //Do i need to nest again because i already have the Countries as objects
var x = d3.time.scale()
.domain(d3.extent(data, function(d, i){
var date = dateParser(Object.keys(d).Datum(i)); // Do't know if this is legit either
// date= 0;
return date;
}))
.range([0+margin.left,width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d){
return d.value;
})])
.range([height,0+margin.top]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
//enter()
svg.selectAll(".point")
.data(layers)
.enter()
}
</script>
</body>
</html>
&#13;
我不知道如何为我的数据声明图层,你能帮我解决这个问题吗?
答案 0 :(得分:1)
我支持这个问题,主要是出于无聊,但我认为我的评论中有点苛刻。正如我所说,你的数据有太多的“by”变量,所以让我们假设我们想要按照国家流式传输“InsgesamtMonat”,“EntscheidungenInsgesamt”等可选过滤器......所以问题就变成了我们如何获得这些数据在 JavaScript 中采用d3.layout.stack
将理解的格式?
// give a stack defined as...
var stack = d3.layout.stack()
.offset("wiggle")
.values(function(d) {
return d.values;
});
// convert data
// varToStackOn is "EntscheidungenInsgesamt"
var properData = [];
for (country in json) {
var obj = {};
obj.name = country;
obj.values = [];
json[country][varToStackOn].forEach(function(d, i) {
obj.values.push({
x: format.parse(json[country]["Datum"][i]),
y: d
});
})
properData.push(obj);
}
// and stack it
var stackedData = stack(properData);
完成后,按照示例变得容易。
这一切都在一起:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.chart {
background: #fff;
}
p {
font: 12px helvetica;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
stroke-width: 2px;
shape-rendering: crispEdges;
}
button {
position: absolute;
right: 50px;
top: 10px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<div class="chart">
</div>
<script>
var json = {
"Irak": {
"Asylberechtigt": [65, 60, 54, 47, 47, 30, 25, 21, 12, 6],
"EntscheidungenInsgesamt": [8645, 7559, 6533, 5425, 4351, 3336, 2643, 2022, 1270, 645],
"InsgesamtMonat": [1086, 1026, 1108, 1074, 1015, 693, 621, 752, 625, 645],
"Datum": ["2015-10-01", "2015-09-01", "2015-08-01", "2015-07-01", "2015-06-01", "2015-05-01", "2015-04-01", "2015-03-01", "2015-02-01", "2015-01-01"]
},
"Mazedonien": {
"Asylberechtigt": [50, 20, 10, 14, 10, 6, 18, 32, 30, 12],
"EntscheidungenInsgesamt": [4734, 4091, 3527, 3268, 2715, 2238, 1923, 1489, 1094, 604],
"InsgesamtMonat": [643, 564, 259, 553, 477, 315, 434, 395, 490, 604],
"Datum": ["2015-10-01", "2015-09-01", "2015-08-01", "2015-07-01", "2015-06-01", "2015-05-01", "2015-04-01", "2015-03-01",
"2015-02-01", "2015-01-01"
]
}
}
var format = d3.time.format("%Y-%d-%m");
var stack = d3.layout.stack()
.offset("wiggle")
.values(function(d) {
return d.values;
});
var width = 300,
height = 300;
var x = d3.time.scale()
.range([0, width])
.domain(d3.extent(["2015-10-01", "2015-09-01", "2015-08-01", "2015-07-01", "2015-06-01", "2015-05-01", "2015-04-01", "2015-03-01", "2015-02-01", "2015-01-01"], function(d) {
return format.parse(d);
}));
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10()
var area = d3.svg.area()
.x(function(d) {
return x(d.x);
})
.y0(function(d) {
return y(d.y0);
})
.y1(function(d) {
return y(d.y0 + d.y);
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var stackOn = "InsgesamtMonat";
setInterval(function(){
if (stackOn === "InsgesamtMonat")
stackOn = "EntscheidungenInsgesamt";
else if (stackOn === "Asylberechtigt")
stackOn = "InsgesamtMonat";
else if (stackOn === "EntscheidungenInsgesamt")
stackOn = "Asylberechtigt";
updateGraph(stackOn);
}, 1000);
function updateGraph(varToStackOn) {
var properData = [];
for (country in json) {
var obj = {};
obj.name = country;
obj.values = [];
json[country][varToStackOn].forEach(function(d, i) {
obj.values.push({
x: format.parse(json[country]["Datum"][i]),
y: d
});
})
properData.push(obj);
}
var stackedData = stack(properData);
y.domain([0, d3.max(stackedData, function(layer) {
return d3.max(layer.values, function(d) {
return d.y0 + d.y;
});
})]);
var paths = svg.selectAll("path")
.data(stack(properData))
paths
.enter().append("path")
.style("fill", function(d, i) {
return color(i);
});
paths.transition()
.attr("d", function(d) {
return area(d.values);
});
}
</script>
</body>
</html>