0

我试图用这个 D3.js 的流图布局做一些例子。我的数据有这种格式。所以我的对象在这些对象中有带有国家名称和名称的对象我有几个数组,每个月都有不同的值和每个月的日期(“基准”)

{
"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 是伊拉克,但最后我必须遍历所有国家/地区)。我认为这不是永久的解决方案。但是我的数据一般应该是什么样子,因为我意识到嵌套对我来说非常混乱。那么需要什么结构才能使用这些函数来可视化流图?

    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>

我不知道如何准确地为我的数据声明图层,你能帮我吗?

4

1 回答 1

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>

于 2015-12-18T20:10:23.527 回答