简体   繁体   English

D3.js流图示例-生成正确的面积函数值

[英]D3.js streamgraph example - generating correct area function values

I'm new to d3js and trying to adapt the streamgraph example from here http://bl.ocks.org/mbostock/4060954 : 我是d3js的新手,并尝试从此处http://bl.ocks.org/mbostock/4060954改编流图示例:

在此处输入图片说明

...to work with my own data that tracks visitors to an art exhibition from different places (online, guestbook, museum). ...使用我自己的数据来跟踪来自不同地方(在线,访客留言簿,博物馆)的艺术展览的访客。 I've made some progress and I think my data's in the right format but I'm getting some really wonky final y values and my example isn't showing anything. 我已经取得了一些进展,我认为我的数据格式正确,但是我得到了一些非常奇怪的最终y值,并且我的示例没有显示任何内容。

My data starts as csv: 我的数据以csv开头:

index,date,venue,num_visitors
0,4/6/2013,online,3844
0,4/6/2013,museum,789
0,4/6/2013,guestbook,20
1,4/7/2013,online,217
1,4/7/2013,museum,718
1,4/7/2013,guestbook,20

And then I nest it to organize into 3 layers/streams by venue (online, museum, guestbook): 然后我将其嵌套以按场所(在线,博物馆,访客留言簿)分为3层/流:

layer0 = [
  {
    "key": "online",
    "values": [
      { "x": 0, "y":  3844},
      { "x": 1, "y": 217}
      etc

    ]
  },
  {  
    "key": "museum",
    "values": [
      { "x": 0, "y":  789},
      { "x": 1, "y": 718}
      etc
    ]
  }
];

When the page is generated the y values are always 800 and the svg path objects measure 1400px width and 0 height. 生成页面时,y值始终为800,svg路径对象的宽度为1400px,高度为0。 I'm not sure if this is a problem with how I'm scaling the input domain to the output range or if it's a problem with how the area function is generating the y values. 我不确定这是我将输入域缩放到输出范围的方式是否有问题,还是面积函数如何生成y值是否有问题。 Here's a sample of what the point values show as for one of the generated paths: 这是关于生成的路径之一的点值显示的示例:

d="M0,800L17.72151898734177,800L35.44303797468354,800L53.164556962025316,800L70.88607594936708, etc"

Here's my full page - would REALLY appreciate some guidance as I feel like I'm missing something simple here. 这是我的整页-非常感谢您提供一些指导,因为我觉得这里缺少一些简单的东西。

<!DOCTYPE html>
<meta charset="utf-8">
<title>Streamgraph</title>
<style>

body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  margin: 0;
  position: relative;
  width: 1400px;
}

button {
  position: absolute;
  right: 10px;
  top: 10px;
}

</style>
<button onclick="transition()">Update</button>
<script src="d3.js"></script>
<script>

var format = d3.time.format("%m/%d/%Y");

d3.csv("streamdata.csv", function(error, data) {
        data.forEach(function(d) {
            d.date = format.parse(d.date);
            d.y = d.num_visitors;
            d.x = d.index;

        });
        window.data = data;

        drawVisitorStats();
});

function drawVisitorStats(){
    var nest = d3.nest()
           .key(function(d){ return d.venue});
    var n = window.data.length, // number of layers, online, guestbook & museum

        stack = d3.layout.stack().offset("wiggle").offset("zero")
          .values(function(d) { return d.values; }),

        //group data by venue
        layers0 = stack(nest.entries(data)),
        layers1 = stack(nest.entries(data));

    var m = layers0[0].values.length; // number of samples per layer

    var yDomain = d3.max(layers0.concat(layers1), function(layer) { 
        return d3.max(layer, 
            function(d) { 
              return d.y0 + d.y; 
            }); 
    });

    var width = 1400,
        height = 800;

    var x = d3.scale.linear()
    .domain([0, m - 1])
    .range([0, width]);

    var y = d3.scale.linear()
    .domain([0, yDomain])
    .range([height, 0]);

    var color = d3.scale.linear()
        .range(["#ff0c00", "#ffc000"]);

    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);

    svg.selectAll("path")
        .data(layers0)
      .enter().append("path")
        .attr("d", function(d) { return area(d.values); })
        .style("fill", function() { return color(Math.random()); });
}
function transition() {
  d3.selectAll("path")
      .data(function() {
        var d = layers1;
        layers1 = layers0;
        return layers0 = d;
      })
    .transition()
      .duration(2500)
      .attr("d", area);
}



</script>

And here is the data csv file 这是数据csv文件

index,date,venue,num_visitors
0,4/6/2013,online,3844
0,4/6/2013,museum,789
0,4/6/2013,guestbook,20
1,4/7/2013,online,217
1,4/7/2013,museum,718
1,4/7/2013,guestbook,20
2,4/8/2013,online,203
2,4/8/2013,museum,741
2,4/8/2013,guestbook,6
3,4/9/2013,online,1445
3,4/9/2013,museum,874
3,4/9/2013,guestbook,7
4,4/10/2013,online,3098
4,4/10/2013,museum,755
4,4/10/2013,guestbook,3
5,4/11/2013,online,744
5,4/11/2013,museum,368
5,4/11/2013,guestbook,6
6,4/12/2013,online,1342
6,4/12/2013,museum,826
6,4/12/2013,guestbook,17
7,4/13/2013,online,694
7,4/13/2013,museum,826
7,4/13/2013,guestbook,17
8,4/14/2013,online,213
8,4/14/2013,museum,261
8,4/14/2013,guestbook,7
9,4/15/2013,online,3215
9,4/15/2013,museum,776
9,4/15/2013,guestbook,14
10,4/16/2013,online,2663
10,4/16/2013,museum,331
10,4/16/2013,guestbook,12
11,4/17/2013,online,172
11,4/17/2013,museum,633
11,4/17/2013,guestbook,10
12,4/18/2013,online,4516
12,4/18/2013,museum,543
12,4/18/2013,guestbook,5
13,4/19/2013,online,988
13,4/19/2013,museum,792
13,4/19/2013,guestbook,19
14,4/20/2013,online,2556
14,4/20/2013,museum,663
14,4/20/2013,guestbook,0
15,4/21/2013,online,2814
15,4/21/2013,museum,449
15,4/21/2013,guestbook,18
16,4/22/2013,online,596
16,4/22/2013,museum,445
16,4/22/2013,guestbook,15
17,4/23/2013,online,4790
17,4/23/2013,museum,217
17,4/23/2013,guestbook,5
18,4/24/2013,online,733
18,4/24/2013,museum,655
18,4/24/2013,guestbook,12
19,4/25/2013,online,362
19,4/25/2013,museum,321
19,4/25/2013,guestbook,20
20,4/26/2013,online,637
20,4/26/2013,museum,420
20,4/26/2013,guestbook,3
21,4/27/2013,online,2916
21,4/27/2013,museum,910
21,4/27/2013,guestbook,6
22,4/28/2013,online,1097
22,4/28/2013,museum,468
22,4/28/2013,guestbook,0
23,4/29/2013,online,796
23,4/29/2013,museum,687
23,4/29/2013,guestbook,9
24,4/30/2013,online,821
24,4/30/2013,museum,951
24,4/30/2013,guestbook,12
25,5/1/2013,online,2466
25,5/1/2013,museum,810
25,5/1/2013,guestbook,6
26,5/2/2013,online,1005
26,5/2/2013,museum,291
26,5/2/2013,guestbook,19
27,5/3/2013,online,1243
27,5/3/2013,museum,446
27,5/3/2013,guestbook,5
28,5/4/2013,online,4623
28,5/4/2013,museum,538
28,5/4/2013,guestbook,0
29,5/5/2013,online,547
29,5/5/2013,museum,457
29,5/5/2013,guestbook,11
30,5/6/2013,online,4132
30,5/6/2013,museum,407
30,5/6/2013,guestbook,8
31,5/7/2013,online,3083
31,5/7/2013,museum,741
31,5/7/2013,guestbook,9
32,5/8/2013,online,2854
32,5/8/2013,museum,516
32,5/8/2013,guestbook,1
33,5/9/2013,online,2122
33,5/9/2013,museum,932
33,5/9/2013,guestbook,14
34,5/10/2013,online,587
34,5/10/2013,museum,701
34,5/10/2013,guestbook,0
35,5/11/2013,online,698
35,5/11/2013,museum,887
35,5/11/2013,guestbook,18
36,5/12/2013,online,3538
36,5/12/2013,museum,223
36,5/12/2013,guestbook,4
37,5/13/2013,online,2413
37,5/13/2013,museum,799
37,5/13/2013,guestbook,13
38,5/14/2013,online,3581
38,5/14/2013,museum,744
38,5/14/2013,guestbook,7
39,5/15/2013,online,1750
39,5/15/2013,museum,845
39,5/15/2013,guestbook,17
40,5/16/2013,online,3025
40,5/16/2013,museum,630
40,5/16/2013,guestbook,10
41,5/17/2013,online,2038
41,5/17/2013,museum,342
41,5/17/2013,guestbook,7
42,5/18/2013,online,148
42,5/18/2013,museum,447
42,5/18/2013,guestbook,20
43,5/19/2013,online,886
43,5/19/2013,museum,755
43,5/19/2013,guestbook,20
44,5/20/2013,online,1168
44,5/20/2013,museum,305
44,5/20/2013,guestbook,10
45,5/21/2013,online,190
45,5/21/2013,museum,378
45,5/21/2013,guestbook,11
46,5/22/2013,online,1416
46,5/22/2013,museum,276
46,5/22/2013,guestbook,13
47,5/23/2013,online,1753
47,5/23/2013,museum,380
47,5/23/2013,guestbook,7
48,5/24/2013,online,2573
48,5/24/2013,museum,221
48,5/24/2013,guestbook,17
49,5/25/2013,online,2425
49,5/25/2013,museum,610
49,5/25/2013,guestbook,11
50,5/26/2013,online,3359
50,5/26/2013,museum,492
50,5/26/2013,guestbook,1
51,5/27/2013,online,1853
51,5/27/2013,museum,873
51,5/27/2013,guestbook,4
52,5/28/2013,online,4106
52,5/28/2013,museum,543
52,5/28/2013,guestbook,7
53,5/29/2013,online,591
53,5/29/2013,museum,894
53,5/29/2013,guestbook,11
54,5/30/2013,online,2938
54,5/30/2013,museum,565
54,5/30/2013,guestbook,4
55,5/31/2013,online,2237
55,5/31/2013,museum,313
55,5/31/2013,guestbook,4
56,6/1/2013,online,3754
56,6/1/2013,museum,622
56,6/1/2013,guestbook,10
57,6/2/2013,online,1529
57,6/2/2013,museum,309
57,6/2/2013,guestbook,2
58,6/3/2013,online,1482
58,6/3/2013,museum,636
58,6/3/2013,guestbook,8
59,6/4/2013,online,1607
59,6/4/2013,museum,655
59,6/4/2013,guestbook,8
60,6/5/2013,online,364
60,6/5/2013,museum,485
60,6/5/2013,guestbook,0
61,6/6/2013,online,555
61,6/6/2013,museum,219
61,6/6/2013,guestbook,3
62,6/7/2013,online,4209
62,6/7/2013,museum,674
62,6/7/2013,guestbook,18
63,6/8/2013,online,4767
63,6/8/2013,museum,824
63,6/8/2013,guestbook,11
64,6/9/2013,online,4788
64,6/9/2013,museum,877
64,6/9/2013,guestbook,2
65,6/10/2013,online,295
65,6/10/2013,museum,873
65,6/10/2013,guestbook,14
66,6/11/2013,online,2057
66,6/11/2013,museum,559
66,6/11/2013,guestbook,13
67,6/12/2013,online,3199
67,6/12/2013,museum,592
67,6/12/2013,guestbook,15
68,6/13/2013,online,2453
68,6/13/2013,museum,907
68,6/13/2013,guestbook,12
69,6/14/2013,online,3688
69,6/14/2013,museum,267
69,6/14/2013,guestbook,12
70,6/15/2013,online,352
70,6/15/2013,museum,389
70,6/15/2013,guestbook,15
71,6/16/2013,online,1583
71,6/16/2013,museum,304
71,6/16/2013,guestbook,7
72,6/17/2013,online,4202
72,6/17/2013,museum,438
72,6/17/2013,guestbook,3
73,6/18/2013,online,2652
73,6/18/2013,museum,392
73,6/18/2013,guestbook,1
74,6/19/2013,online,3988
74,6/19/2013,museum,764
74,6/19/2013,guestbook,17
75,6/20/2013,online,3025
75,6/20/2013,museum,663
75,6/20/2013,guestbook,18
76,6/21/2013,online,4057
76,6/21/2013,museum,266
76,6/21/2013,guestbook,9
77,6/22/2013,online,4853
77,6/22/2013,museum,614
77,6/22/2013,guestbook,15
78,6/23/2013,online,1334
78,6/23/2013,museum,745
78,6/23/2013,guestbook,6
79,6/24/2013,online,4729
79,6/24/2013,museum,506
79,6/24/2013,guestbook,8

Thanks! 谢谢!

In your yDomain definition, you need to return the max of each layer's values, since each layer is a map - it has both a key and an array of values, rather than just a flat array of numbers. yDomain定义中,您需要返回每一层值的最大值,因为每一层都是一个映射-它既有键又有值数组,而不仅仅是平面的数字数组。

var yDomain = d3.max(layers0.concat(layers1), function(layer) { 
    return d3.max(layer.values, //Used to be layer
        function(d) { 
          return d.y0 + d.y; 
        }); 
});

Also, for your stack definition, you need to remove the second offset call.. it negates the "wiggle" one, so you will get a normal stacked graph rather than a streamgraph. 另外,对于您的堆栈定义,您需要删除第二个偏移量调用。它抵消了“摆动”调用,因此您将获得普通的堆栈图而不是流图。

stack = d3.layout.stack().offset("wiggle")  // Used to have .offset("zero") here
      .values(function(d) { return d.values; })

Here's an example with both of those changed : http://jsfiddle.net/G6dTy/3/ . 这是两个示例均已更改的示例: http : //jsfiddle.net/G6dTy/3/ The numbers for the guestbook are small, and are dwarfed by the other two values. 留言簿的数字很小,与其他两个值相比显得相形见war。

It might be informative to take a look at the Stacked area chart example 看一下堆积面积图示例可能会有所帮助

Thanks minikomi! 谢谢minikomi! That was super helpful. 超级有帮助。 The other thing I realized was off was that I wasn't parsing the x & y values into numbers and it was reading them as strings and making the points computation go crazy. 我意识到的另一件事是,我没有将x&y值解析为数字,而是将它们读取为字符串并将点计算变得疯狂。 So when it's iterating through the rows of the CSV file it needs to use parseInt: 因此,在遍历CSV文件的行时,需要使用parseInt:

data.forEach(function(d) {
        d.date = format.parse(d.date);
        d.y = parseInt(d.num_visitors);
        d.x = parseInt(d.index);

    });

Here are my updated files in case anyone wants to use this as an example in the future. 这是我更新的文件,以防将来有人想以此为例。

HTML HTML

<!DOCTYPE html>
<meta charset="utf-8">
<title>Streamgraph</title>
<script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
<style>

body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  margin: 0;
  position: relative;
  width: 1400px;
  background-color: #053749;
}

button {
  position: absolute;
  right: 10px;
  top: 10px;
}
svg{
  margin-top: 450px;
}

</style>
<script src="d3.js"></script>
<body>
  <div id="layerTitle"></div>
</body>
<script>


var format = d3.time.format("%m/%d/%Y");

d3.csv("streamdata.csv", function(error, data) {
        data.forEach(function(d) {
            d.date = format.parse(d.date);
            d.y = parseInt(d.num_visitors) + 1;
            d.x = parseInt(d.index);

        });
        window.data = data;

        drawVisitorStats();
        //$('path').tooltip('{container:layerTitle}');
        $("path").tooltip({
            'container': 'body',
            'placement': 'bottom'
        });


});

function drawVisitorStats(){
    var nest = d3.nest()
           .key(function(d){ return d.venue});
    var n = window.data.length, // number of layers, online, guestbook & museum

    stack = d3.layout.stack().offset("wiggle")
          .values(function(d) { return d.values; });

    //group data by venue
    layers0 = stack(nest.entries(data));

    var m = layers0[0].values.length; // number of samples per layer

    var allValues = layers0[0].values.concat(layers0[1].values).concat(layers0[2].values);

    var yDomain = d3.max(allValues, function(d) { 
      return d.y0 + d.y; 
    });

    var width = 1400,
        height = 200;

    var x = d3.scale.linear()
      .domain([0, m - 1])
      .range([0, width]);

    var y = d3.scale.linear()
    .domain([1, yDomain])
    .range([height, 0]);

    var color = d3.scale.linear()
        .range(["#053749", "#6bb9d6"]);

    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); 
        })
        .interpolate("cardinal")
        .tension(0.6); 

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    svg.selectAll("path")
        .data(layers0)
      .enter().append("path")
        .attr("d", function(d) { return area(d.values); })
        .attr("id", function(d) { 
          return d.key;
        })
        .attr("title", function(d) { 
          return "visitors from " + d.key;
        })
        .style("fill", function() { return color(Math.random()); });
}

</script>
</html>

DATA FILE 资料档

index,date,venue,num_visitors
0,4/8/2013,online,1721
0,4/8/2013,museum,826
0,4/8/2013,guestbook,333
1,4/9/2013,online,1377
1,4/9/2013,museum,840
1,4/9/2013,guestbook,61
2,4/10/2013,online,1849
2,4/10/2013,museum,539
2,4/10/2013,guestbook,191
3,4/11/2013,online,1205
3,4/11/2013,museum,810
3,4/11/2013,guestbook,65
4,4/12/2013,online,1960
4,4/12/2013,museum,957
4,4/12/2013,guestbook,221
5,4/13/2013,online,1215
5,4/13/2013,museum,658
5,4/13/2013,guestbook,384
6,4/14/2013,online,1565
6,4/14/2013,museum,621
6,4/14/2013,guestbook,94
7,4/15/2013,online,1678
7,4/15/2013,museum,710
7,4/15/2013,guestbook,35
8,4/16/2013,online,1267
8,4/16/2013,museum,964
8,4/16/2013,guestbook,8
9,4/17/2013,online,1781
9,4/17/2013,museum,896
9,4/17/2013,guestbook,238
10,4/18/2013,online,1185
10,4/18/2013,museum,712
10,4/18/2013,guestbook,318
11,4/19/2013,online,1097
11,4/19/2013,museum,753
11,4/19/2013,guestbook,132
12,4/20/2013,online,1053
12,4/20/2013,museum,927
12,4/20/2013,guestbook,399
13,4/21/2013,online,1738
13,4/21/2013,museum,653
13,4/21/2013,guestbook,78
14,4/22/2013,online,1491
14,4/22/2013,museum,568
14,4/22/2013,guestbook,72
15,4/23/2013,online,1403
15,4/23/2013,museum,997
15,4/23/2013,guestbook,184
16,4/24/2013,online,1335
16,4/24/2013,museum,987
16,4/24/2013,guestbook,26
17,4/25/2013,online,1964
17,4/25/2013,museum,753
17,4/25/2013,guestbook,239
18,4/26/2013,online,1260
18,4/26/2013,museum,815
18,4/26/2013,guestbook,249
19,4/27/2013,online,1404
19,4/27/2013,museum,817
19,4/27/2013,guestbook,360
20,4/28/2013,online,1790
20,4/28/2013,museum,840
20,4/28/2013,guestbook,163
21,4/29/2013,online,1698
21,4/29/2013,museum,700
21,4/29/2013,guestbook,129
22,4/30/2013,online,1479
22,4/30/2013,museum,921
22,4/30/2013,guestbook,347
23,5/1/2013,online,1093
23,5/1/2013,museum,720
23,5/1/2013,guestbook,278
24,5/2/2013,online,1148
24,5/2/2013,museum,655
24,5/2/2013,guestbook,162
25,5/3/2013,online,1521
25,5/3/2013,museum,806
25,5/3/2013,guestbook,267
26,5/4/2013,online,1365
26,5/4/2013,museum,662
26,5/4/2013,guestbook,232
27,5/5/2013,online,1809
27,5/5/2013,museum,659
27,5/5/2013,guestbook,398
28,5/6/2013,online,1078
28,5/6/2013,museum,999
28,5/6/2013,guestbook,51
29,5/7/2013,online,1477
29,5/7/2013,museum,512
29,5/7/2013,guestbook,385

Just to note, there is a follow-up question here based on the same CSV data but attempting to use transitions. 只是要注意,有一个后续问题在此基础上,同一个CSV数据,但尝试使用过渡。 Similarly the error is related to 'area' but within the transition function. 同样,错误与“区域”有关,但在转换函数内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM