右 JSON Streamgraph 示例 D3 的格式结构

right JSON format structure for Streamgraph example D3

我试图用 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 并且我知道它必须 return 我正在使用此函数访问的一些 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>

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

我双重支持这个问题,主要是出于无聊,但我认为我的评论有点过于苛刻。正如我所说,您的数据有太多 "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>